@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.
Files changed (45) hide show
  1. package/bin/azure-net.js +73 -34
  2. package/bin/azure-net.ts +81 -34
  3. package/eslint.config.js +15 -0
  4. package/package.json +1 -1
  5. package/src/checks/checkDomain.js +201 -0
  6. package/src/checks/checkDomain.ts +223 -0
  7. package/src/checks/checkFoldersStructure.js +70 -0
  8. package/src/checks/checkFoldersStructure.ts +85 -0
  9. package/src/checks/checkImports.ts +166 -0
  10. package/src/checks/checkInternal.js +37 -0
  11. package/src/checks/checkInternal.ts +44 -0
  12. package/src/checks/checkLayerBoundaries.js +178 -0
  13. package/src/checks/checkLayerBoundaries.ts +216 -0
  14. package/src/checks/checkPresenterNames.js +202 -0
  15. package/src/checks/checkPresenterNames.ts +208 -0
  16. package/src/checks/checkProject.js +42 -0
  17. package/src/checks/checkProject.ts +45 -0
  18. package/src/checks/checkProviderGraph.js +221 -0
  19. package/src/checks/checkProviderGraph.ts +234 -0
  20. package/src/checks/checkProviderNames.js +158 -0
  21. package/src/checks/checkProviderNames.ts +165 -0
  22. package/src/checks/index.js +8 -0
  23. package/src/checks/index.ts +9 -0
  24. package/src/generate/layers/generateRepository.ts +123 -0
  25. package/src/generate/layers/generateRepositoryMethod.ts +102 -0
  26. package/src/generate/layers/generateUseCases.ts +50 -0
  27. package/src/generate/layers/repositoryShared.ts +657 -0
  28. package/src/generate/module/generateModulePreset.js +307 -0
  29. package/src/generate/module/generateModulePreset.ts +337 -0
  30. package/src/generate/module/generateSchemaFromType.js +46 -8
  31. package/src/generate/module/generateSchemaFromType.ts +52 -8
  32. package/src/generate/module/repositoryModuleShared.ts +665 -0
  33. package/src/utils/contextUtils.ts +89 -0
  34. package/src/utils/fileUtils.ts +100 -0
  35. package/src/utils/loadConfig.ts +69 -0
  36. package/src/commands/generate/generateCrudBase.js +0 -188
  37. package/src/commands/generate/generateCrudPresenter.js +0 -225
  38. package/src/commands/generate/generateModule.js +0 -31
  39. package/src/commands/generate/generateModuleBase.js +0 -130
  40. package/src/commands/generate/generateModulePresenter.js +0 -103
  41. package/src/commands/generate/generatePresenter.js +0 -80
  42. package/src/commands/generate/generateRepository.js +0 -70
  43. package/src/commands/generate/generateSchema.js +0 -100
  44. package/src/commands/generate/generateService.js +0 -66
  45. 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';