@azure-net/cli 4.0.0-0 ā 4.1.0
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/bin/azure-net.js +73 -34
- package/bin/azure-net.ts +81 -34
- package/eslint.config.js +15 -0
- package/package.json +1 -1
- package/src/checks/checkDomain.js +201 -0
- package/src/checks/checkDomain.ts +223 -0
- package/src/checks/checkFoldersStructure.js +70 -0
- package/src/checks/checkFoldersStructure.ts +85 -0
- package/src/checks/checkImports.ts +166 -0
- package/src/checks/checkInternal.js +37 -0
- package/src/checks/checkInternal.ts +44 -0
- package/src/checks/checkLayerBoundaries.js +178 -0
- package/src/checks/checkLayerBoundaries.ts +216 -0
- package/src/checks/checkPresenterNames.js +202 -0
- package/src/checks/checkPresenterNames.ts +208 -0
- package/src/checks/checkProject.js +42 -0
- package/src/checks/checkProject.ts +45 -0
- package/src/checks/checkProviderGraph.js +221 -0
- package/src/checks/checkProviderGraph.ts +234 -0
- package/src/checks/checkProviderNames.js +158 -0
- package/src/checks/checkProviderNames.ts +165 -0
- package/src/checks/index.js +8 -0
- package/src/checks/index.ts +9 -0
- package/src/generate/layers/generateRepository.ts +123 -0
- package/src/generate/layers/generateRepositoryMethod.ts +102 -0
- package/src/generate/layers/generateUseCases.ts +50 -0
- package/src/generate/layers/repositoryShared.ts +657 -0
- package/src/generate/module/generateModulePreset.js +307 -0
- package/src/generate/module/generateModulePreset.ts +337 -0
- package/src/generate/module/generateSchemaFromType.js +46 -8
- package/src/generate/module/generateSchemaFromType.ts +52 -8
- package/src/generate/module/repositoryModuleShared.ts +665 -0
- package/src/utils/contextUtils.ts +89 -0
- package/src/utils/fileUtils.ts +100 -0
- package/src/utils/loadConfig.ts +69 -0
- package/src/commands/generate/generateCrudBase.js +0 -188
- package/src/commands/generate/generateCrudPresenter.js +0 -225
- package/src/commands/generate/generateModule.js +0 -31
- package/src/commands/generate/generateModuleBase.js +0 -130
- package/src/commands/generate/generateModulePresenter.js +0 -103
- package/src/commands/generate/generatePresenter.js +0 -80
- package/src/commands/generate/generateRepository.js +0 -70
- package/src/commands/generate/generateSchema.js +0 -100
- package/src/commands/generate/generateService.js +0 -66
- package/src/commands/generate/index.js +0 -9
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import prompts from 'prompts';
|
|
2
|
-
import generateRepository from './generateRepository.js';
|
|
3
|
-
import generateService from './generateService.js';
|
|
4
|
-
import generatePresenter from './generatePresenter.js';
|
|
5
|
-
import generateSchema from './generateSchema.js';
|
|
6
|
-
|
|
7
|
-
export default async function generateModule() {
|
|
8
|
-
console.log('š Generating complete module...\n');
|
|
9
|
-
console.log('ā ļø Note: This will create repository, service, presenter and schemas.');
|
|
10
|
-
console.log(' You will need to manually wire them in the providers.\n');
|
|
11
|
-
|
|
12
|
-
const { confirm } = await prompts({
|
|
13
|
-
type: 'confirm',
|
|
14
|
-
name: 'confirm',
|
|
15
|
-
message: 'Continue?'
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
if (confirm) {
|
|
19
|
-
await generateRepository();
|
|
20
|
-
await generateService();
|
|
21
|
-
await generatePresenter();
|
|
22
|
-
await generateSchema(); // Create schema
|
|
23
|
-
await generateSchema(); // Update schema
|
|
24
|
-
|
|
25
|
-
console.log('\nā
Module generation complete!');
|
|
26
|
-
console.log('\nš” Remember to:');
|
|
27
|
-
console.log(' 1. Add repository to InfrastructureProvider');
|
|
28
|
-
console.log(' 2. Add service to ApplicationProvider');
|
|
29
|
-
console.log(' 3. Update presenter to use the service from ApplicationProvider');
|
|
30
|
-
}
|
|
31
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import prompts from 'prompts';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { selectContext, getContextPath, toPascalCase, toCamelCase, getAvailableFiles, toKebabCase } from '../../utils/contextUtils.js';
|
|
4
|
-
import { writeIfNotExists, updateIndexTs, updateCoreIndex } from '../../utils/fileUtils.js';
|
|
5
|
-
|
|
6
|
-
const entityTemplate = `export interface I{{name}} {
|
|
7
|
-
\tid: number;
|
|
8
|
-
\t// Add entity fields here
|
|
9
|
-
\tcreated_at: string;
|
|
10
|
-
\tupdated_at: string;
|
|
11
|
-
}`;
|
|
12
|
-
|
|
13
|
-
const repositoryTemplate = `import { {{datasource}} } from '{{datasourceImport}}';
|
|
14
|
-
|
|
15
|
-
export class {{name}}Repository {
|
|
16
|
-
\tprivate endpoint = '{{endpoint}}';
|
|
17
|
-
\t
|
|
18
|
-
\tconstructor(private {{datasourceVar}}: {{datasource}}) {}
|
|
19
|
-
\t
|
|
20
|
-
\tpublic async example() {
|
|
21
|
-
\t\treturn this.{{datasourceVar}}.createRequest(({ http }) =>
|
|
22
|
-
\t\t\thttp.get(this.endpoint)
|
|
23
|
-
\t\t).then(res => res.getData());
|
|
24
|
-
\t}
|
|
25
|
-
}`;
|
|
26
|
-
|
|
27
|
-
const serviceTemplate = `import { ClassMirror } from '@azure-net/kit';
|
|
28
|
-
import { {{name}}Repository } from '\${{context}}/infrastructure/http/repositories';
|
|
29
|
-
|
|
30
|
-
export class {{name}}Service extends ClassMirror<{{name}}Repository> {
|
|
31
|
-
\tconstructor(private {{camelName}}Repository: {{name}}Repository) {
|
|
32
|
-
\t\tsuper({{camelName}}Repository);
|
|
33
|
-
\t}
|
|
34
|
-
\t
|
|
35
|
-
\tdeclare example: {{name}}Repository['example'];
|
|
36
|
-
}`;
|
|
37
|
-
|
|
38
|
-
export default async function generateModuleBase() {
|
|
39
|
-
const context = await selectContext('Select context for module base:');
|
|
40
|
-
|
|
41
|
-
const { name } = await prompts({
|
|
42
|
-
type: 'text',
|
|
43
|
-
name: 'name',
|
|
44
|
-
message: 'Module name (PascalCase):'
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const { endpoint } = await prompts({
|
|
48
|
-
type: 'text',
|
|
49
|
-
name: 'endpoint',
|
|
50
|
-
message: 'API endpoint (e.g. /api/users):'
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const { needEntity } = await prompts({
|
|
54
|
-
type: 'confirm',
|
|
55
|
-
name: 'needEntity',
|
|
56
|
-
message: 'Create domain entity?',
|
|
57
|
-
initial: true
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// Get available datasources
|
|
61
|
-
const contextPath = getContextPath(context);
|
|
62
|
-
const coreDatasources = await getAvailableFiles(path.join(process.cwd(), 'src/core/datasources'));
|
|
63
|
-
const contextDatasources = await getAvailableFiles(path.join(contextPath, 'infrastructure/http/datasources'));
|
|
64
|
-
|
|
65
|
-
const allDatasources = [
|
|
66
|
-
...coreDatasources.map((d) => ({ title: `${d} (core)`, value: { name: d, from: 'core' } })),
|
|
67
|
-
...contextDatasources.map((d) => ({ title: `${d} (${context})`, value: { name: d, from: context } }))
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
const { datasource } = await prompts({
|
|
71
|
-
type: 'select',
|
|
72
|
-
name: 'datasource',
|
|
73
|
-
message: 'Select datasource:',
|
|
74
|
-
choices: allDatasources
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const pascalName = toPascalCase(name);
|
|
78
|
-
const camelName = toCamelCase(name);
|
|
79
|
-
const entityLower = toKebabCase(pascalName);
|
|
80
|
-
|
|
81
|
-
console.log('\nš Generating module base (repository & service)...\n');
|
|
82
|
-
|
|
83
|
-
// 1. Create Domain entity if needed
|
|
84
|
-
if (needEntity) {
|
|
85
|
-
const domainPath = path.join(contextPath, 'domain', entityLower);
|
|
86
|
-
const modelPath = path.join(domainPath, 'model');
|
|
87
|
-
|
|
88
|
-
await writeIfNotExists(path.join(modelPath, `I${pascalName}.ts`), entityTemplate.replace(/{{name}}/g, pascalName));
|
|
89
|
-
|
|
90
|
-
await writeIfNotExists(path.join(modelPath, 'index.ts'), `export * from './I${pascalName}';`);
|
|
91
|
-
|
|
92
|
-
await writeIfNotExists(path.join(domainPath, 'index.ts'), `export * from './model';`);
|
|
93
|
-
|
|
94
|
-
console.log(`ā
Domain entity I${pascalName} created`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// 2. Create Repository
|
|
98
|
-
const repoPath = path.join(contextPath, 'infrastructure/http/repositories');
|
|
99
|
-
const datasourceImport = datasource.from === 'core' ? '$core/datasources' : `\$${context}/infrastructure/http/datasources`;
|
|
100
|
-
|
|
101
|
-
await writeIfNotExists(
|
|
102
|
-
path.join(repoPath, `${pascalName}Repository.ts`),
|
|
103
|
-
repositoryTemplate
|
|
104
|
-
.replace(/{{name}}/g, pascalName)
|
|
105
|
-
.replace(/{{endpoint}}/g, endpoint)
|
|
106
|
-
.replace(/{{datasource}}/g, datasource.name)
|
|
107
|
-
.replace(/{{datasourceImport}}/g, datasourceImport)
|
|
108
|
-
.replace(/{{datasourceVar}}/g, toCamelCase(datasource.name))
|
|
109
|
-
);
|
|
110
|
-
await updateIndexTs(repoPath);
|
|
111
|
-
|
|
112
|
-
// 3. Create Service
|
|
113
|
-
const servicePath = path.join(contextPath, 'application/services');
|
|
114
|
-
await writeIfNotExists(
|
|
115
|
-
path.join(servicePath, `${pascalName}Service.ts`),
|
|
116
|
-
serviceTemplate
|
|
117
|
-
.replace(/{{name}}/g, pascalName)
|
|
118
|
-
.replace(/{{camelName}}/g, camelName)
|
|
119
|
-
.replace(/{{context}}/g, context)
|
|
120
|
-
);
|
|
121
|
-
await updateIndexTs(servicePath);
|
|
122
|
-
|
|
123
|
-
// Update core index
|
|
124
|
-
await updateCoreIndex();
|
|
125
|
-
|
|
126
|
-
console.log(`\nā
Module base for ${pascalName} created successfully!`);
|
|
127
|
-
console.log(`\nš” Remember to:`);
|
|
128
|
-
console.log(` 1. Add ${pascalName}Repository to InfrastructureProvider`);
|
|
129
|
-
console.log(` 2. Add ${pascalName}Service to ApplicationProvider`);
|
|
130
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import prompts from 'prompts';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import {
|
|
4
|
-
selectContext,
|
|
5
|
-
getContextPath,
|
|
6
|
-
toPascalCase,
|
|
7
|
-
getAvailableFiles,
|
|
8
|
-
getApplicationProviderServices,
|
|
9
|
-
toKebabCase
|
|
10
|
-
} from '../../utils/contextUtils.js';
|
|
11
|
-
import { updateIndexTs, writeIfNotExists, updateCoreIndex } from '../../utils/fileUtils.js';
|
|
12
|
-
|
|
13
|
-
const presenterWithCoreTemplate = `import { {{presenterFactory}} } from '$core/presenters';
|
|
14
|
-
import { ApplicationProvider } from '\${{context}}/application';
|
|
15
|
-
|
|
16
|
-
export const {{name}}Presenter = {{presenterFactory}}('{{name}}Presenter', ({ createAsyncResource, createAsyncAction }) => {
|
|
17
|
-
\tconst { {{serviceName}} } = ApplicationProvider();
|
|
18
|
-
\t
|
|
19
|
-
\t// Add your presenter methods here
|
|
20
|
-
\t
|
|
21
|
-
\treturn {};
|
|
22
|
-
});`;
|
|
23
|
-
|
|
24
|
-
const presenterWithoutCoreTemplate = `import { createPresenter } from '@azure-net/kit';
|
|
25
|
-
import { ApplicationProvider } from '\${{context}}/application';
|
|
26
|
-
|
|
27
|
-
export const {{name}}Presenter = createPresenter('{{name}}Presenter', () => {
|
|
28
|
-
\tconst { {{serviceName}} } = ApplicationProvider();
|
|
29
|
-
\t
|
|
30
|
-
\t// Add your presenter methods here
|
|
31
|
-
\t
|
|
32
|
-
\treturn {};
|
|
33
|
-
});`;
|
|
34
|
-
|
|
35
|
-
export default async function generateModulePresenter() {
|
|
36
|
-
const context = await selectContext('Select context for module presenter:');
|
|
37
|
-
|
|
38
|
-
// Get available services from ApplicationProvider
|
|
39
|
-
const services = await getApplicationProviderServices(context);
|
|
40
|
-
|
|
41
|
-
if (services.length === 0) {
|
|
42
|
-
console.error('ā No services found in ApplicationProvider. Add services manually first.');
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const { service } = await prompts({
|
|
47
|
-
type: 'select',
|
|
48
|
-
name: 'service',
|
|
49
|
-
message: 'Select service for presenter:',
|
|
50
|
-
choices: services.map((s) => ({ title: s, value: s }))
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const { moduleName } = await prompts({
|
|
54
|
-
type: 'text',
|
|
55
|
-
name: 'moduleName',
|
|
56
|
-
message: 'Module name for presenter (will create folder in delivery):'
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Extract entity name from service name
|
|
60
|
-
const pascalName = toPascalCase(moduleName);
|
|
61
|
-
const entityLower = toKebabCase(pascalName);
|
|
62
|
-
|
|
63
|
-
// Get presenter factory
|
|
64
|
-
const corePresenters = await getAvailableFiles(path.join(process.cwd(), 'src/core/presenters'));
|
|
65
|
-
|
|
66
|
-
const { presenterType } = await prompts({
|
|
67
|
-
type: 'select',
|
|
68
|
-
name: 'presenterType',
|
|
69
|
-
message: 'Select presenter factory:',
|
|
70
|
-
choices: [
|
|
71
|
-
{ title: 'Use createPresenter from package', value: 'package' },
|
|
72
|
-
...corePresenters.map((p) => ({ title: `Use ${p} from core`, value: p }))
|
|
73
|
-
]
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const contextPath = getContextPath(context);
|
|
77
|
-
const deliveryModulePath = path.join(contextPath, 'delivery', entityLower);
|
|
78
|
-
|
|
79
|
-
console.log('\nš Generating module presenter...\n');
|
|
80
|
-
|
|
81
|
-
// Create Presenter
|
|
82
|
-
const presenterTemplate = presenterType === 'package' ? presenterWithoutCoreTemplate : presenterWithCoreTemplate;
|
|
83
|
-
|
|
84
|
-
const presenterFactory = presenterType === 'package' ? 'createPresenter' : presenterType;
|
|
85
|
-
|
|
86
|
-
await writeIfNotExists(
|
|
87
|
-
path.join(deliveryModulePath, `${pascalName}Presenter.ts`),
|
|
88
|
-
presenterTemplate
|
|
89
|
-
.replace(/{{name}}/g, pascalName)
|
|
90
|
-
.replace(/{{context}}/g, context)
|
|
91
|
-
.replace(/{{serviceName}}/g, service)
|
|
92
|
-
.replace(/{{presenterFactory}}/g, presenterFactory)
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
// Create module index
|
|
96
|
-
await writeIfNotExists(path.join(deliveryModulePath, 'index.ts'), `export * from './${pascalName}Presenter';`);
|
|
97
|
-
|
|
98
|
-
// Update core index
|
|
99
|
-
await updateCoreIndex();
|
|
100
|
-
|
|
101
|
-
console.log(`ā
Module presenter for ${pascalName} created successfully!`);
|
|
102
|
-
console.log(`\nš” Remember to add presenter methods using the ${service}.`);
|
|
103
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import prompts from 'prompts';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { selectContext, getContextPath, toPascalCase, getAvailableFiles, toKebabCase } from '../../utils/contextUtils.js';
|
|
4
|
-
import { writeIfNotExists, updateCoreIndex } from '../../utils/fileUtils.js';
|
|
5
|
-
|
|
6
|
-
const presenterWithCoreTemplate = `import { {{corePresenter}} } from '$core/presenters';
|
|
7
|
-
import { ApplicationProvider } from '\${{context}}/application';
|
|
8
|
-
|
|
9
|
-
export const {{name}}Presenter = {{corePresenter}}('{{name}}Presenter', ({ createAsyncResource, createAsyncAction }) => {
|
|
10
|
-
\tconst { /* extract services from ApplicationProvider */ } = ApplicationProvider();
|
|
11
|
-
\t
|
|
12
|
-
\tconst example = async () => {
|
|
13
|
-
\t\t// Using async helpers from core presenter factory
|
|
14
|
-
\t\treturn await createAsyncResource(Promise.resolve({}));
|
|
15
|
-
\t};
|
|
16
|
-
\t
|
|
17
|
-
\treturn { example };
|
|
18
|
-
});`;
|
|
19
|
-
|
|
20
|
-
const presenterWithPackageTemplate = `import { createPresenter } from '@azure-net/kit';
|
|
21
|
-
import { ApplicationProvider } from '\${{context}}/application';
|
|
22
|
-
|
|
23
|
-
export const {{name}}Presenter = createPresenter('{{name}}Presenter', () => {
|
|
24
|
-
\tconst { /* extract services from ApplicationProvider */ } = ApplicationProvider();
|
|
25
|
-
\t
|
|
26
|
-
\tconst example = async () => {
|
|
27
|
-
\t\t// Direct method without async helpers
|
|
28
|
-
\t\treturn await Promise.resolve({});
|
|
29
|
-
\t};
|
|
30
|
-
\t
|
|
31
|
-
\treturn { example };
|
|
32
|
-
});`;
|
|
33
|
-
|
|
34
|
-
export default async function generatePresenter() {
|
|
35
|
-
const context = await selectContext('Select context for presenter:');
|
|
36
|
-
|
|
37
|
-
const { name } = await prompts({
|
|
38
|
-
type: 'text',
|
|
39
|
-
name: 'name',
|
|
40
|
-
message: 'Module name (will create folder in delivery):'
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Check for core presenters
|
|
44
|
-
const corePresenters = await getAvailableFiles(path.join(process.cwd(), 'src/core/presenters'));
|
|
45
|
-
|
|
46
|
-
const presenterChoices = [
|
|
47
|
-
{ title: 'Use createPresenter from package', value: 'package' },
|
|
48
|
-
...corePresenters.map((p) => ({ title: `Use ${p} from core`, value: p }))
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
const { presenterType } = await prompts({
|
|
52
|
-
type: 'select',
|
|
53
|
-
name: 'presenterType',
|
|
54
|
-
message: 'Select presenter factory:',
|
|
55
|
-
choices: presenterChoices
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const pascalName = toPascalCase(name);
|
|
59
|
-
const moduleLower = toKebabCase(pascalName);
|
|
60
|
-
const contextPath = getContextPath(context);
|
|
61
|
-
const modulePath = path.join(contextPath, 'delivery', moduleLower);
|
|
62
|
-
const filePath = path.join(modulePath, `${pascalName}Presenter.ts`);
|
|
63
|
-
|
|
64
|
-
const content =
|
|
65
|
-
presenterType === 'package'
|
|
66
|
-
? presenterWithPackageTemplate.replace(/{{name}}/g, pascalName).replace(/{{context}}/g, context)
|
|
67
|
-
: presenterWithCoreTemplate
|
|
68
|
-
.replace(/{{name}}/g, pascalName)
|
|
69
|
-
.replace(/{{corePresenter}}/g, presenterType)
|
|
70
|
-
.replace(/{{context}}/g, context);
|
|
71
|
-
|
|
72
|
-
await writeIfNotExists(filePath, content);
|
|
73
|
-
await writeIfNotExists(path.join(modulePath, 'index.ts'), `export * from './${pascalName}Presenter';`);
|
|
74
|
-
|
|
75
|
-
// Update core index
|
|
76
|
-
await updateCoreIndex();
|
|
77
|
-
|
|
78
|
-
console.log(`ā
Presenter created at ${filePath}`);
|
|
79
|
-
console.log(`\nš” Remember to extract needed services from ApplicationProvider in the presenter.`);
|
|
80
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import prompts from 'prompts';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { selectContext, getContextPath, toPascalCase, getAvailableFiles, toCamelCase } from '../../utils/contextUtils.js';
|
|
4
|
-
import { writeIfNotExists, updateIndexTs, updateCoreIndex } from '../../utils/fileUtils.js';
|
|
5
|
-
|
|
6
|
-
const repositoryTemplate = `import { {{datasource}} } from '{{datasourceImport}}';
|
|
7
|
-
|
|
8
|
-
export class {{name}}Repository {
|
|
9
|
-
\tconstructor(private {{datasourceVar}}: {{datasource}}) {}
|
|
10
|
-
\t
|
|
11
|
-
\tpublic async example() {
|
|
12
|
-
\t\treturn this.{{datasourceVar}}.createRequest(({ http }) =>
|
|
13
|
-
\t\t\thttp.get('/endpoint')
|
|
14
|
-
\t\t).then(res => res.getData());
|
|
15
|
-
\t}
|
|
16
|
-
}`;
|
|
17
|
-
|
|
18
|
-
export default async function generateRepository() {
|
|
19
|
-
const context = await selectContext('Select context for repository:');
|
|
20
|
-
|
|
21
|
-
const { name } = await prompts({
|
|
22
|
-
type: 'text',
|
|
23
|
-
name: 'name',
|
|
24
|
-
message: 'Repository name (without "Repository" suffix):'
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// Get available datasources
|
|
28
|
-
const contextPath = getContextPath(context);
|
|
29
|
-
const coreDatasources = await getAvailableFiles(path.join(process.cwd(), 'src/core/datasources'));
|
|
30
|
-
const contextDatasources = await getAvailableFiles(path.join(contextPath, 'infrastructure/http/datasources'));
|
|
31
|
-
|
|
32
|
-
const allDatasources = [
|
|
33
|
-
...coreDatasources.map((d) => ({ title: `${d} (core)`, value: { name: d, from: 'core' } })),
|
|
34
|
-
...contextDatasources.map((d) => ({ title: `${d} (${context})`, value: { name: d, from: context } }))
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
if (allDatasources.length === 0) {
|
|
38
|
-
console.error('ā No datasources available. Create a datasource first.');
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const { datasource } = await prompts({
|
|
43
|
-
type: 'select',
|
|
44
|
-
name: 'datasource',
|
|
45
|
-
message: 'Select datasource:',
|
|
46
|
-
choices: allDatasources
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const pascalName = toPascalCase(name);
|
|
50
|
-
const repoPath = path.join(contextPath, 'infrastructure/http/repositories');
|
|
51
|
-
const filePath = path.join(repoPath, `${pascalName}Repository.ts`);
|
|
52
|
-
|
|
53
|
-
// Generate repository
|
|
54
|
-
const datasourceImport = datasource.from === 'core' ? '$core/datasources' : `\${context}/infrastructure/http/datasources`;
|
|
55
|
-
|
|
56
|
-
const content = repositoryTemplate
|
|
57
|
-
.replace(/{{name}}/g, pascalName)
|
|
58
|
-
.replace(/{{datasource}}/g, datasource.name)
|
|
59
|
-
.replace(/{{datasourceImport}}/g, datasourceImport)
|
|
60
|
-
.replace(/{{datasourceVar}}/g, toCamelCase(datasource.name));
|
|
61
|
-
|
|
62
|
-
await writeIfNotExists(filePath, content);
|
|
63
|
-
await updateIndexTs(repoPath);
|
|
64
|
-
|
|
65
|
-
// Update core index
|
|
66
|
-
await updateCoreIndex();
|
|
67
|
-
|
|
68
|
-
console.log(`ā
Repository created at ${filePath}`);
|
|
69
|
-
console.log(`\nš” Remember to manually add this repository to InfrastructureProvider when needed.`);
|
|
70
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import prompts from 'prompts';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs/promises';
|
|
4
|
-
import { selectContext, getContextPath, toPascalCase, getAvailableFiles } from '../../utils/contextUtils.js';
|
|
5
|
-
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
6
|
-
|
|
7
|
-
const schemaWithCoreTemplate = `import { {{coreSchema}} } from '\$core/schemas';
|
|
8
|
-
|
|
9
|
-
export const {{name}}Schema = {{coreSchema}}()
|
|
10
|
-
\t.rules((rules) => ({
|
|
11
|
-
\t\t// Add validation rules here
|
|
12
|
-
\t}))
|
|
13
|
-
\t.create();`;
|
|
14
|
-
|
|
15
|
-
const schemaWithPackageTemplate = `import { createSchemaFactory } from '@azure-net/kit';
|
|
16
|
-
import { createRules, validationMessagesI18n } from '@azure-net/kit/schema';
|
|
17
|
-
|
|
18
|
-
const Schema = createSchemaFactory(createRules(validationMessagesI18n));
|
|
19
|
-
|
|
20
|
-
export const {{name}}Schema = Schema()
|
|
21
|
-
\t.rules((rules) => ({
|
|
22
|
-
\t\t// Add validation rules here
|
|
23
|
-
\t}))
|
|
24
|
-
\t.create();`;
|
|
25
|
-
|
|
26
|
-
export default async function generateSchema() {
|
|
27
|
-
const context = await selectContext('Select context for schema:');
|
|
28
|
-
|
|
29
|
-
if (context === 'core') {
|
|
30
|
-
console.error('ā Cannot create schema in core. Choose a specific context.');
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const { module } = await prompts({
|
|
35
|
-
type: 'text',
|
|
36
|
-
name: 'module',
|
|
37
|
-
message: 'Module name (folder in delivery):'
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const { name } = await prompts({
|
|
41
|
-
type: 'text',
|
|
42
|
-
name: 'name',
|
|
43
|
-
message: 'Schema name (without "Schema" suffix):'
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// Check for core schemas
|
|
47
|
-
const coreSchemas = await getAvailableFiles(path.join(process.cwd(), 'src/core/schemas'));
|
|
48
|
-
|
|
49
|
-
const choices = [
|
|
50
|
-
{ title: 'Use createSchemaFactory from package', value: 'package' },
|
|
51
|
-
...coreSchemas.map((s) => ({ title: `Use ${s} from core`, value: s }))
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
const { schemaType } = await prompts({
|
|
55
|
-
type: 'select',
|
|
56
|
-
name: 'schemaType',
|
|
57
|
-
message: 'Select schema factory:',
|
|
58
|
-
choices
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const pascalName = toPascalCase(name);
|
|
62
|
-
const moduleName = toPascalCase(module);
|
|
63
|
-
const moduleLower = moduleName.toLowerCase();
|
|
64
|
-
const entityLower = moduleName.toLowerCase();
|
|
65
|
-
const contextPath = getContextPath(context);
|
|
66
|
-
const schemaPath = path.join(contextPath, 'delivery', moduleLower, 'schema');
|
|
67
|
-
const filePath = path.join(schemaPath, `${pascalName}Schema.ts`);
|
|
68
|
-
|
|
69
|
-
const content =
|
|
70
|
-
schemaType === 'package'
|
|
71
|
-
? schemaWithPackageTemplate
|
|
72
|
-
.replace(/{{name}}/g, pascalName)
|
|
73
|
-
.replace(/{{context}}/g, context)
|
|
74
|
-
.replace(/{{entityLower}}/g, entityLower)
|
|
75
|
-
: schemaWithCoreTemplate
|
|
76
|
-
.replace(/{{name}}/g, pascalName)
|
|
77
|
-
.replace(/{{context}}/g, context)
|
|
78
|
-
.replace(/{{entityLower}}/g, entityLower)
|
|
79
|
-
.replace(/{{coreSchema}}/g, schemaType);
|
|
80
|
-
|
|
81
|
-
await writeIfNotExists(filePath, content);
|
|
82
|
-
await updateIndexTs(schemaPath);
|
|
83
|
-
|
|
84
|
-
// Update module index
|
|
85
|
-
const moduleIndexPath = path.join(contextPath, 'delivery', moduleLower, 'index.ts');
|
|
86
|
-
if (
|
|
87
|
-
await fs
|
|
88
|
-
.access(moduleIndexPath)
|
|
89
|
-
.then(() => true)
|
|
90
|
-
.catch(() => false)
|
|
91
|
-
) {
|
|
92
|
-
let indexContent = await fs.readFile(moduleIndexPath, 'utf-8');
|
|
93
|
-
if (!indexContent.includes(`export * from './schema'`)) {
|
|
94
|
-
indexContent += `\nexport * from './schema';`;
|
|
95
|
-
await fs.writeFile(moduleIndexPath, indexContent, 'utf-8');
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
console.log(`ā
Schema created at ${filePath}`);
|
|
100
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import prompts from 'prompts';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { selectContext, getContextPath, toPascalCase, getAvailableFiles } from '../../utils/contextUtils.js';
|
|
4
|
-
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
5
|
-
|
|
6
|
-
const serviceTemplate = `import { ClassMirror } from '@azure-net/kit';
|
|
7
|
-
import { {{repository}} } from '\${{context}}/infrastructure/http/repositories';
|
|
8
|
-
|
|
9
|
-
export class {{name}}Service extends ClassMirror<{{repository}}> {
|
|
10
|
-
\tconstructor(private {{repositoryVar}}: {{repository}}) {
|
|
11
|
-
\t\tsuper({{repositoryVar}});
|
|
12
|
-
\t}
|
|
13
|
-
\t
|
|
14
|
-
\tdeclare example: {{repository}}['example'];
|
|
15
|
-
}`;
|
|
16
|
-
|
|
17
|
-
const serviceWithoutRepoTemplate = `export class {{name}}Service {
|
|
18
|
-
\tconstructor() {}
|
|
19
|
-
\t
|
|
20
|
-
\tpublic async example() {
|
|
21
|
-
\t\t// Implement service logic
|
|
22
|
-
\t\treturn {};
|
|
23
|
-
\t}
|
|
24
|
-
}`;
|
|
25
|
-
|
|
26
|
-
export default async function generateService() {
|
|
27
|
-
const context = await selectContext('Select context for service:');
|
|
28
|
-
|
|
29
|
-
const { name } = await prompts({
|
|
30
|
-
type: 'text',
|
|
31
|
-
name: 'name',
|
|
32
|
-
message: 'Service name (without "Service" suffix):'
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Get available repositories
|
|
36
|
-
const contextPath = getContextPath(context);
|
|
37
|
-
const repositories = await getAvailableFiles(path.join(contextPath, 'infrastructure', 'http', 'repositories'));
|
|
38
|
-
|
|
39
|
-
const choices = [{ title: 'Without repository', value: null }, ...repositories.map((r) => ({ title: `${r}`, value: r }))];
|
|
40
|
-
|
|
41
|
-
const { repository } = await prompts({
|
|
42
|
-
type: 'select',
|
|
43
|
-
name: 'repository',
|
|
44
|
-
message: 'Select repository:',
|
|
45
|
-
choices
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const pascalName = toPascalCase(name);
|
|
49
|
-
const servicePath = path.join(contextPath, 'application', 'services');
|
|
50
|
-
const filePath = path.join(servicePath, `${pascalName}Service.ts`);
|
|
51
|
-
|
|
52
|
-
// Generate service
|
|
53
|
-
const content = repository
|
|
54
|
-
? serviceTemplate
|
|
55
|
-
.replace(/{{name}}/g, pascalName)
|
|
56
|
-
.replace(/{{repository}}/g, repository)
|
|
57
|
-
.replace(/{{repositoryVar}}/g, repository.charAt(0).toLowerCase() + repository.slice(1))
|
|
58
|
-
.replace(/{{context}}/g, context)
|
|
59
|
-
: serviceWithoutRepoTemplate.replace(/{{name}}/g, pascalName);
|
|
60
|
-
|
|
61
|
-
await writeIfNotExists(filePath, content);
|
|
62
|
-
await updateIndexTs(servicePath);
|
|
63
|
-
|
|
64
|
-
console.log(`ā
Service created at ${filePath}`);
|
|
65
|
-
console.log(`\nš” Remember to manually add this service to ApplicationProvider when needed.`);
|
|
66
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { default as generateRepository } from './generateRepository.js';
|
|
2
|
-
export { default as generateService } from './generateService.js';
|
|
3
|
-
export { default as generateSchema } from './generateSchema.js';
|
|
4
|
-
export { default as generatePresenter } from './generatePresenter.js';
|
|
5
|
-
export { default as generateModule } from './generateModule.js';
|
|
6
|
-
export { default as generateCrudBase } from './generateCrudBase.js';
|
|
7
|
-
export { default as generateCrudPresenter } from './generateCrudPresenter.js';
|
|
8
|
-
export { default as generateModuleBase } from './generateModuleBase.js';
|
|
9
|
-
export { default as generateModulePresenter } from './generateModulePresenter.js';
|