vovk-cli 0.0.1-draft.1 → 0.0.1-draft.10
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/README.md +1 -1
- package/dist/getProjectInfo/getRelativeSrcRoot.mjs +3 -3
- package/dist/getProjectInfo/getUserConfig.mjs +1 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.mjs +6 -4
- package/dist/init/index.mjs +29 -19
- package/dist/init/installDependencies.d.mts +3 -0
- package/dist/init/installDependencies.mjs +1 -1
- package/dist/init/logUpdateDependenciesError.d.mts +11 -0
- package/dist/init/logUpdateDependenciesError.mjs +45 -0
- package/dist/init/updateDependenciesWithoutInstalling.mjs +9 -2
- package/dist/new/addClassToSegmentCode.mjs +6 -2
- package/dist/new/index.d.mts +1 -1
- package/dist/new/index.mjs +13 -3
- package/dist/new/newModule.d.mts +6 -2
- package/dist/new/newModule.mjs +39 -21
- package/dist/new/newSegment.d.mts +3 -2
- package/dist/new/newSegment.mjs +3 -3
- package/dist/new/render.d.mts +3 -7
- package/dist/new/render.mjs +13 -6
- package/dist/postinstall.mjs +3 -1
- package/dist/types.d.mts +7 -0
- package/dist/utils/getAvailablePort.mjs +1 -1
- package/dist/watcher/ensureSchemaFiles.mjs +18 -6
- package/dist/watcher/index.mjs +11 -9
- package/dist/watcher/writeOneSchemaFile.mjs +2 -1
- package/package.json +6 -5
- package/templates/controller.ejs +15 -14
- package/templates/service.ejs +24 -4
- package/templates/worker.ejs +24 -1
- package/dist/getProjectInfo/directoryExists.d.mts +0 -1
- package/dist/getProjectInfo/directoryExists.mjs +0 -10
- package/templates_old/MyThingController.c.only.template.ts +0 -32
- package/templates_old/MyThingController.c.template.ts +0 -34
- package/templates_old/MyThingService.s.template.ts +0 -18
- package/templates_old/controller.ejs +0 -85
- package/templates_old/service.ejs +0 -9
- package/templates_old/worker.ejs +0 -9
- package/templates_old/zod/MyThingController.c.only.template.ts +0 -32
- package/templates_old/zod/MyThingController.c.template.ts +0 -39
- package/templates_old/zod/MyThingService.s.template.ts +0 -18
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Description is coming soon.
|
|
1
|
+
Description is coming soon.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import
|
|
2
|
+
import getFileSystemEntryType, { FileSystemEntryType } from '../utils/getFileSystemEntryType.mjs';
|
|
3
3
|
export default async function getRelativeSrcRoot({ cwd }) {
|
|
4
4
|
// Next.js Docs: src/app or src/pages will be ignored if app or pages are present in the root directory.
|
|
5
|
-
if (await
|
|
5
|
+
if ((await getFileSystemEntryType(path.join(cwd, 'app'))) === FileSystemEntryType.DIRECTORY) {
|
|
6
6
|
return '.';
|
|
7
7
|
}
|
|
8
|
-
else if (await
|
|
8
|
+
else if ((await getFileSystemEntryType(path.join(cwd, 'src/app'))) === FileSystemEntryType.DIRECTORY) {
|
|
9
9
|
return './src';
|
|
10
10
|
}
|
|
11
11
|
throw new Error(`${cwd} Could not find app router directory. Check Next.js docs for more info.`);
|
|
@@ -11,7 +11,7 @@ async function getUserConfig({ cwd, }) {
|
|
|
11
11
|
try {
|
|
12
12
|
userConfig = await importUncachedModule(configPath);
|
|
13
13
|
}
|
|
14
|
-
catch
|
|
14
|
+
catch {
|
|
15
15
|
try {
|
|
16
16
|
const cacheBuster = Date.now();
|
|
17
17
|
({ default: userConfig } = (await import(`${configPath}?cache=${cacheBuster}`)));
|
package/dist/index.d.mts
CHANGED
|
@@ -20,7 +20,11 @@ export interface InitOptions {
|
|
|
20
20
|
channel?: 'latest' | 'beta' | 'dev';
|
|
21
21
|
}
|
|
22
22
|
export interface NewOptions {
|
|
23
|
-
dryRun
|
|
23
|
+
dryRun?: boolean;
|
|
24
|
+
template?: string;
|
|
25
|
+
dir?: string;
|
|
26
|
+
overwrite?: boolean;
|
|
27
|
+
noSegmentUpdate?: boolean;
|
|
24
28
|
}
|
|
25
29
|
declare const program: Command;
|
|
26
30
|
export declare function initProgram(p: typeof program, command: string): Command;
|
package/dist/index.mjs
CHANGED
|
@@ -25,9 +25,7 @@ program
|
|
|
25
25
|
const PORT = !options.nextDev
|
|
26
26
|
? process.env.PORT
|
|
27
27
|
: process.env.PORT ||
|
|
28
|
-
(await getAvailablePort(3000, portAttempts, 0, (failedPort, tryingPort) =>
|
|
29
|
-
// eslint-disable-next-line no-console
|
|
30
|
-
console.warn(`🐺 Next.js Port ${failedPort} is in use, trying ${tryingPort} instead.`)).catch(() => {
|
|
28
|
+
(await getAvailablePort(3000, portAttempts, 0, (failedPort, tryingPort) => console.warn(`🐺 Next.js Port ${failedPort} is in use, trying ${tryingPort} instead.`)).catch(() => {
|
|
31
29
|
throw new Error(`🐺 ❌ Failed to find available Next port after ${portAttempts} attempts`);
|
|
32
30
|
}));
|
|
33
31
|
if (!PORT) {
|
|
@@ -88,8 +86,8 @@ export function initProgram(p, command) {
|
|
|
88
86
|
.option('--update-scripts <mode>', 'Update package.json scripts (implicit or explicit)')
|
|
89
87
|
.option('--validation-library <library>', 'Validation library to use ("vovk-zod", "vovk-yup", "vovk-dto" or another). Set to "none" to skip validation')
|
|
90
88
|
.option('--validate-on-client', 'Validate on client')
|
|
91
|
-
.option('--dry-run', 'Do not write files to disk')
|
|
92
89
|
.option('--channel <channel>', 'Channel to use for fetching packages', 'latest')
|
|
90
|
+
.option('--dry-run', 'Do not write files to disk')
|
|
93
91
|
.action((prefix = '.', options) => new Init().main(prefix, options));
|
|
94
92
|
}
|
|
95
93
|
initProgram(program, 'init ');
|
|
@@ -97,6 +95,10 @@ program
|
|
|
97
95
|
.command('new [components...]')
|
|
98
96
|
.alias('n')
|
|
99
97
|
.description('Create new components. "vovk new [...components] [segmentName/]moduleName" to create a new module or "vovk new segment [segmentName]" to create a new segment')
|
|
98
|
+
.option('-O, --overwrite', 'Overwrite existing files')
|
|
99
|
+
.option('--template <template>', 'Override config template')
|
|
100
|
+
.option('--dir <dirname>', 'Override dirName in template file. Relative to the root of the project')
|
|
101
|
+
.option('--no-segment-update', 'Do not update segment files when creating a new module')
|
|
100
102
|
.option('--dry-run', 'Do not write files to disk')
|
|
101
103
|
.action((components, options) => newComponents(components, options));
|
|
102
104
|
program
|
package/dist/init/index.mjs
CHANGED
|
@@ -62,13 +62,15 @@ import fs from 'fs/promises';
|
|
|
62
62
|
import getConfigPaths from '../getProjectInfo/getConfigAbsolutePaths.mjs';
|
|
63
63
|
import chalk from 'chalk';
|
|
64
64
|
import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
65
|
-
import installDependencies from './installDependencies.mjs';
|
|
65
|
+
import installDependencies, { getPackageManager } from './installDependencies.mjs';
|
|
66
66
|
import getLogger from '../utils/getLogger.mjs';
|
|
67
67
|
import createConfig from './createConfig.mjs';
|
|
68
68
|
import updateNPMScripts from './updateNPMScripts.mjs';
|
|
69
69
|
import checkTSConfigForExperimentalDecorators from './checkTSConfigForExperimentalDecorators.mjs';
|
|
70
70
|
import updateTypeScriptConfig from './updateTypeScriptConfig.mjs';
|
|
71
71
|
import updateDependenciesWithoutInstalling from './updateDependenciesWithoutInstalling.mjs';
|
|
72
|
+
import logUpdateDependenciesError from './logUpdateDependenciesError.mjs';
|
|
73
|
+
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
72
74
|
export class Init {
|
|
73
75
|
root;
|
|
74
76
|
log;
|
|
@@ -113,6 +115,7 @@ export class Init {
|
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
if (!dryRun) {
|
|
118
|
+
let depsUpdated = false;
|
|
116
119
|
try {
|
|
117
120
|
await updateDependenciesWithoutInstalling({
|
|
118
121
|
log,
|
|
@@ -121,27 +124,34 @@ export class Init {
|
|
|
121
124
|
devDependencyNames: devDependencies,
|
|
122
125
|
channel: channel ?? 'latest',
|
|
123
126
|
});
|
|
124
|
-
|
|
127
|
+
depsUpdated = true;
|
|
125
128
|
}
|
|
126
|
-
catch (
|
|
127
|
-
|
|
129
|
+
catch (e) {
|
|
130
|
+
const error = e;
|
|
131
|
+
logUpdateDependenciesError({ log, error, useNpm, useYarn, usePnpm, useBun, dependencies, devDependencies });
|
|
128
132
|
}
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
cwd: root,
|
|
134
|
-
options: {
|
|
135
|
-
useNpm,
|
|
136
|
-
useYarn,
|
|
137
|
-
usePnpm,
|
|
138
|
-
useBun,
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
log.info('Dependencies installed successfully');
|
|
133
|
+
if (depsUpdated) {
|
|
134
|
+
const packageManager = getPackageManager({ useNpm, useYarn, usePnpm, useBun });
|
|
135
|
+
if (skipInstall) {
|
|
136
|
+
log.info(`Installation skipped. Please, install them manually with ${chalkHighlightThing(packageManager + ' install')}`);
|
|
142
137
|
}
|
|
143
|
-
|
|
144
|
-
|
|
138
|
+
else {
|
|
139
|
+
try {
|
|
140
|
+
await installDependencies({
|
|
141
|
+
log,
|
|
142
|
+
cwd: root,
|
|
143
|
+
options: {
|
|
144
|
+
useNpm,
|
|
145
|
+
useYarn,
|
|
146
|
+
usePnpm,
|
|
147
|
+
useBun,
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
log.info('Dependencies installed successfully');
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
log.warn(`Failed to install dependencies: ${error.message}. Please, install them manually with ${chalkHighlightThing(packageManager + ' install')}`);
|
|
154
|
+
}
|
|
145
155
|
}
|
|
146
156
|
}
|
|
147
157
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { InitOptions } from '../index.mjs';
|
|
2
2
|
import getLogger from '../utils/getLogger.mjs';
|
|
3
|
+
type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
|
|
4
|
+
export declare function getPackageManager(options: Pick<InitOptions, 'useNpm' | 'useYarn' | 'usePnpm' | 'useBun'>): PackageManager;
|
|
3
5
|
export default function installDependencies({ log, cwd, options, }: {
|
|
4
6
|
log: ReturnType<typeof getLogger>;
|
|
5
7
|
cwd: string;
|
|
6
8
|
options: Pick<InitOptions, 'useNpm' | 'useYarn' | 'usePnpm' | 'useBun'>;
|
|
7
9
|
}): Promise<void>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import getLogger from "../utils/getLogger.mjs";
|
|
2
|
+
export default function logUpdateDependenciesError({ useNpm, useYarn, usePnpm, useBun, log, dependencies, devDependencies, error }: {
|
|
3
|
+
useNpm?: boolean;
|
|
4
|
+
useYarn?: boolean;
|
|
5
|
+
usePnpm?: boolean;
|
|
6
|
+
useBun?: boolean;
|
|
7
|
+
log: ReturnType<typeof getLogger>;
|
|
8
|
+
dependencies: string[];
|
|
9
|
+
devDependencies: string[];
|
|
10
|
+
error: Error;
|
|
11
|
+
}): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import chalkHighlightThing from "../utils/chalkHighlightThing.mjs";
|
|
2
|
+
import { getPackageManager } from "./installDependencies.mjs";
|
|
3
|
+
export default function logUpdateDependenciesError({ useNpm, useYarn, usePnpm, useBun, log, dependencies, devDependencies, error }) {
|
|
4
|
+
const packageManager = getPackageManager({ useNpm, useYarn, usePnpm, useBun });
|
|
5
|
+
const installCommands = [];
|
|
6
|
+
if (dependencies.length > 0) {
|
|
7
|
+
let depInstallCmd = '';
|
|
8
|
+
switch (packageManager) {
|
|
9
|
+
case 'npm':
|
|
10
|
+
depInstallCmd = `npm install ${dependencies.join(' ')}`;
|
|
11
|
+
break;
|
|
12
|
+
case 'yarn':
|
|
13
|
+
depInstallCmd = `yarn add ${dependencies.join(' ')}`;
|
|
14
|
+
break;
|
|
15
|
+
case 'pnpm':
|
|
16
|
+
depInstallCmd = `pnpm add ${dependencies.join(' ')}`;
|
|
17
|
+
break;
|
|
18
|
+
case 'bun':
|
|
19
|
+
depInstallCmd = `bun add ${dependencies.join(' ')}`;
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
installCommands.push(depInstallCmd);
|
|
23
|
+
}
|
|
24
|
+
if (devDependencies.length > 0) {
|
|
25
|
+
let devDepInstallCmd = '';
|
|
26
|
+
switch (packageManager) {
|
|
27
|
+
case 'npm':
|
|
28
|
+
devDepInstallCmd = `npm install -D ${devDependencies.join(' ')}`;
|
|
29
|
+
break;
|
|
30
|
+
case 'yarn':
|
|
31
|
+
devDepInstallCmd = `yarn add --dev ${devDependencies.join(' ')}`;
|
|
32
|
+
break;
|
|
33
|
+
case 'pnpm':
|
|
34
|
+
devDepInstallCmd = `pnpm add -D ${devDependencies.join(' ')}`;
|
|
35
|
+
break;
|
|
36
|
+
case 'bun':
|
|
37
|
+
devDepInstallCmd = `bun add -d ${devDependencies.join(' ')}`;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
installCommands.push(devDepInstallCmd);
|
|
41
|
+
}
|
|
42
|
+
const installCmd = installCommands.join(' && ');
|
|
43
|
+
// Log the error with the appropriate manual installation instructions
|
|
44
|
+
log.warn(`Failed to update dependencies: ${error.message}. Please, install them manually with ${chalkHighlightThing(installCmd)}`);
|
|
45
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import getNPMPackageMetadata from '../utils/getNPMPackageMetadata.mjs';
|
|
3
3
|
import path from 'path';
|
|
4
|
+
import chalk from 'chalk';
|
|
4
5
|
async function updateDeps({ packageJson, packageNames, channel, key, }) {
|
|
5
6
|
return Promise.all(packageNames.map(async (packageName) => {
|
|
6
7
|
if (packageJson[key]?.[packageName])
|
|
@@ -18,8 +19,14 @@ export default async function updateDependenciesWithoutInstalling({ log, dir, de
|
|
|
18
19
|
const packageJsonPath = path.join(dir, 'package.json');
|
|
19
20
|
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
|
|
20
21
|
await updateDeps({ packageJson, packageNames: dependencyNames, channel, key: 'dependencies' });
|
|
21
|
-
log.debug('Updated dependencies in package.json');
|
|
22
22
|
await updateDeps({ packageJson, packageNames: devDependencyNames, channel, key: 'devDependencies' });
|
|
23
|
-
log.debug('Updated devDependencies in package.json');
|
|
24
23
|
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
24
|
+
log.info('Added dependencies to package.json:');
|
|
25
|
+
for (const dependency of dependencyNames) {
|
|
26
|
+
log.raw.log(` - ${chalk.cyan(dependency)}`);
|
|
27
|
+
}
|
|
28
|
+
log.info('Added devDependencies to package.json:');
|
|
29
|
+
for (const dependency of devDependencyNames) {
|
|
30
|
+
log.raw.log(` - ${chalk.cyan(dependency)}`);
|
|
31
|
+
}
|
|
25
32
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { Project, SyntaxKind } from 'ts-morph';
|
|
1
|
+
import { Project, QuoteKind, SyntaxKind } from 'ts-morph';
|
|
2
2
|
export default function addClassToSegmentCode(segmentSourceCode, { sourceName, compiledName, type, importPath, }) {
|
|
3
|
-
const project = new Project(
|
|
3
|
+
const project = new Project({
|
|
4
|
+
manipulationSettings: {
|
|
5
|
+
quoteKind: QuoteKind.Single
|
|
6
|
+
}
|
|
7
|
+
});
|
|
4
8
|
const sourceFile = project.createSourceFile('route.ts', segmentSourceCode, { overwrite: true });
|
|
5
9
|
// Add the import if it doesn't exist
|
|
6
10
|
let importDeclaration = sourceFile.getImportDeclaration((imp) => {
|
package/dist/new/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { NewOptions } from '../index.mjs';
|
|
2
|
-
export default function newComponents(components: string[],
|
|
2
|
+
export default function newComponents(components: string[], { dryRun, dir, template, overwrite, noSegmentUpdate }: NewOptions): Promise<void>;
|
package/dist/new/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import newModule from './newModule.mjs';
|
|
2
2
|
import newSegment from './newSegment.mjs';
|
|
3
|
-
export default async function newComponents(components,
|
|
3
|
+
export default async function newComponents(components, { dryRun, dir, template, overwrite, noSegmentUpdate }) {
|
|
4
4
|
if (components[0] === 'segment' || components[0] === 'segments') {
|
|
5
|
+
// vovk new segment [segmentName]
|
|
5
6
|
let segmentNames = components
|
|
6
7
|
.slice(1)
|
|
7
8
|
.map((segmentName) => (segmentName === '""' || segmentName === "''" ? '' : segmentName));
|
|
@@ -9,10 +10,11 @@ export default async function newComponents(components, options) {
|
|
|
9
10
|
segmentNames = [''];
|
|
10
11
|
}
|
|
11
12
|
for (const segmentName of segmentNames) {
|
|
12
|
-
await newSegment({ segmentName,
|
|
13
|
+
await newSegment({ segmentName, overwrite, dryRun });
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
else {
|
|
17
|
+
// vovk new [what...] [moduleNameWithOptionalSegment]
|
|
16
18
|
if (components.length < 2) {
|
|
17
19
|
throw new Error('Invalid command invocation. Please provide at least two arguments.');
|
|
18
20
|
}
|
|
@@ -21,6 +23,14 @@ export default async function newComponents(components, options) {
|
|
|
21
23
|
if (!moduleNameWithOptionalSegment) {
|
|
22
24
|
throw new Error('A module name with an optional segment cannot be empty');
|
|
23
25
|
}
|
|
24
|
-
await newModule({
|
|
26
|
+
await newModule({
|
|
27
|
+
what,
|
|
28
|
+
moduleNameWithOptionalSegment,
|
|
29
|
+
dir,
|
|
30
|
+
template,
|
|
31
|
+
overwrite,
|
|
32
|
+
noSegmentUpdate,
|
|
33
|
+
dryRun,
|
|
34
|
+
});
|
|
25
35
|
}
|
|
26
36
|
}
|
package/dist/new/newModule.d.mts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
export default function newModule({ what, moduleNameWithOptionalSegment, dryRun, }: {
|
|
1
|
+
export default function newModule({ what, moduleNameWithOptionalSegment, dryRun, dir: dirNameFlag, template: templateFlag, noSegmentUpdate, overwrite, }: {
|
|
2
2
|
what: string[];
|
|
3
3
|
moduleNameWithOptionalSegment: string;
|
|
4
|
-
dryRun
|
|
4
|
+
dryRun?: boolean;
|
|
5
|
+
dir?: string;
|
|
6
|
+
template?: string;
|
|
7
|
+
noSegmentUpdate?: boolean;
|
|
8
|
+
overwrite?: boolean;
|
|
5
9
|
}): Promise<void>;
|
package/dist/new/newModule.mjs
CHANGED
|
@@ -18,7 +18,7 @@ function splitByLast(str, delimiter = '/') {
|
|
|
18
18
|
const after = str.substring(index + delimiter.length);
|
|
19
19
|
return [before, after];
|
|
20
20
|
}
|
|
21
|
-
export default async function newModule({ what, moduleNameWithOptionalSegment, dryRun, }) {
|
|
21
|
+
export default async function newModule({ what, moduleNameWithOptionalSegment, dryRun, dir: dirNameFlag, template: templateFlag, noSegmentUpdate, overwrite, }) {
|
|
22
22
|
const { config, log, apiDir, cwd } = await getProjectInfo();
|
|
23
23
|
const templates = config.templates;
|
|
24
24
|
const [segmentName, moduleName] = splitByLast(moduleNameWithOptionalSegment);
|
|
@@ -35,10 +35,19 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
|
|
|
35
35
|
return s;
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
console.log('moduleNameWithOptionalSegment', moduleNameWithOptionalSegment);
|
|
39
|
+
console.log('what', what);
|
|
40
|
+
if (templateFlag) {
|
|
41
|
+
if (what.length > 1) {
|
|
42
|
+
throw new Error('Cannot use --template flag with multiple types');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// check if template exists
|
|
47
|
+
for (const type of what) {
|
|
48
|
+
if (!templates[type]) {
|
|
49
|
+
throw new Error(`Template for ${type} not found in config`);
|
|
50
|
+
}
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
const segments = await locateSegments(apiDir);
|
|
@@ -47,44 +56,53 @@ export default async function newModule({ what, moduleNameWithOptionalSegment, d
|
|
|
47
56
|
throw new Error(`Segment ${segmentName} not found`);
|
|
48
57
|
}
|
|
49
58
|
for (const type of what) {
|
|
50
|
-
const templatePath = templates[type];
|
|
59
|
+
const templatePath = templateFlag ?? templates[type];
|
|
51
60
|
const templateAbsolutePath = templatePath.startsWith('/') || templatePath.startsWith('.')
|
|
52
61
|
? path.resolve(cwd, templatePath)
|
|
53
62
|
: path.resolve(cwd, './node_modules', templatePath);
|
|
54
63
|
const templateCode = await fs.readFile(templateAbsolutePath, 'utf-8');
|
|
55
|
-
const {
|
|
64
|
+
const { dirName: renderedDirName, fileName, sourceName, compiledName, code, } = await render(templateCode, {
|
|
65
|
+
cwd,
|
|
56
66
|
config,
|
|
57
67
|
withService: what.includes('service'),
|
|
58
68
|
segmentName,
|
|
59
69
|
moduleName,
|
|
60
70
|
});
|
|
61
|
-
const
|
|
62
|
-
const
|
|
71
|
+
const absoluteModuleDir = path.join(cwd, dirNameFlag || renderedDirName);
|
|
72
|
+
const absoluteModulePath = path.join(absoluteModuleDir, fileName);
|
|
63
73
|
const prettiedCode = await prettify(code, absoluteModulePath);
|
|
64
74
|
if (!dryRun) {
|
|
65
|
-
if (await getFileSystemEntryType(absoluteModulePath)) {
|
|
75
|
+
if (!overwrite && (await getFileSystemEntryType(absoluteModulePath))) {
|
|
66
76
|
log.warn(`File ${chalkHighlightThing(absoluteModulePath)} already exists, skipping this "${type}"`);
|
|
67
77
|
}
|
|
68
78
|
else {
|
|
69
|
-
await fs.mkdir(
|
|
79
|
+
await fs.mkdir(absoluteModuleDir, { recursive: true });
|
|
70
80
|
await fs.writeFile(absoluteModulePath, prettiedCode);
|
|
71
81
|
}
|
|
72
82
|
}
|
|
73
83
|
if (type === 'controller' || type === 'worker') {
|
|
84
|
+
if (!sourceName) {
|
|
85
|
+
throw new Error('sourceName is required');
|
|
86
|
+
}
|
|
87
|
+
if (!compiledName) {
|
|
88
|
+
throw new Error('compiledName is required');
|
|
89
|
+
}
|
|
74
90
|
const { routeFilePath } = segment;
|
|
75
91
|
const segmentSourceCode = await fs.readFile(routeFilePath, 'utf-8');
|
|
76
|
-
const importPath = path.relative(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
const importPath = path.relative(path.dirname(routeFilePath), absoluteModulePath).replace(/\.(ts|tsx)$/, '');
|
|
93
|
+
if (!noSegmentUpdate) {
|
|
94
|
+
const newSegmentCode = addClassToSegmentCode(segmentSourceCode, {
|
|
95
|
+
sourceName,
|
|
96
|
+
compiledName,
|
|
97
|
+
type,
|
|
98
|
+
importPath,
|
|
99
|
+
});
|
|
100
|
+
if (!dryRun) {
|
|
101
|
+
await fs.writeFile(routeFilePath, newSegmentCode);
|
|
102
|
+
}
|
|
85
103
|
}
|
|
86
104
|
log.info(`Added ${chalkHighlightThing(sourceName)} ${type} to ${formatLoggedSegmentName(segmentName)} as ${chalkHighlightThing(compiledName)}`);
|
|
87
105
|
}
|
|
88
|
-
log.info(`Created ${chalkHighlightThing(
|
|
106
|
+
log.info(`Created ${chalkHighlightThing(fileName)} using "${chalkHighlightThing(type)}" template for ${formatLoggedSegmentName(segmentName)}`);
|
|
89
107
|
}
|
|
90
108
|
}
|
package/dist/new/newSegment.mjs
CHANGED
|
@@ -5,10 +5,10 @@ import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
|
5
5
|
import chalkHighlightThing from '../utils/chalkHighlightThing.mjs';
|
|
6
6
|
import formatLoggedSegmentName from '../utils/formatLoggedSegmentName.mjs';
|
|
7
7
|
import prettify from '../utils/prettify.mjs';
|
|
8
|
-
export default async function newSegment({ segmentName, dryRun }) {
|
|
8
|
+
export default async function newSegment({ segmentName, overwrite, dryRun, }) {
|
|
9
9
|
const { apiDir, cwd, log } = await getProjectInfo();
|
|
10
10
|
const absoluteSegmentRoutePath = path.join(cwd, apiDir, segmentName, '[[...vovk]]/route.ts');
|
|
11
|
-
if (await getFileSystemEntryType(absoluteSegmentRoutePath)) {
|
|
11
|
+
if (!overwrite && (await getFileSystemEntryType(absoluteSegmentRoutePath))) {
|
|
12
12
|
throw new Error(`Unable to create new segment. ${formatLoggedSegmentName(segmentName, { upperFirst: true })} already exists.`);
|
|
13
13
|
}
|
|
14
14
|
const code = await prettify(`import { initVovk } from 'vovk';
|
|
@@ -29,5 +29,5 @@ ${segmentName ? ` segmentName: '${segmentName}',\n` : ''} emitSchema: true,
|
|
|
29
29
|
await fs.mkdir(path.dirname(absoluteSegmentRoutePath), { recursive: true });
|
|
30
30
|
await fs.writeFile(absoluteSegmentRoutePath, code);
|
|
31
31
|
}
|
|
32
|
-
log.info(`${formatLoggedSegmentName(segmentName, { upperFirst: true })} created at ${absoluteSegmentRoutePath}. Run ${chalkHighlightThing(`vovk new controller ${segmentName}
|
|
32
|
+
log.info(`${formatLoggedSegmentName(segmentName, { upperFirst: true })} created at ${absoluteSegmentRoutePath}. Run ${chalkHighlightThing(`vovk new controller ${[segmentName, 'someName'].filter(Boolean).join('/')}`)} to create a controller.`);
|
|
33
33
|
}
|
package/dist/new/render.d.mts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import type { VovkConfig } from '../types.mjs';
|
|
1
|
+
import type { VovkConfig, VovkModuleRenderResult } from '../types.mjs';
|
|
2
2
|
export default function render(codeTemplate: string, { config, withService, segmentName, moduleName, }: {
|
|
3
|
+
cwd: string;
|
|
3
4
|
config: VovkConfig;
|
|
4
5
|
withService: boolean;
|
|
5
6
|
segmentName: string;
|
|
6
7
|
moduleName: string;
|
|
7
|
-
}): Promise<
|
|
8
|
-
filePath: string;
|
|
9
|
-
sourceName: string;
|
|
10
|
-
compiledName: string;
|
|
11
|
-
code: string;
|
|
12
|
-
}>;
|
|
8
|
+
}): Promise<VovkModuleRenderResult>;
|
package/dist/new/render.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import pluralize from 'pluralize';
|
|
|
5
5
|
import addCommonTerms from './addCommonTerms.mjs';
|
|
6
6
|
addCommonTerms();
|
|
7
7
|
export default async function render(codeTemplate, { config, withService, segmentName, moduleName, }) {
|
|
8
|
-
const
|
|
8
|
+
const getModuleDirName = (givenSegmentName, givenModuleName) => [config.modulesDir, givenSegmentName || config.rootSegmentModulesDirName, _.camelCase(givenModuleName)]
|
|
9
9
|
.filter(Boolean)
|
|
10
10
|
.join('/');
|
|
11
11
|
const templateVars = {
|
|
@@ -15,15 +15,22 @@ export default async function render(codeTemplate, { config, withService, segmen
|
|
|
15
15
|
segmentName,
|
|
16
16
|
moduleName,
|
|
17
17
|
// utils
|
|
18
|
-
|
|
18
|
+
getModuleDirName,
|
|
19
19
|
// libraries
|
|
20
20
|
_, // lodash
|
|
21
21
|
pluralize,
|
|
22
22
|
};
|
|
23
23
|
// first, render the front matter because it can use ejs variables
|
|
24
24
|
const parsed = matter((await ejs.render(codeTemplate, templateVars, { async: true })).trim());
|
|
25
|
-
const {
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
|
|
25
|
+
const { dirName, fileName, sourceName, compiledName } = parsed.data;
|
|
26
|
+
const code = parsed.content;
|
|
27
|
+
// const templateContent = parsed.content; TODO
|
|
28
|
+
// const code = await ejs.render(templateContent, templateVars, { async: true });
|
|
29
|
+
return {
|
|
30
|
+
dirName,
|
|
31
|
+
fileName,
|
|
32
|
+
sourceName,
|
|
33
|
+
compiledName,
|
|
34
|
+
code,
|
|
35
|
+
};
|
|
29
36
|
}
|
package/dist/postinstall.mjs
CHANGED
|
@@ -11,7 +11,9 @@ async function postinstall() {
|
|
|
11
11
|
const js = path.join(vovk, 'client.js');
|
|
12
12
|
const ts = path.join(vovk, 'client.d.ts');
|
|
13
13
|
const index = path.join(vovk, 'index.ts');
|
|
14
|
-
if ((await getFileSystemEntryType(js)) ||
|
|
14
|
+
if ((await getFileSystemEntryType(js)) ||
|
|
15
|
+
(await getFileSystemEntryType(ts)) ||
|
|
16
|
+
(await getFileSystemEntryType(index))) {
|
|
15
17
|
return;
|
|
16
18
|
}
|
|
17
19
|
await fs.mkdir(vovk, { recursive: true });
|
package/dist/types.d.mts
CHANGED
|
@@ -34,7 +34,7 @@ function getAvailablePort(startPort, maxAttempts, attempt, onWarning) {
|
|
|
34
34
|
getAvailablePort(startPort + 1, maxAttempts, attempt + 1, onWarning).then(resolve, reject);
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
reject('No available ports found');
|
|
37
|
+
reject(new Error('No available ports found'));
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
});
|
|
@@ -7,17 +7,29 @@ export default async function ensureSchemaFiles(projectInfo, schemaOutAbsolutePa
|
|
|
7
7
|
const now = Date.now();
|
|
8
8
|
let hasChanged = false;
|
|
9
9
|
// Create index.js file
|
|
10
|
-
const indexContent =
|
|
10
|
+
const indexContent = `// auto-generated
|
|
11
|
+
${segmentNames
|
|
11
12
|
.map((segmentName) => {
|
|
12
13
|
return `module.exports['${segmentName}'] = require('./${segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json');`;
|
|
13
14
|
})
|
|
14
|
-
.join('\n')
|
|
15
|
-
const dTsContent =
|
|
16
|
-
|
|
15
|
+
.join('\n')}`;
|
|
16
|
+
const dTsContent = `// auto-generated
|
|
17
|
+
import type { VovkSchema } from 'vovk';
|
|
18
|
+
declare const segmentSchema: {
|
|
19
|
+
${segmentNames.map((segmentName) => ` '${segmentName}': VovkSchema;`).join('\n')}
|
|
20
|
+
};
|
|
17
21
|
export default segmentSchema;`;
|
|
22
|
+
const jsAbsolutePath = path.join(schemaOutAbsolutePath, 'index.js');
|
|
23
|
+
const dTsAbsolutePath = path.join(schemaOutAbsolutePath, 'index.d.ts');
|
|
24
|
+
const existingJs = await fs.readFile(jsAbsolutePath, 'utf-8').catch(() => null);
|
|
25
|
+
const existingDTs = await fs.readFile(dTsAbsolutePath, 'utf-8').catch(() => null);
|
|
18
26
|
await fs.mkdir(schemaOutAbsolutePath, { recursive: true });
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
if (existingJs !== indexContent) {
|
|
28
|
+
await fs.writeFile(jsAbsolutePath, indexContent);
|
|
29
|
+
}
|
|
30
|
+
if (existingDTs !== dTsContent) {
|
|
31
|
+
await fs.writeFile(dTsAbsolutePath, dTsContent);
|
|
32
|
+
}
|
|
21
33
|
// Create JSON files (if not exist) with name [segmentName].json (where segmentName can include /, which means the folder structure can be nested)
|
|
22
34
|
await Promise.all(segmentNames.map(async (segmentName) => {
|
|
23
35
|
const { isCreated } = await writeOneSchemaFile({
|
package/dist/watcher/index.mjs
CHANGED
|
@@ -51,7 +51,6 @@ export class VovkCLIWatcher {
|
|
|
51
51
|
void this.#requestSchema(getSegmentName(filePath));
|
|
52
52
|
}
|
|
53
53
|
})
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
55
54
|
.on('addDir', async (dirPath) => {
|
|
56
55
|
log.debug(`Directory ${dirPath} has been added to segments folder`);
|
|
57
56
|
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
@@ -59,7 +58,6 @@ export class VovkCLIWatcher {
|
|
|
59
58
|
void this.#requestSchema(segmentName);
|
|
60
59
|
}
|
|
61
60
|
})
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
63
61
|
.on('unlinkDir', async (dirPath) => {
|
|
64
62
|
log.debug(`Directory ${dirPath} has been removed from segments folder`);
|
|
65
63
|
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
@@ -81,7 +79,7 @@ export class VovkCLIWatcher {
|
|
|
81
79
|
log.debug('Segments watcher is ready');
|
|
82
80
|
})
|
|
83
81
|
.on('error', (error) => {
|
|
84
|
-
log.error(`Error watching segments folder: ${error
|
|
82
|
+
log.error(`Error watching segments folder: ${error?.message ?? 'Unknown error'}`);
|
|
85
83
|
});
|
|
86
84
|
};
|
|
87
85
|
#watchModules = () => {
|
|
@@ -119,13 +117,14 @@ export class VovkCLIWatcher {
|
|
|
119
117
|
log.debug('Modules watcher is ready');
|
|
120
118
|
})
|
|
121
119
|
.on('error', (error) => {
|
|
122
|
-
log.error(`Error watching modules folder: ${error
|
|
120
|
+
log.error(`Error watching modules folder: ${error?.message ?? 'Unknown error'}`);
|
|
123
121
|
});
|
|
124
122
|
};
|
|
125
123
|
#watchConfig = () => {
|
|
126
124
|
const { log, cwd } = this.#projectInfo;
|
|
127
125
|
log.debug(`Watching config files`);
|
|
128
126
|
let isInitial = true;
|
|
127
|
+
let isReady = false;
|
|
129
128
|
const handle = debounce(async () => {
|
|
130
129
|
this.#projectInfo = await getProjectInfo();
|
|
131
130
|
if (!isInitial) {
|
|
@@ -148,11 +147,14 @@ export class VovkCLIWatcher {
|
|
|
148
147
|
.on('change', () => void handle())
|
|
149
148
|
.on('unlink', () => void handle())
|
|
150
149
|
.on('ready', () => {
|
|
150
|
+
if (isReady)
|
|
151
|
+
return;
|
|
152
|
+
// for some reason this watcher triggers ready event twice
|
|
151
153
|
log.debug('Config files watcher is ready');
|
|
154
|
+
isReady = true;
|
|
152
155
|
})
|
|
153
|
-
.on('error', (error) => {
|
|
154
|
-
|
|
155
|
-
});
|
|
156
|
+
.on('error', (error) => log.error(`Error watching config files: ${error?.message ?? 'Unknown error'}`));
|
|
157
|
+
void handle();
|
|
156
158
|
};
|
|
157
159
|
#watch() {
|
|
158
160
|
if (this.#isWatching)
|
|
@@ -274,13 +276,13 @@ export class VovkCLIWatcher {
|
|
|
274
276
|
const schemaOutAbsolutePath = path.join(cwd, config.schemaOutDir);
|
|
275
277
|
this.#segments = await locateSegments(apiDirAbsolutePath);
|
|
276
278
|
await debouncedEnsureSchemaFiles(this.#projectInfo, schemaOutAbsolutePath, this.#segments.map((s) => s.segmentName));
|
|
277
|
-
// Request schema every segment in
|
|
279
|
+
// Request schema every segment in 5 seconds in order to update schema and start watching
|
|
278
280
|
setTimeout(() => {
|
|
279
281
|
for (const { segmentName } of this.#segments) {
|
|
280
282
|
void this.#requestSchema(segmentName);
|
|
281
283
|
}
|
|
282
284
|
this.#watch();
|
|
283
|
-
},
|
|
285
|
+
}, 5000);
|
|
284
286
|
}
|
|
285
287
|
}
|
|
286
288
|
const env = process.env;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
3
|
import diffSchema from './diffSchema.mjs';
|
|
4
|
+
import getFileSystemEntryType from '../utils/getFileSystemEntryType.mjs';
|
|
4
5
|
export const ROOT_SEGMENT_SCHEMA_NAME = '_root';
|
|
5
6
|
export default async function writeOneSchemaFile({ schemaOutAbsolutePath, schema, skipIfExists = false, }) {
|
|
6
7
|
const segmentPath = path.join(schemaOutAbsolutePath, `${schema.segmentName || ROOT_SEGMENT_SCHEMA_NAME}.json`);
|
|
7
|
-
if (skipIfExists) {
|
|
8
|
+
if (skipIfExists && (await getFileSystemEntryType(segmentPath))) {
|
|
8
9
|
try {
|
|
9
10
|
await fs.stat(segmentPath);
|
|
10
11
|
return { isCreated: false, diffResult: null };
|
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.10",
|
|
4
4
|
"bin": {
|
|
5
5
|
"vovk": "./dist/index.mjs"
|
|
6
6
|
},
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "rm -rf dist tsconfig.build.tsbuildinfo && tsc -P tsconfig.build.json",
|
|
13
13
|
"build-test": "rm -rf test_dist && tsc -P tsconfig.test.json",
|
|
14
|
-
"test": "npm run build && chmod +x ./dist/index.mjs && npm run build-test
|
|
15
|
-
"
|
|
14
|
+
"pre-test": "npm run build && chmod +x ./dist/index.mjs && npm run build-test",
|
|
15
|
+
"test-only": "npm run pre-test && node --test --test-only test_dist/test/**/*.mjs",
|
|
16
|
+
"test": "npm run pre-test && node --test --test-concurrency=1 test_dist/test/**/*.mjs",
|
|
16
17
|
"ncu": "npm-check-updates -u",
|
|
17
18
|
"npm-publish": "npm publish"
|
|
18
19
|
},
|
|
@@ -33,10 +34,10 @@
|
|
|
33
34
|
},
|
|
34
35
|
"homepage": "https://vovk.dev",
|
|
35
36
|
"peerDependencies": {
|
|
36
|
-
"vovk": "^3.0.0-draft.
|
|
37
|
+
"vovk": "^3.0.0-draft.12"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
|
-
"@inquirer/prompts": "^7.0.
|
|
40
|
+
"@inquirer/prompts": "^7.0.1",
|
|
40
41
|
"@npmcli/package-json": "^6.0.1",
|
|
41
42
|
"chalk": "^5.3.0",
|
|
42
43
|
"chokidar": "^4.0.1",
|
package/templates/controller.ejs
CHANGED
|
@@ -1,50 +1,51 @@
|
|
|
1
1
|
<% var modulePascalName = _.upperFirst(_.camelCase(moduleName)); %>
|
|
2
2
|
<% var modulePascalNamePlural = pluralize(modulePascalName); %>
|
|
3
|
-
<% var
|
|
4
|
-
<% var
|
|
5
|
-
<% var
|
|
3
|
+
<% var controllerName = modulePascalName + 'Controller'; %>
|
|
4
|
+
<% var compiledName = modulePascalName + 'RPC'; %>
|
|
5
|
+
<% var serviceName = modulePascalName + 'Service'; %>
|
|
6
6
|
---
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
dirName: <%= getModuleDirName(segmentName, moduleName) %>
|
|
8
|
+
fileName: <%= controllerName + '.ts' %>
|
|
9
|
+
sourceName: <%= controllerName %>
|
|
10
|
+
compiledName: <%= compiledName %>
|
|
10
11
|
---
|
|
11
12
|
|
|
12
|
-
import { prefix, get, put, post, del
|
|
13
|
+
import { prefix, get, put, post, del, type VovkRequest } from 'vovk';
|
|
13
14
|
<% if(withService) { %>
|
|
14
|
-
import <%=
|
|
15
|
+
import <%= serviceName %> from './<%= serviceName %>';
|
|
15
16
|
<% } %>
|
|
16
17
|
|
|
17
18
|
@prefix('<%= _.kebabCase(moduleName).toLowerCase() %>')
|
|
18
|
-
export default class <%=
|
|
19
|
+
export default class <%= controllerName %> {
|
|
19
20
|
@get()
|
|
20
21
|
static get<%= modulePascalNamePlural %> = async (req: VovkRequest<null, { q: string }>) => {
|
|
21
22
|
const q = req.nextUrl.searchParams.get('q');
|
|
22
23
|
<% if(withService) { %>
|
|
23
|
-
return <%=
|
|
24
|
+
return <%= serviceName %>.get<%= modulePascalNamePlural %>(q);
|
|
24
25
|
<% } else { %>
|
|
25
26
|
return { q };
|
|
26
27
|
<% } %>
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
@put(':id')
|
|
30
|
-
static update<%=
|
|
31
|
+
static update<%= modulePascalName %> = async (req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>, params: { id: string }) => {
|
|
31
32
|
const { id } = params;
|
|
32
33
|
const body = await req.json();
|
|
33
34
|
const q = req.nextUrl.searchParams.get('q');
|
|
34
35
|
<% if(withService) { %>
|
|
35
|
-
return MyThingService.
|
|
36
|
+
return MyThingService.update<%= modulePascalName %>(id, q, body);
|
|
36
37
|
<% } else { %>
|
|
37
38
|
return { id, body, q };
|
|
38
39
|
<% } %>
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
@post()
|
|
42
|
-
static create<%=
|
|
43
|
+
static create<%= modulePascalName %> = () => {
|
|
43
44
|
// ...
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
@del(':id')
|
|
47
|
-
static delete<%=
|
|
48
|
+
static delete<%= modulePascalName %> = () => {
|
|
48
49
|
// ...
|
|
49
50
|
};
|
|
50
51
|
}
|
package/templates/service.ejs
CHANGED
|
@@ -1,7 +1,27 @@
|
|
|
1
|
-
<% var
|
|
2
|
-
|
|
1
|
+
<% var modulePascalName = _.upperFirst(_.camelCase(moduleName)); %>
|
|
2
|
+
<% var modulePascalNamePlural = pluralize(modulePascalName); %>
|
|
3
|
+
<% var serviceName = modulePascalName + 'Service'; %>
|
|
4
|
+
<% var controllerName = modulePascalName + 'Controller'; %>
|
|
3
5
|
---
|
|
4
|
-
|
|
6
|
+
dirName: <%= getModuleDirName(segmentName, moduleName) %>
|
|
7
|
+
fileName: <%= serviceName + '.ts' %>
|
|
5
8
|
---
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
import type { VovkControllerBody, VovkControllerQuery } from 'vovk';
|
|
11
|
+
import type <%= controllerName %> from './<%= controllerName %>';
|
|
12
|
+
|
|
13
|
+
export default class <%= serviceName %> {
|
|
14
|
+
static get<%= modulePascalNamePlural %> = (q: VovkControllerQuery<typeof <%= controllerName %>.get<%= modulePascalNamePlural %>>['q']) => {
|
|
15
|
+
return [];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
static update<%= modulePascalName %> = (
|
|
19
|
+
id: string,
|
|
20
|
+
q: VovkControllerQuery<typeof <%= controllerName %>.get<%= modulePascalName %>>['q'],
|
|
21
|
+
body: VovkControllerBody<typeof <%= controllerName %>.get<%= modulePascalName %>>
|
|
22
|
+
) => {
|
|
23
|
+
return { id, q, body };
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// ...
|
|
27
|
+
}
|
package/templates/worker.ejs
CHANGED
|
@@ -1 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
<% var modulePascalName = _.upperFirst(_.camelCase(moduleName)); %>
|
|
2
|
+
<% var modulePascalNamePlural = pluralize(modulePascalName); %>
|
|
3
|
+
<% var workerName = modulePascalName + 'Worker'; %>
|
|
4
|
+
<% var compiledName = modulePascalName + 'WPC'; %>
|
|
5
|
+
---
|
|
6
|
+
dirName: <%= getModuleDirName(segmentName, moduleName) %>
|
|
7
|
+
fileName: <%= controllerName + '.ts' %>
|
|
8
|
+
sourceName: <%= workerName %>
|
|
9
|
+
compiledName: <%= compiledName %>
|
|
10
|
+
---
|
|
11
|
+
import { worker } from 'vovk';
|
|
12
|
+
|
|
13
|
+
@worker()
|
|
14
|
+
export default class <%= workerName %> {
|
|
15
|
+
static heavyComputation = () => {
|
|
16
|
+
return 'Hello, World';
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
static heavyComputationYield = function* () {
|
|
20
|
+
for(const str of ['Hello', 'World'] as const) {
|
|
21
|
+
yield str;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function directoryExists(dir: string): Promise<boolean>;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { prefix, get, put, post, del, type VovkRequest } from 'vovk';
|
|
2
|
-
|
|
3
|
-
@prefix('my-things')
|
|
4
|
-
export default class MyThingController {
|
|
5
|
-
@get()
|
|
6
|
-
static getMyThingsExample = (req: VovkRequest<null, { q: string }>) => {
|
|
7
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
8
|
-
return { q };
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
@put(':id')
|
|
12
|
-
static updateMyThingExample = async (
|
|
13
|
-
req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>,
|
|
14
|
-
params: { id: string }
|
|
15
|
-
) => {
|
|
16
|
-
const { id } = params;
|
|
17
|
-
const body = await req.json();
|
|
18
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
19
|
-
|
|
20
|
-
return { id, q, body };
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
@post()
|
|
24
|
-
static createMyThingExample = () => {
|
|
25
|
-
// ...
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
@del(':id')
|
|
29
|
-
static deleteMyThingExample = () => {
|
|
30
|
-
// ...
|
|
31
|
-
};
|
|
32
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { prefix, get, put, post, del, type VovkRequest } from 'vovk';
|
|
2
|
-
import MyThingService from './MyThingService.s.template';
|
|
3
|
-
|
|
4
|
-
@prefix('my-things')
|
|
5
|
-
export default class MyThingController {
|
|
6
|
-
@get()
|
|
7
|
-
static getMyThingsExample(req: VovkRequest<null, { q: string }>) {
|
|
8
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
9
|
-
|
|
10
|
-
return MyThingService.getMyThingsExample(q);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
@put(':id')
|
|
14
|
-
static updateMyThingExample = async (
|
|
15
|
-
req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>,
|
|
16
|
-
params: { id: string }
|
|
17
|
-
) => {
|
|
18
|
-
const { id } = params;
|
|
19
|
-
const body = await req.json();
|
|
20
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
21
|
-
|
|
22
|
-
return MyThingService.updateMyThingExample(id, q, body);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
@post()
|
|
26
|
-
static createMyThingExample = () => {
|
|
27
|
-
// ...
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
@del(':id')
|
|
31
|
-
static deleteMyThingExample = () => {
|
|
32
|
-
// ...
|
|
33
|
-
};
|
|
34
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { VovkControllerBody, VovkControllerQuery } from 'vovk';
|
|
2
|
-
import type MyThingController from './MyThingController.c.template';
|
|
3
|
-
|
|
4
|
-
export default class MyThingService {
|
|
5
|
-
static getMyThingsExample = (q: VovkControllerQuery<typeof MyThingController.getMyThingsExample>['q']) => {
|
|
6
|
-
return { q };
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
static updateMyThingExample = (
|
|
10
|
-
id: string,
|
|
11
|
-
q: VovkControllerQuery<typeof MyThingController.updateMyThingExample>['q'],
|
|
12
|
-
body: VovkControllerBody<typeof MyThingController.updateMyThingExample>
|
|
13
|
-
) => {
|
|
14
|
-
return { id, q, body };
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// ...
|
|
18
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
<% var modulePascalName = _.upperFirst(_.camelCase(moduleName)); %>
|
|
2
|
-
<% var modulePascalNamePlural = pluralize(modulePascalName); %>
|
|
3
|
-
<% var ControllerName = modulePascalName + 'Controller'; %>
|
|
4
|
-
<% var RPCName = modulePascalName + 'RPC'; %>
|
|
5
|
-
<% var ServiceName = modulePascalName + 'Service'; %>
|
|
6
|
-
---
|
|
7
|
-
# Relative to modules dir
|
|
8
|
-
fileName: <%= getFileDir(segmentName, moduleName) + ControllerName + '.ts' %>
|
|
9
|
-
className: <%= ControllerName %> # Used to define a controller in a segment
|
|
10
|
-
rpcName: <%= RPCName %> # Used to define an exported RPC class in a segment
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
import { prefix, get, put, post, del<%= !config.validationLibrary ? ', type VovkRequest' : '' %> } from 'vovk';
|
|
14
|
-
<% if(withService) { %>
|
|
15
|
-
import <%= ServiceName %> from './<%= ServiceName %>';
|
|
16
|
-
<% } %>
|
|
17
|
-
<% if(config.validationLibrary === 'vovk-zod') { %>
|
|
18
|
-
import { withZod } from 'vovk-zod';
|
|
19
|
-
import { z } from 'zod';
|
|
20
|
-
<% } %>
|
|
21
|
-
|
|
22
|
-
@prefix('<%= _.kebabCase(moduleName).toLowerCase() %>')
|
|
23
|
-
export default class <%= ControllerName %> {
|
|
24
|
-
@get()
|
|
25
|
-
<% if(config.validationLibrary === 'vovk-zod') { %>
|
|
26
|
-
async get<%= modulePascalNamePlural %> = withZod(null, z.object({ q: z.string() }), (req) => {
|
|
27
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
28
|
-
<% if(withService) { %>
|
|
29
|
-
return <%= ServiceName %>.getMyThingsExample(q);
|
|
30
|
-
<% } else { %>
|
|
31
|
-
return { q };
|
|
32
|
-
<% } %>
|
|
33
|
-
});
|
|
34
|
-
<% } else { %>
|
|
35
|
-
static get<%= modulePascalNamePlural %> = async (req: VovkRequest<null, { q: string }>) => {
|
|
36
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
37
|
-
<% if(withService) { %>
|
|
38
|
-
return <%= ServiceName %>.getMyThingsExample(q);
|
|
39
|
-
<% } else { %>
|
|
40
|
-
return { q };
|
|
41
|
-
<% } %>
|
|
42
|
-
}
|
|
43
|
-
<% } %>
|
|
44
|
-
|
|
45
|
-
@put(':id')
|
|
46
|
-
<% if(config.validationLibrary === 'vovk-zod') { %>
|
|
47
|
-
static update<%= modulePascalNamePlural %> = withZod(
|
|
48
|
-
z.object({
|
|
49
|
-
foo: z.union([z.literal('bar'), z.literal('baz')]),
|
|
50
|
-
}),
|
|
51
|
-
z.object({ q: z.string() }),
|
|
52
|
-
async (req, params: { id: string }) => {
|
|
53
|
-
const { id } = params;
|
|
54
|
-
const body = await req.json();
|
|
55
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
56
|
-
<% if(withService) { %>
|
|
57
|
-
return MyThingService.updateMyThingExample(id, q, body);
|
|
58
|
-
<% } else { %>
|
|
59
|
-
return { id, body, q };
|
|
60
|
-
<% } %>
|
|
61
|
-
}
|
|
62
|
-
);
|
|
63
|
-
<% } else { %>
|
|
64
|
-
static update<%= modulePascalNamePlural %> = async (req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>, params: { id: string }) => {
|
|
65
|
-
const { id } = params;
|
|
66
|
-
const body = await req.json();
|
|
67
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
68
|
-
<% if(withService) { %>
|
|
69
|
-
return MyThingService.updateMyThingExample(id, q, body);
|
|
70
|
-
<% } else { %>
|
|
71
|
-
return { id, body, q };
|
|
72
|
-
<% } %>
|
|
73
|
-
};
|
|
74
|
-
<% } %>
|
|
75
|
-
|
|
76
|
-
@post()
|
|
77
|
-
static create<%= modulePascalNamePlural %> = () => {
|
|
78
|
-
// ...
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
@del(':id')
|
|
82
|
-
static delete<%= modulePascalNamePlural %> = () => {
|
|
83
|
-
// ...
|
|
84
|
-
};
|
|
85
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<% var modulePascalName = _.upperFirst(_.camelCase(moduleName); %>
|
|
2
|
-
<% var ServiceName = modulePascalName + 'Service'; %>
|
|
3
|
-
|
|
4
|
-
---
|
|
5
|
-
# Relative to modules dir
|
|
6
|
-
fileName: <%= getFileDir(segmentName, moduleName) + ServiceName + '.ts' %>
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
// TO DO: Implement <%= ServiceName %>
|
package/templates_old/worker.ejs
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<% var modulePascalName = _.upperFirst(_.camelCase(moduleName); %>
|
|
2
|
-
<% var WorkerName = modulePascalName + 'Worker'; %>
|
|
3
|
-
|
|
4
|
-
---
|
|
5
|
-
# Relative to modules dir
|
|
6
|
-
fileName: <%= getFileDir(segmentName, moduleName) + WorkerName + '.ts' %>
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
// TO DO: Implement <%= WorkerName %>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { prefix, get, put, post, del, type VovkRequest } from 'vovk';
|
|
2
|
-
|
|
3
|
-
@prefix('my-thing')
|
|
4
|
-
export default class MyThingController {
|
|
5
|
-
@get()
|
|
6
|
-
static getMyThingsExample = (req: VovkRequest<null, { q: string }>) => {
|
|
7
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
8
|
-
return { q };
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
@put(':id')
|
|
12
|
-
static updateMyThingExample = async (
|
|
13
|
-
req: VovkRequest<{ foo: 'bar' | 'baz' }, { q: string }>,
|
|
14
|
-
params: { id: string }
|
|
15
|
-
) => {
|
|
16
|
-
const { id } = params;
|
|
17
|
-
const body = await req.json();
|
|
18
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
19
|
-
|
|
20
|
-
return { id, q, body };
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
@post()
|
|
24
|
-
static createMyThingExample = () => {
|
|
25
|
-
// ...
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
@del(':id')
|
|
29
|
-
static deleteMyThingExample = () => {
|
|
30
|
-
// ...
|
|
31
|
-
};
|
|
32
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { prefix, get, put, post, del } from 'vovk';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { withZod } from 'vovk-zod';
|
|
4
|
-
import MyThingService from './MyThingService.s.template';
|
|
5
|
-
|
|
6
|
-
@prefix('my-thing')
|
|
7
|
-
export default class MyThingController {
|
|
8
|
-
@get()
|
|
9
|
-
static getMyThingsExample = withZod(null, z.object({ q: z.string() }), (req) => {
|
|
10
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
11
|
-
|
|
12
|
-
return MyThingService.getMyThingsExample(q);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
@put(':id')
|
|
16
|
-
static updateMyThingExample = withZod(
|
|
17
|
-
z.object({
|
|
18
|
-
foo: z.union([z.literal('bar'), z.literal('baz')]),
|
|
19
|
-
}),
|
|
20
|
-
z.object({ q: z.string() }),
|
|
21
|
-
async (req, params: { id: string }) => {
|
|
22
|
-
const { id } = params;
|
|
23
|
-
const body = await req.json();
|
|
24
|
-
const q = req.nextUrl.searchParams.get('q');
|
|
25
|
-
|
|
26
|
-
return MyThingService.updateMyThingExample(id, q, body);
|
|
27
|
-
}
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
@post()
|
|
31
|
-
static async createMyThingExample() {
|
|
32
|
-
// ...
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@del(':id')
|
|
36
|
-
static deleteMyThingExample() {
|
|
37
|
-
// ...
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { VovkControllerBody, VovkControllerQuery } from 'vovk';
|
|
2
|
-
import type MyThingController from './MyThingController.c.template';
|
|
3
|
-
|
|
4
|
-
export default class MyThingService {
|
|
5
|
-
static getMyThingsExample = (q: VovkControllerQuery<typeof MyThingController.getMyThingsExample>['q']) => {
|
|
6
|
-
return { q };
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
static updateMyThingExample = (
|
|
10
|
-
id: string,
|
|
11
|
-
q: VovkControllerQuery<typeof MyThingController.updateMyThingExample>['q'],
|
|
12
|
-
body: VovkControllerBody<typeof MyThingController.updateMyThingExample>
|
|
13
|
-
) => {
|
|
14
|
-
return { id, q, body };
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// ...
|
|
18
|
-
}
|