vovk-cli 0.0.1-draft.35 → 0.0.1-draft.350
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.
- package/LICENSE +1 -1
- package/README.md +29 -1
- package/client-templates/cjs/index.cjs.ejs +20 -0
- package/client-templates/cjs/index.d.cts.ejs +22 -0
- package/client-templates/mixins/mixins.d.ts.ejs +64 -0
- package/client-templates/mixins/mixins.json.ejs +1 -0
- package/client-templates/mjs/index.d.mts.ejs +22 -0
- package/client-templates/mjs/index.mjs.ejs +18 -0
- package/client-templates/openapiCjs/openapi.cjs.ejs +4 -0
- package/client-templates/openapiCjs/openapi.d.cts.ejs +4 -0
- package/client-templates/openapiJson/openapi.json.ejs +1 -0
- package/client-templates/openapiTs/openapi.ts.ejs +4 -0
- package/client-templates/packageJson/package.json.ejs +1 -0
- package/client-templates/readme/README.md.ejs +39 -0
- package/client-templates/schemaCjs/schema.cjs.ejs +23 -0
- package/client-templates/schemaCjs/schema.d.cts.ejs +10 -0
- package/client-templates/schemaJson/schema.json.ejs +1 -0
- package/client-templates/schemaTs/schema.ts.ejs +31 -0
- package/client-templates/ts/index.ts.ejs +27 -0
- package/dist/bundle/index.d.mts +8 -0
- package/dist/bundle/index.mjs +102 -0
- package/dist/dev/diffSegmentSchema.d.mts +36 -0
- package/dist/dev/{diffSchema.mjs → diffSegmentSchema.mjs} +3 -11
- package/dist/dev/ensureSchemaFiles.d.mts +4 -1
- package/dist/dev/ensureSchemaFiles.mjs +15 -31
- package/dist/dev/index.d.mts +5 -1
- package/dist/dev/index.mjs +192 -80
- package/dist/dev/logDiffResult.d.mts +1 -1
- package/dist/dev/logDiffResult.mjs +6 -43
- package/dist/dev/writeMetaJson.d.mts +2 -0
- package/dist/dev/writeMetaJson.mjs +20 -0
- package/dist/dev/writeOneSegmentSchemaFile.d.mts +12 -0
- package/dist/dev/{writeOneSchemaFile.mjs → writeOneSegmentSchemaFile.mjs} +10 -6
- package/dist/generate/ensureClient.d.mts +3 -0
- package/dist/generate/ensureClient.mjs +28 -0
- package/dist/generate/generate.d.mts +13 -0
- package/dist/generate/generate.mjs +296 -0
- package/dist/generate/getClientTemplateFiles.d.mts +20 -0
- package/dist/generate/getClientTemplateFiles.mjs +85 -0
- package/dist/generate/getProjectFullSchema.d.mts +8 -0
- package/dist/generate/getProjectFullSchema.mjs +64 -0
- package/dist/generate/getTemplateClientImports.d.mts +19 -0
- package/dist/generate/getTemplateClientImports.mjs +49 -0
- package/dist/generate/index.d.mts +33 -0
- package/dist/generate/index.mjs +190 -0
- package/dist/generate/writeOneClientFile.d.mts +41 -0
- package/dist/generate/writeOneClientFile.mjs +136 -0
- package/dist/getProjectInfo/getConfig/getConfigAbsolutePaths.d.mts +5 -0
- package/dist/getProjectInfo/{getConfigAbsolutePaths.mjs → getConfig/getConfigAbsolutePaths.mjs} +4 -1
- package/dist/getProjectInfo/{getRelativeSrcRoot.d.mts → getConfig/getRelativeSrcRoot.d.mts} +1 -1
- package/dist/getProjectInfo/{getRelativeSrcRoot.mjs → getConfig/getRelativeSrcRoot.mjs} +2 -2
- package/dist/getProjectInfo/getConfig/getTemplateDefs.d.mts +24 -0
- package/dist/getProjectInfo/getConfig/getTemplateDefs.mjs +165 -0
- package/dist/getProjectInfo/{getUserConfig.d.mts → getConfig/getUserConfig.d.mts} +3 -2
- package/dist/getProjectInfo/{getUserConfig.mjs → getConfig/getUserConfig.mjs} +3 -3
- package/dist/getProjectInfo/{importUncachedModule.mjs → getConfig/importUncachedModule.mjs} +1 -4
- package/dist/getProjectInfo/getConfig/index.d.mts +76 -0
- package/dist/getProjectInfo/getConfig/index.mjs +91 -0
- package/dist/getProjectInfo/getMetaSchema.d.mts +8 -0
- package/dist/getProjectInfo/getMetaSchema.mjs +14 -0
- package/dist/getProjectInfo/index.d.mts +14 -9
- package/dist/getProjectInfo/index.mjs +24 -22
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +118 -36
- package/dist/init/createConfig.d.mts +2 -2
- package/dist/init/createConfig.mjs +39 -13
- package/dist/init/createStandardSchemaValidatorFile.d.mts +4 -0
- package/dist/init/createStandardSchemaValidatorFile.mjs +39 -0
- package/dist/init/getTemplateFilesFromPackage.mjs +10 -5
- package/dist/init/index.d.mts +2 -2
- package/dist/init/index.mjs +114 -66
- package/dist/init/installDependencies.mjs +4 -2
- package/dist/init/logUpdateDependenciesError.d.mts +3 -1
- package/dist/init/logUpdateDependenciesError.mjs +7 -1
- package/dist/init/updateDependenciesWithoutInstalling.mjs +39 -9
- package/dist/init/updateNPMScripts.d.mts +3 -1
- package/dist/init/updateNPMScripts.mjs +10 -7
- package/dist/init/updateTypeScriptConfig.d.mts +4 -1
- package/dist/init/updateTypeScriptConfig.mjs +11 -7
- package/dist/initProgram.d.mts +1 -1
- package/dist/initProgram.mjs +17 -17
- package/dist/locateSegments.d.mts +8 -1
- package/dist/locateSegments.mjs +13 -3
- package/dist/new/addClassToSegmentCode.d.mts +1 -2
- package/dist/new/addClassToSegmentCode.mjs +3 -3
- package/dist/new/index.d.mts +2 -1
- package/dist/new/index.mjs +4 -2
- package/dist/new/newModule.d.mts +4 -1
- package/dist/new/newModule.mjs +18 -17
- package/dist/new/newSegment.d.mts +4 -1
- package/dist/new/newSegment.mjs +19 -11
- package/dist/new/render.d.mts +7 -3
- package/dist/new/render.mjs +29 -8
- package/dist/types.d.mts +64 -42
- package/dist/utils/compileJSONSchemaToTypeScriptType.d.mts +5 -0
- package/dist/utils/compileJSONSchemaToTypeScriptType.mjs +9 -0
- package/dist/utils/compileTs.d.mts +12 -0
- package/dist/utils/compileTs.mjs +261 -0
- package/dist/utils/debounceWithArgs.d.mts +2 -2
- package/dist/utils/debounceWithArgs.mjs +24 -6
- package/dist/utils/formatLoggedSegmentName.d.mts +3 -1
- package/dist/utils/formatLoggedSegmentName.mjs +3 -2
- package/dist/utils/generateFnName.d.mts +23 -0
- package/dist/utils/generateFnName.mjs +76 -0
- package/dist/utils/getPackageJson.d.mts +3 -0
- package/dist/utils/getPackageJson.mjs +22 -0
- package/dist/utils/getPublicModuleNameFromPath.d.mts +4 -0
- package/dist/utils/getPublicModuleNameFromPath.mjs +9 -0
- package/dist/utils/normalizeOpenAPIMixin.d.mts +14 -0
- package/dist/utils/normalizeOpenAPIMixin.mjs +114 -0
- package/dist/utils/pickSegmentFullSchema.d.mts +3 -0
- package/dist/utils/pickSegmentFullSchema.mjs +15 -0
- package/dist/utils/removeUnlistedDirectories.d.mts +10 -0
- package/dist/utils/removeUnlistedDirectories.mjs +61 -0
- package/dist/utils/resolveAbsoluteModulePath.d.mts +2 -0
- package/dist/utils/resolveAbsoluteModulePath.mjs +32 -0
- package/module-templates/arktype/controller.ts.ejs +68 -0
- package/module-templates/type/controller.ts.ejs +56 -0
- package/module-templates/type/service.ts.ejs +28 -0
- package/module-templates/valibot/controller.ts.ejs +68 -0
- package/package.json +35 -22
- package/dist/dev/diffSchema.d.mts +0 -43
- package/dist/dev/ensureClient.d.mts +0 -5
- package/dist/dev/ensureClient.mjs +0 -31
- package/dist/dev/isMetadataEmpty.d.mts +0 -2
- package/dist/dev/isMetadataEmpty.mjs +0 -4
- package/dist/dev/writeOneSchemaFile.d.mts +0 -11
- package/dist/generateClient.d.mts +0 -7
- package/dist/generateClient.mjs +0 -97
- package/dist/getProjectInfo/getConfig.d.mts +0 -11
- package/dist/getProjectInfo/getConfig.mjs +0 -29
- package/dist/getProjectInfo/getConfigAbsolutePaths.d.mts +0 -4
- package/dist/postinstall.d.mts +0 -1
- package/dist/postinstall.mjs +0 -24
- package/templates/controller.ejs +0 -52
- package/templates/service.ejs +0 -27
- package/templates/worker.ejs +0 -24
- /package/dist/getProjectInfo/{importUncachedModule.d.mts → getConfig/importUncachedModule.d.mts} +0 -0
- /package/dist/getProjectInfo/{importUncachedModuleWorker.d.mts → getConfig/importUncachedModuleWorker.d.mts} +0 -0
- /package/dist/getProjectInfo/{importUncachedModuleWorker.mjs → getConfig/importUncachedModuleWorker.mjs} +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import getFileSystemEntryType, { FileSystemEntryType } from './getFileSystemEntryType.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* Removes all directories in a folder that aren't in the provided allowlist
|
|
6
|
+
* Supports nested directory paths like 'foo/bar/baz'
|
|
7
|
+
*
|
|
8
|
+
* @param folderPath - The path to the folder to process
|
|
9
|
+
* @param allowedDirs - Array of relative directory paths to keep
|
|
10
|
+
* @returns Promise that resolves when all operations are complete
|
|
11
|
+
*/
|
|
12
|
+
async function removeUnlistedDirectories(folderPath, allowedDirs) {
|
|
13
|
+
// Normalize all allowed paths to use the system-specific separator
|
|
14
|
+
const normalizedAllowedDirs = allowedDirs.map((dir) => dir.split('/').join(path.sep));
|
|
15
|
+
// Process the directory tree recursively
|
|
16
|
+
await processDirectory(folderPath, '', normalizedAllowedDirs);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Recursively processes directories to determine which should be kept or removed
|
|
20
|
+
*
|
|
21
|
+
* @param basePath - The absolute base path being processed
|
|
22
|
+
* @param relativePath - The current relative path from the base
|
|
23
|
+
* @param allowedDirs - Normalized list of allowed directory paths
|
|
24
|
+
*/
|
|
25
|
+
async function processDirectory(basePath, relativePath, allowedDirs) {
|
|
26
|
+
const currentDirPath = path.join(basePath, relativePath);
|
|
27
|
+
// check if the current path is a directory
|
|
28
|
+
const type = await getFileSystemEntryType(currentDirPath);
|
|
29
|
+
if (type !== FileSystemEntryType.DIRECTORY) {
|
|
30
|
+
// If it's not a directory, return early
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Read all entries in the current directory
|
|
34
|
+
const entries = await fs.readdir(currentDirPath, { withFileTypes: true });
|
|
35
|
+
// Process only directories
|
|
36
|
+
const dirEntries = entries.filter((entry) => entry.isDirectory());
|
|
37
|
+
// Check each directory
|
|
38
|
+
for (const dir of dirEntries) {
|
|
39
|
+
// Calculate the new relative path
|
|
40
|
+
const newRelativePath = relativePath ? path.join(relativePath, dir.name) : dir.name;
|
|
41
|
+
// Check if this directory or any of its subdirectories should be kept
|
|
42
|
+
const shouldKeep = allowedDirs.some((allowedDir) => {
|
|
43
|
+
// Direct match
|
|
44
|
+
if (allowedDir === newRelativePath)
|
|
45
|
+
return true;
|
|
46
|
+
// Check if it's a parent path of an allowed directory
|
|
47
|
+
// e.g. "foo" is a parent of "foo/bar/baz"
|
|
48
|
+
return allowedDir.startsWith(newRelativePath + path.sep);
|
|
49
|
+
});
|
|
50
|
+
if (shouldKeep) {
|
|
51
|
+
// Recursively process this directory's contents
|
|
52
|
+
await processDirectory(basePath, newRelativePath, allowedDirs);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Remove this directory since it's not in the allowed list
|
|
56
|
+
const fullPath = path.join(basePath, newRelativePath);
|
|
57
|
+
await fs.rm(fullPath, { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export default removeUnlistedDirectories;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import getPublicModuleNameFromPath from './getPublicModuleNameFromPath.mjs';
|
|
4
|
+
// Returns the path up to and including the last occurrence of the given module name
|
|
5
|
+
export function getPathUpToModule(moduleName, fullPath) {
|
|
6
|
+
const idx = fullPath.lastIndexOf(moduleName);
|
|
7
|
+
if (idx === -1)
|
|
8
|
+
return moduleName;
|
|
9
|
+
return fullPath.slice(0, idx + moduleName.length);
|
|
10
|
+
}
|
|
11
|
+
export default function resolveAbsoluteModulePath(modulePath, cwd) {
|
|
12
|
+
// If it's an absolute path or starts with '.' (relative), resolve it directly
|
|
13
|
+
if (modulePath.startsWith('/') || modulePath.startsWith('.')) {
|
|
14
|
+
return path.resolve(cwd, modulePath);
|
|
15
|
+
}
|
|
16
|
+
// For npm package names, use Node's module resolution algorithm
|
|
17
|
+
try {
|
|
18
|
+
const { moduleName, restPath } = getPublicModuleNameFromPath(modulePath);
|
|
19
|
+
if (!moduleName) {
|
|
20
|
+
throw new Error(`Invalid module path: ${modulePath}`);
|
|
21
|
+
}
|
|
22
|
+
const require = createRequire(import.meta.url);
|
|
23
|
+
const resolved = require.resolve(moduleName);
|
|
24
|
+
return path.resolve(getPathUpToModule(moduleName, path.dirname(resolved)), restPath);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
// eslint-disable-next-line no-console
|
|
28
|
+
console.error(`Error resolving module path: ${modulePath}`, e);
|
|
29
|
+
// If resolution fails, fall back to the original behavior
|
|
30
|
+
return path.resolve(cwd, './node_modules', modulePath);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<% const vars = {
|
|
2
|
+
ModuleName: t.TheThing + 'Controller',
|
|
3
|
+
ServiceName: t.TheThing + 'Service',
|
|
4
|
+
}; %>
|
|
5
|
+
---
|
|
6
|
+
dir: <%= t.defaultDir %>
|
|
7
|
+
fileName: <%= vars.ModuleName + '.ts' %>
|
|
8
|
+
sourceName: <%= vars.ModuleName %>
|
|
9
|
+
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
import { prefix, get, put, post, del, operation } from 'vovk';
|
|
13
|
+
import { type } from 'arktype';
|
|
14
|
+
import withArk from '@/lib/withArk<%= t.nodeNextResolutionExt.ts %>';
|
|
15
|
+
<% if(t.withService) { %>
|
|
16
|
+
import <%= vars.ServiceName %> from './<%= vars.ServiceName %><%= t.nodeNextResolutionExt.ts %>';
|
|
17
|
+
<% } %>
|
|
18
|
+
|
|
19
|
+
@prefix('<%= t['the-things'] %>')
|
|
20
|
+
export default class <%= vars.ModuleName %> {
|
|
21
|
+
@operation({
|
|
22
|
+
summary: 'Get <%= t.TheThings %>',
|
|
23
|
+
})
|
|
24
|
+
@get()
|
|
25
|
+
static get<%= t.TheThings %> = withArk({
|
|
26
|
+
query: type({ search: type('string') }),
|
|
27
|
+
handle(req) {
|
|
28
|
+
const search = req.nextUrl.searchParams.get('search');
|
|
29
|
+
<% if(t.withService) { %>
|
|
30
|
+
return <%= vars.ServiceName %>.get<%= t.TheThings %>(search);
|
|
31
|
+
<% } else { %>
|
|
32
|
+
return { results: [], search };
|
|
33
|
+
<% } %>
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
@operation({
|
|
38
|
+
summary: 'Update <%= t.TheThing %>',
|
|
39
|
+
})
|
|
40
|
+
@put('{id}')
|
|
41
|
+
static update<%= t.TheThing %> = withArk({
|
|
42
|
+
body: type({
|
|
43
|
+
foo: type('"bar" | "baz"'),
|
|
44
|
+
}),
|
|
45
|
+
query: type({ q: type('string') }),
|
|
46
|
+
params: type({ id: type('string') }),
|
|
47
|
+
async handle(req, params) {
|
|
48
|
+
const { id } = params;
|
|
49
|
+
const body = await req.json();
|
|
50
|
+
const q = req.nextUrl.searchParams.get('q');
|
|
51
|
+
<% if(t.withService) { %>
|
|
52
|
+
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id, q, body);
|
|
53
|
+
<% } else { %>
|
|
54
|
+
return { id, body, q };
|
|
55
|
+
<% } %>
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
@post()
|
|
60
|
+
static create<%= t.TheThing %> = () => {
|
|
61
|
+
// ...
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
@del(':id')
|
|
65
|
+
static delete<%= t.TheThing %> = () => {
|
|
66
|
+
// ...
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<% const vars = {
|
|
2
|
+
rpcModuleName: t.TheThing + 'Controller',
|
|
3
|
+
ServiceName: t.TheThing + 'Service',
|
|
4
|
+
}; %>
|
|
5
|
+
---
|
|
6
|
+
dir: <%= t.defaultDir %>
|
|
7
|
+
fileName: <%= vars.rpcModuleName + '.ts' %>
|
|
8
|
+
sourceName: <%= vars.rpcModuleName %>
|
|
9
|
+
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
import { prefix, get, put, post, del, operation, type VovkRequest } from 'vovk';
|
|
13
|
+
<% if(t.withService) { %>
|
|
14
|
+
import <%= vars.ServiceName %> from './<%= vars.ServiceName %><%= t.nodeNextResolutionExt.ts %>';
|
|
15
|
+
<% } %>
|
|
16
|
+
|
|
17
|
+
@prefix('<%= t['the-things'] %>')
|
|
18
|
+
export default class <%= vars.rpcModuleName %> {
|
|
19
|
+
@operation({
|
|
20
|
+
summary: 'Get <%= t.TheThings %>',
|
|
21
|
+
})
|
|
22
|
+
@get()
|
|
23
|
+
static get<%= t.TheThings %> = async (req: VovkRequest<null, { search: string }>) => {
|
|
24
|
+
const search = req.nextUrl.searchParams.get('search');
|
|
25
|
+
<% if(t.withService) { %>
|
|
26
|
+
return <%= vars.ServiceName %>.get<%= t.TheThings %>(search);
|
|
27
|
+
<% } else { %>
|
|
28
|
+
return { results: [], search };
|
|
29
|
+
<% } %>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@operation({
|
|
33
|
+
summary: 'Update <%= t.TheThing %>',
|
|
34
|
+
})
|
|
35
|
+
@put('{id}')
|
|
36
|
+
static update<%= t.TheThing %> = async (req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>, params: { id: string }) => {
|
|
37
|
+
const { id } = params;
|
|
38
|
+
const body = await req.json();
|
|
39
|
+
const q = req.nextUrl.searchParams.get('q');
|
|
40
|
+
<% if(t.withService) { %>
|
|
41
|
+
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id, q, body);
|
|
42
|
+
<% } else { %>
|
|
43
|
+
return { id, body, q };
|
|
44
|
+
<% } %>
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
@post()
|
|
48
|
+
static create<%= t.TheThing %> = () => {
|
|
49
|
+
// ...
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
@del(':id')
|
|
53
|
+
static delete<%= t.TheThing %> = () => {
|
|
54
|
+
// ...
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<% const vars = {
|
|
2
|
+
rpcModuleName: t.TheThing + 'Controller',
|
|
3
|
+
ServiceName: t.TheThing + 'Service',
|
|
4
|
+
}; %>
|
|
5
|
+
---
|
|
6
|
+
dir: <%= t.defaultDir %>
|
|
7
|
+
fileName: <%= vars.ServiceName + '.ts' %>
|
|
8
|
+
sourceName: <%= vars.ServiceName %>
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
import type { VovkBody, VovkQuery } from 'vovk';
|
|
12
|
+
import type <%= vars.rpcModuleName %> from './<%= vars.rpcModuleName %><%= t.nodeNextResolutionExt.ts %>';
|
|
13
|
+
|
|
14
|
+
export default class <%= vars.ServiceName %> {
|
|
15
|
+
static get<%= t.TheThings %> = (search: VovkQuery<typeof <%= vars.rpcModuleName %>.get<%= t.TheThings %>>['search']) => {
|
|
16
|
+
return { results: [], search };
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
static update<%= t.TheThing %> = (
|
|
20
|
+
id: string,
|
|
21
|
+
q: VovkQuery<typeof <%= vars.rpcModuleName %>.update<%= t.TheThing %>>['q'],
|
|
22
|
+
body: VovkBody<typeof <%= vars.rpcModuleName %>.update<%= t.TheThing %>>
|
|
23
|
+
) => {
|
|
24
|
+
return { id, q, body };
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// ...
|
|
28
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<% const vars = {
|
|
2
|
+
ModuleName: t.TheThing + 'Controller',
|
|
3
|
+
ServiceName: t.TheThing + 'Service',
|
|
4
|
+
}; %>
|
|
5
|
+
---
|
|
6
|
+
dir: <%= t.defaultDir %>
|
|
7
|
+
fileName: <%= vars.ModuleName + '.ts' %>
|
|
8
|
+
sourceName: <%= vars.ModuleName %>
|
|
9
|
+
compiledName: <%= t.TheThing + 'RPC' %>
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
import { prefix, get, put, post, del, operation } from 'vovk';
|
|
13
|
+
import * as v from 'valibot';
|
|
14
|
+
import withValibot from '@/lib/withValibot<%= t.nodeNextResolutionExt.ts %>';
|
|
15
|
+
<% if(t.withService) { %>
|
|
16
|
+
import <%= vars.ServiceName %> from './<%= vars.ServiceName %><%= t.nodeNextResolutionExt.ts %>';
|
|
17
|
+
<% } %>
|
|
18
|
+
|
|
19
|
+
@prefix('<%= t['the-things'] %>')
|
|
20
|
+
export default class <%= vars.ModuleName %> {
|
|
21
|
+
@operation({
|
|
22
|
+
summary: 'Get <%= t.TheThings %>',
|
|
23
|
+
})
|
|
24
|
+
@get()
|
|
25
|
+
static get<%= t.TheThings %> = withValibot({
|
|
26
|
+
query: v.object({ search: v.string() }),
|
|
27
|
+
handle(req) {
|
|
28
|
+
const search = req.nextUrl.searchParams.get('search');
|
|
29
|
+
<% if(t.withService) { %>
|
|
30
|
+
return <%= vars.ServiceName %>.get<%= t.TheThings %>(search);
|
|
31
|
+
<% } else { %>
|
|
32
|
+
return { results: [], search };
|
|
33
|
+
<% } %>
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
@operation({
|
|
38
|
+
summary: 'Update <%= t.TheThing %>',
|
|
39
|
+
})
|
|
40
|
+
@put('{id}')
|
|
41
|
+
static update<%= t.TheThing %> = withValibot({
|
|
42
|
+
body: v.object({
|
|
43
|
+
foo: v.union([v.literal('bar'), v.literal('baz')]),
|
|
44
|
+
}),
|
|
45
|
+
query: v.object({ q: v.string() }),
|
|
46
|
+
params: v.object({ id: v.string() }),
|
|
47
|
+
async handle(req, params) {
|
|
48
|
+
const { id } = params;
|
|
49
|
+
const body = await req.json();
|
|
50
|
+
const q = req.nextUrl.searchParams.get('q');
|
|
51
|
+
<% if(t.withService) { %>
|
|
52
|
+
return <%= vars.ServiceName %>.update<%= t.TheThing %>(id, q, body);
|
|
53
|
+
<% } else { %>
|
|
54
|
+
return { id, body, q };
|
|
55
|
+
<% } %>
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
@post()
|
|
60
|
+
static create<%= t.TheThing %> = () => {
|
|
61
|
+
// ...
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
@del(':id')
|
|
65
|
+
static delete<%= t.TheThing %> = () => {
|
|
66
|
+
// ...
|
|
67
|
+
};
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vovk-cli",
|
|
3
|
-
"version": "0.0.1-draft.
|
|
3
|
+
"version": "0.0.1-draft.350",
|
|
4
4
|
"bin": {
|
|
5
5
|
"vovk": "./dist/index.mjs"
|
|
6
6
|
},
|
|
@@ -11,12 +11,11 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "rm -rf dist tsconfig.build.tsbuildinfo && tsc -P tsconfig.build.json",
|
|
13
13
|
"postbuild": "chmod +x ./dist/index.mjs",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"test
|
|
17
|
-
"test": "npm run pre-test && node --test --test-concurrency=1 test_dist/test/**/*.mjs",
|
|
14
|
+
"pre-test": "npm run build",
|
|
15
|
+
"test-only": "npm run pre-test && node --experimental-transform-types --experimental-strip-types --test --test-only test/spec/**/*.mts",
|
|
16
|
+
"test": "npm run pre-test && node --experimental-transform-types --experimental-strip-types --test --test-concurrency=1 test/spec/**/*.mts",
|
|
18
17
|
"tsc": "tsc --noEmit",
|
|
19
|
-
"ncu": "npm-check-updates -u",
|
|
18
|
+
"ncu": "npm-check-updates -u -x commander",
|
|
20
19
|
"npm-publish": "npm publish"
|
|
21
20
|
},
|
|
22
21
|
"repository": {
|
|
@@ -29,44 +28,58 @@
|
|
|
29
28
|
"cli",
|
|
30
29
|
"vovk"
|
|
31
30
|
],
|
|
32
|
-
"author": "
|
|
31
|
+
"author": "Andrey Gubanov",
|
|
33
32
|
"license": "MIT",
|
|
34
33
|
"bugs": {
|
|
35
34
|
"url": "https://github.com/finom/vovk/issues"
|
|
36
35
|
},
|
|
37
36
|
"homepage": "https://vovk.dev",
|
|
38
37
|
"peerDependencies": {
|
|
39
|
-
"vovk": "^3.0.0-draft.
|
|
38
|
+
"vovk": "^3.0.0-draft.411"
|
|
39
|
+
},
|
|
40
|
+
"optionalDependencies": {
|
|
41
|
+
"@rolldown/binding-linux-x64-gnu": "1.0.0-beta.31"
|
|
40
42
|
},
|
|
41
43
|
"dependencies": {
|
|
42
|
-
"@
|
|
43
|
-
"@
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
44
|
+
"@iarna/toml": "^2.2.5",
|
|
45
|
+
"@inquirer/prompts": "^7.7.1",
|
|
46
|
+
"@npmcli/package-json": "^6.2.0",
|
|
47
|
+
"@types/json-schema": "^7.0.15",
|
|
48
|
+
"chalk": "^5.4.1",
|
|
49
|
+
"chokidar": "^4.0.3",
|
|
50
|
+
"clone-deep": "^4.0.1",
|
|
51
|
+
"commander": "^13.1.0",
|
|
52
|
+
"concurrently": "^9.2.0",
|
|
53
|
+
"dotenv": "^17.2.1",
|
|
49
54
|
"ejs": "^3.1.10",
|
|
55
|
+
"get-tsconfig": "^4.10.1",
|
|
56
|
+
"glob": "^11.0.3",
|
|
50
57
|
"gray-matter": "^4.0.3",
|
|
51
|
-
"inflection": "^3.0.
|
|
58
|
+
"inflection": "^3.0.2",
|
|
52
59
|
"jsonc-parser": "^3.3.1",
|
|
53
60
|
"lodash": "^4.17.21",
|
|
54
61
|
"loglevel": "^1.9.2",
|
|
62
|
+
"openapi3-ts": "^4.5.0",
|
|
55
63
|
"pluralize": "^8.0.0",
|
|
56
|
-
"prettier": "^3.
|
|
64
|
+
"prettier": "^3.6.2",
|
|
57
65
|
"tar-stream": "^3.1.7",
|
|
58
|
-
"ts-morph": "^
|
|
59
|
-
"
|
|
66
|
+
"ts-morph": "^26.0.0",
|
|
67
|
+
"tsdown": "^0.13.0",
|
|
68
|
+
"type-fest": "^4.41.0",
|
|
69
|
+
"undici": "^7.12.0",
|
|
70
|
+
"vovk-openapi": "^0.0.1-draft.112",
|
|
71
|
+
"yaml": "^2.8.0"
|
|
60
72
|
},
|
|
61
73
|
"devDependencies": {
|
|
62
74
|
"@types/concat-stream": "^2.0.3",
|
|
63
75
|
"@types/ejs": "^3.1.5",
|
|
76
|
+
"@types/js-yaml": "^4.0.9",
|
|
64
77
|
"@types/npmcli__package-json": "^4.0.4",
|
|
65
78
|
"@types/pluralize": "^0.0.33",
|
|
66
|
-
"@types/tar-stream": "^3.1.
|
|
79
|
+
"@types/tar-stream": "^3.1.4",
|
|
67
80
|
"concat-stream": "^2.0.0",
|
|
68
|
-
"create-next-app": "^15.
|
|
81
|
+
"create-next-app": "^15.4.4",
|
|
69
82
|
"node-pty": "^1.0.0",
|
|
70
|
-
"
|
|
83
|
+
"zod": "^4.0.10"
|
|
71
84
|
}
|
|
72
85
|
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { VovkSchema } from 'vovk';
|
|
2
|
-
import type { _VovkControllerSchema, _VovkWorkerSchema } from 'vovk/types';
|
|
3
|
-
interface HandlersDiff {
|
|
4
|
-
nameOfClass: string;
|
|
5
|
-
added: string[];
|
|
6
|
-
removed: string[];
|
|
7
|
-
changed: string[];
|
|
8
|
-
}
|
|
9
|
-
interface WorkersOrControllersDiff {
|
|
10
|
-
added: string[];
|
|
11
|
-
removed: string[];
|
|
12
|
-
handlers: HandlersDiff[];
|
|
13
|
-
}
|
|
14
|
-
export interface DiffResult {
|
|
15
|
-
workers: WorkersOrControllersDiff;
|
|
16
|
-
controllers: WorkersOrControllersDiff;
|
|
17
|
-
}
|
|
18
|
-
export declare function diffHandlers<T extends _VovkWorkerSchema['handlers'] | _VovkControllerSchema['handlers']>(oldHandlers: T, newHandlers: T, nameOfClass: string): HandlersDiff;
|
|
19
|
-
export declare function diffWorkersOrControllers<T extends VovkSchema['controllers'] | VovkSchema['workers']>(oldItems: T, newItems: T): WorkersOrControllersDiff;
|
|
20
|
-
/**
|
|
21
|
-
example output:
|
|
22
|
-
{
|
|
23
|
-
workers: {
|
|
24
|
-
added: ["WorkerC"],
|
|
25
|
-
removed: ["WorkerA"],
|
|
26
|
-
handlers: []
|
|
27
|
-
},
|
|
28
|
-
controllers: {
|
|
29
|
-
added: ["ControllerC"],
|
|
30
|
-
removed: ["ControllerB"],
|
|
31
|
-
handlers: [
|
|
32
|
-
{
|
|
33
|
-
nameOfClass: "ControllerA",
|
|
34
|
-
added: ["handlerF"],
|
|
35
|
-
removed: [],
|
|
36
|
-
changed: ["handlerD"]
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
*/
|
|
42
|
-
export default function diffSchema(oldJson: VovkSchema, newJson: VovkSchema): DiffResult;
|
|
43
|
-
export {};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import fs from 'node:fs/promises';
|
|
3
|
-
export default async function ensureClient(projectInfo) {
|
|
4
|
-
const { config, cwd, log } = projectInfo;
|
|
5
|
-
const now = Date.now();
|
|
6
|
-
const clientoOutDirAbsolutePath = path.join(cwd, config.clientOutDir);
|
|
7
|
-
const dts = `// auto-generated
|
|
8
|
-
// This is a temporary placeholder to avoid errors if client is imported before it's generated.
|
|
9
|
-
// If you still see this text, the client is not generated yet because of an unknown problem.
|
|
10
|
-
// Feel free to report an issue at https://github.com/finom/vovk/issues`;
|
|
11
|
-
const js = dts;
|
|
12
|
-
const ts = dts;
|
|
13
|
-
const localJsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'client.js');
|
|
14
|
-
const localDtsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'client.d.ts');
|
|
15
|
-
const localTsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'index.ts');
|
|
16
|
-
const existingJs = await fs.readFile(localJsAbsolutePath, 'utf-8').catch(() => null);
|
|
17
|
-
const existingDts = await fs.readFile(localDtsAbsolutePath, 'utf-8').catch(() => null);
|
|
18
|
-
const existingTs = await fs.readFile(localTsAbsolutePath, 'utf-8').catch(() => null);
|
|
19
|
-
if (existingJs && existingDts && existingTs) {
|
|
20
|
-
return { written: false, path: clientoOutDirAbsolutePath };
|
|
21
|
-
}
|
|
22
|
-
await fs.mkdir(clientoOutDirAbsolutePath, { recursive: true });
|
|
23
|
-
if (!existingJs)
|
|
24
|
-
await fs.writeFile(localJsAbsolutePath, js);
|
|
25
|
-
if (!existingDts)
|
|
26
|
-
await fs.writeFile(localDtsAbsolutePath, dts);
|
|
27
|
-
if (!existingTs)
|
|
28
|
-
await fs.writeFile(localTsAbsolutePath, ts);
|
|
29
|
-
log.info(`Empty client files are generated in ${Date.now() - now}ms`);
|
|
30
|
-
return { written: true, path: clientoOutDirAbsolutePath };
|
|
31
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { VovkSchema } from 'vovk';
|
|
2
|
-
import { type DiffResult } from './diffSchema.mjs';
|
|
3
|
-
export declare const ROOT_SEGMENT_SCHEMA_NAME = "_root";
|
|
4
|
-
export default function writeOneSchemaFile({ schemaOutAbsolutePath, schema, skipIfExists, }: {
|
|
5
|
-
schemaOutAbsolutePath: string;
|
|
6
|
-
schema: VovkSchema;
|
|
7
|
-
skipIfExists?: boolean;
|
|
8
|
-
}): Promise<{
|
|
9
|
-
isCreated: boolean;
|
|
10
|
-
diffResult: DiffResult | null;
|
|
11
|
-
}>;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { VovkSchema } from 'vovk';
|
|
2
|
-
import type { ProjectInfo } from './getProjectInfo/index.mjs';
|
|
3
|
-
import type { Segment } from './locateSegments.mjs';
|
|
4
|
-
export default function generateClient(projectInfo: ProjectInfo, segments: Segment[], segmentsSchema: Record<string, VovkSchema>): Promise<{
|
|
5
|
-
written: boolean;
|
|
6
|
-
path: string;
|
|
7
|
-
}>;
|
package/dist/generateClient.mjs
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import fs from 'node:fs/promises';
|
|
3
|
-
import formatLoggedSegmentName from './utils/formatLoggedSegmentName.mjs';
|
|
4
|
-
import prettify from './utils/prettify.mjs';
|
|
5
|
-
export default async function generateClient(projectInfo, segments, segmentsSchema) {
|
|
6
|
-
const { config, cwd, log, validateOnClientImportPath, apiEntryPoint, fetcherClientImportPath, schemaOutImportPath } = projectInfo;
|
|
7
|
-
const now = Date.now();
|
|
8
|
-
const clientoOutDirAbsolutePath = path.join(cwd, config.clientOutDir);
|
|
9
|
-
let dts = `// auto-generated
|
|
10
|
-
/* eslint-disable */
|
|
11
|
-
import type { clientizeController } from 'vovk/client';
|
|
12
|
-
import type { promisifyWorker } from 'vovk/worker';
|
|
13
|
-
import type { VovkClientFetcher } from 'vovk/client';
|
|
14
|
-
import type fetcher from '${fetcherClientImportPath}';
|
|
15
|
-
|
|
16
|
-
`;
|
|
17
|
-
let js = `// auto-generated
|
|
18
|
-
/* eslint-disable */
|
|
19
|
-
const { clientizeController } = require('vovk/client');
|
|
20
|
-
const { promisifyWorker } = require('vovk/worker');
|
|
21
|
-
const { default: fetcher } = require('${fetcherClientImportPath}');
|
|
22
|
-
const schema = require('${schemaOutImportPath}');
|
|
23
|
-
`;
|
|
24
|
-
let ts = `// auto-generated
|
|
25
|
-
/* eslint-disable */
|
|
26
|
-
import { clientizeController } from 'vovk/client';
|
|
27
|
-
import { promisifyWorker } from 'vovk/worker';
|
|
28
|
-
import type { VovkClientFetcher } from 'vovk/client';
|
|
29
|
-
import fetcher from '${fetcherClientImportPath}';
|
|
30
|
-
import schema from '${schemaOutImportPath}';
|
|
31
|
-
|
|
32
|
-
`;
|
|
33
|
-
for (let i = 0; i < segments.length; i++) {
|
|
34
|
-
const { routeFilePath, segmentName } = segments[i];
|
|
35
|
-
const schema = segmentsSchema[segmentName];
|
|
36
|
-
if (!schema) {
|
|
37
|
-
throw new Error(`Unable to generate client. No schema found for ${formatLoggedSegmentName(segmentName)}`);
|
|
38
|
-
}
|
|
39
|
-
if (!schema.emitSchema)
|
|
40
|
-
continue;
|
|
41
|
-
const importRouteFilePath = path.relative(config.clientOutDir, routeFilePath);
|
|
42
|
-
dts += `import type { Controllers as Controllers${i}, Workers as Workers${i} } from "${importRouteFilePath}";\n`;
|
|
43
|
-
ts += `import type { Controllers as Controllers${i}, Workers as Workers${i} } from "${importRouteFilePath}";\n`;
|
|
44
|
-
}
|
|
45
|
-
dts += `
|
|
46
|
-
type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
47
|
-
`;
|
|
48
|
-
ts += `
|
|
49
|
-
${validateOnClientImportPath ? `import validateOnClient from '${validateOnClientImportPath}';\n` : '\nconst validateOnClient = undefined;'}
|
|
50
|
-
type Options = typeof fetcher extends VovkClientFetcher<infer U> ? U : never;
|
|
51
|
-
const apiRoot = '${apiEntryPoint}';
|
|
52
|
-
`;
|
|
53
|
-
js += `
|
|
54
|
-
const { default: validateOnClient = null } = ${validateOnClientImportPath ? `require('${validateOnClientImportPath}')` : '{}'};
|
|
55
|
-
const apiRoot = '${apiEntryPoint}';
|
|
56
|
-
`;
|
|
57
|
-
for (let i = 0; i < segments.length; i++) {
|
|
58
|
-
const { segmentName } = segments[i];
|
|
59
|
-
const schema = segmentsSchema[segmentName];
|
|
60
|
-
if (!schema) {
|
|
61
|
-
throw new Error(`Unable to generate client. No schema found for ${formatLoggedSegmentName(segmentName)}`);
|
|
62
|
-
}
|
|
63
|
-
if (!schema.emitSchema)
|
|
64
|
-
continue;
|
|
65
|
-
for (const key of Object.keys(schema.controllers)) {
|
|
66
|
-
dts += `export const ${key}: ReturnType<typeof clientizeController<Controllers${i}["${key}"], Options>>;\n`;
|
|
67
|
-
js += `exports.${key} = clientizeController(schema['${segmentName}'].controllers.${key}, '${segmentName}', { fetcher, validateOnClient, defaultOptions: { apiRoot } });\n`;
|
|
68
|
-
ts += `export const ${key} = clientizeController<Controllers${i}["${key}"], Options>(schema['${segmentName}'].controllers.${key}, '${segmentName}', { fetcher, validateOnClient, defaultOptions: { apiRoot } });\n`;
|
|
69
|
-
}
|
|
70
|
-
for (const key of Object.keys(schema.workers)) {
|
|
71
|
-
dts += `export const ${key}: ReturnType<typeof promisifyWorker<Workers${i}["${key}"]>>;\n`;
|
|
72
|
-
js += `exports.${key} = promisifyWorker(null, schema['${segmentName}'].workers.${key});\n`;
|
|
73
|
-
ts += `export const ${key} = promisifyWorker<Workers${i}["${key}"]>(null, schema['${segmentName}'].workers.${key});\n`;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
const localJsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'client.js');
|
|
77
|
-
const localDtsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'client.d.ts');
|
|
78
|
-
const localTsAbsolutePath = path.join(clientoOutDirAbsolutePath, 'index.ts');
|
|
79
|
-
const existingJs = await fs.readFile(localJsAbsolutePath, 'utf-8').catch(() => '');
|
|
80
|
-
const existingDts = await fs.readFile(localDtsAbsolutePath, 'utf-8').catch(() => '');
|
|
81
|
-
const existingTs = await fs.readFile(localTsAbsolutePath, 'utf-8').catch(() => '');
|
|
82
|
-
if (config.prettifyClient) {
|
|
83
|
-
js = await prettify(js, localJsAbsolutePath);
|
|
84
|
-
dts = await prettify(dts, localDtsAbsolutePath);
|
|
85
|
-
ts = await prettify(ts, localTsAbsolutePath);
|
|
86
|
-
}
|
|
87
|
-
if (existingJs === js && existingDts === dts && existingTs === ts) {
|
|
88
|
-
log.debug(`Client is up to date and doesn't need to be regenerated (${Date.now() - now}ms)`);
|
|
89
|
-
return { written: false, path: clientoOutDirAbsolutePath };
|
|
90
|
-
}
|
|
91
|
-
await fs.mkdir(clientoOutDirAbsolutePath, { recursive: true });
|
|
92
|
-
await fs.writeFile(localJsAbsolutePath, js);
|
|
93
|
-
await fs.writeFile(localDtsAbsolutePath, dts);
|
|
94
|
-
await fs.writeFile(localTsAbsolutePath, ts);
|
|
95
|
-
log.info(`Client generated in ${Date.now() - now}ms`);
|
|
96
|
-
return { written: true, path: clientoOutDirAbsolutePath };
|
|
97
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { VovkConfig } from '../types.mjs';
|
|
2
|
-
export default function getConfig({ clientOutDir, cwd }: {
|
|
3
|
-
clientOutDir?: string;
|
|
4
|
-
cwd: string;
|
|
5
|
-
}): Promise<{
|
|
6
|
-
config: Required<VovkConfig>;
|
|
7
|
-
srcRoot: string;
|
|
8
|
-
configAbsolutePaths: string[];
|
|
9
|
-
userConfig: VovkConfig | null;
|
|
10
|
-
error: Error | undefined;
|
|
11
|
-
}>;
|