@azure-net/cli 2.0.4 → 2.0.6
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 +23 -5
- package/package.json +1 -1
- package/src/commands/generate/generateCrudBase.js +188 -0
- package/src/commands/generate/generateCrudPresenter.js +220 -0
- package/src/commands/generate/generateDatasource.js +18 -89
- package/src/commands/generate/generateModule.js +9 -1
- package/src/commands/generate/generatePresenter.js +19 -49
- package/src/commands/generate/generatePresenterByService.js +102 -0
- package/src/commands/generate/generateRepository.js +9 -38
- package/src/commands/generate/generateResponse.js +6 -3
- package/src/commands/generate/generateService.js +3 -26
- package/src/commands/generate/generateServiceByRepo.js +86 -0
- package/src/commands/generate/index.js +4 -1
- package/src/commands/init/initAliases.js +1 -1
- package/src/commands/init/initMiddleware.js +4 -4
- package/src/commands/init/initSchema.js +2 -2
- package/src/commands/init/initStructure.js +76 -15
- package/src/commands/init/initTranslations.js +4 -4
- package/src/utils/contextUtils.js +25 -4
- package/src/commands/generate/generateCrud.js +0 -413
- package/src/utils/providerUtils.js +0 -112
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import prompts from 'prompts';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import fs from 'fs/promises';
|
|
3
4
|
import { selectContext, getContextPath, toPascalCase, getAvailableFiles } from '../../utils/contextUtils.js';
|
|
4
|
-
import { writeIfNotExists
|
|
5
|
+
import { writeIfNotExists } from '../../utils/fileUtils.js';
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
{{
|
|
7
|
+
const presenterWithSharedTemplate = `import { {{sharedPresenter}} } from '$shared/Presenter';
|
|
8
|
+
import { ApplicationProvider } from '\${{context}}/Application';
|
|
8
9
|
|
|
9
|
-
export const {{name}}Presenter = {{
|
|
10
|
-
\
|
|
10
|
+
export const {{name}}Presenter = {{sharedPresenter}}('{{name}}Presenter', ({ createAsyncResource, createAsyncAction }) => {
|
|
11
|
+
\tconst { /* extract services from ApplicationProvider */ } = ApplicationProvider();
|
|
11
12
|
\t
|
|
12
13
|
\tconst example = async () => {
|
|
13
|
-
\t\t// Using async helpers from
|
|
14
|
+
\t\t// Using async helpers from shared presenter factory
|
|
14
15
|
\t\treturn await createAsyncResource(Promise.resolve({}));
|
|
15
16
|
\t};
|
|
16
17
|
\t
|
|
@@ -18,10 +19,10 @@ export const {{name}}Presenter = {{corePresenter}}('{{name}}Presenter', ({ creat
|
|
|
18
19
|
});`;
|
|
19
20
|
|
|
20
21
|
const presenterWithPackageTemplate = `import { createPresenter } from '@azure-net/kit';
|
|
21
|
-
{{
|
|
22
|
+
import { ApplicationProvider } from '\${{context}}/Application';
|
|
22
23
|
|
|
23
24
|
export const {{name}}Presenter = createPresenter('{{name}}Presenter', () => {
|
|
24
|
-
\
|
|
25
|
+
\tconst { /* extract services from ApplicationProvider */ } = ApplicationProvider();
|
|
25
26
|
\t
|
|
26
27
|
\tconst example = async () => {
|
|
27
28
|
\t\t// Direct method without async helpers
|
|
@@ -34,25 +35,20 @@ export const {{name}}Presenter = createPresenter('{{name}}Presenter', () => {
|
|
|
34
35
|
export default async function generatePresenter() {
|
|
35
36
|
const context = await selectContext('Select context for presenter:');
|
|
36
37
|
|
|
37
|
-
if (context === 'core') {
|
|
38
|
-
console.error('❌ Cannot create presenter in core. Choose a specific context.');
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
38
|
const { name } = await prompts({
|
|
43
39
|
type: 'text',
|
|
44
40
|
name: 'name',
|
|
45
41
|
message: 'Module name (will create folder in Delivery):'
|
|
46
42
|
});
|
|
47
43
|
|
|
48
|
-
// Check for
|
|
49
|
-
const
|
|
50
|
-
path.join(process.cwd(), 'src/app/
|
|
44
|
+
// Check for shared presenters
|
|
45
|
+
const sharedPresenters = await getAvailableFiles(
|
|
46
|
+
path.join(process.cwd(), 'src/app/shared/Presenter')
|
|
51
47
|
);
|
|
52
48
|
|
|
53
49
|
const presenterChoices = [
|
|
54
50
|
{ title: 'Use createPresenter from package', value: 'package' },
|
|
55
|
-
...
|
|
51
|
+
...sharedPresenters.map(p => ({ title: `Use ${p} from shared`, value: p }))
|
|
56
52
|
];
|
|
57
53
|
|
|
58
54
|
const { presenterType } = await prompts({
|
|
@@ -62,46 +58,19 @@ export default async function generatePresenter() {
|
|
|
62
58
|
choices: presenterChoices
|
|
63
59
|
});
|
|
64
60
|
|
|
65
|
-
// Get available services
|
|
66
|
-
const contextPath = getContextPath(context);
|
|
67
|
-
const services = await getAvailableFiles(
|
|
68
|
-
path.join(contextPath, 'Application/Services')
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const serviceChoices = [
|
|
72
|
-
{ title: 'Without service', value: null },
|
|
73
|
-
...services.map(s => ({ title: s, value: s }))
|
|
74
|
-
];
|
|
75
|
-
|
|
76
|
-
const { service } = await prompts({
|
|
77
|
-
type: 'select',
|
|
78
|
-
name: 'service',
|
|
79
|
-
message: 'Select service (optional):',
|
|
80
|
-
choices: serviceChoices
|
|
81
|
-
});
|
|
82
|
-
|
|
83
61
|
const pascalName = toPascalCase(name);
|
|
62
|
+
const contextPath = getContextPath(context);
|
|
84
63
|
const modulePath = path.join(contextPath, 'Delivery', pascalName);
|
|
85
64
|
const filePath = path.join(modulePath, `${pascalName}Presenter.ts`);
|
|
86
65
|
|
|
87
|
-
const serviceImport = service
|
|
88
|
-
? `import { ApplicationProvider } from '\$${context}/Application';`
|
|
89
|
-
: '';
|
|
90
|
-
|
|
91
|
-
const serviceInit = service
|
|
92
|
-
? `const { ${service} } = ApplicationProvider();`
|
|
93
|
-
: '';
|
|
94
|
-
|
|
95
66
|
const content = presenterType === 'package'
|
|
96
67
|
? presenterWithPackageTemplate
|
|
97
68
|
.replace(/{{name}}/g, pascalName)
|
|
98
|
-
.replace(/{{
|
|
99
|
-
|
|
100
|
-
: presenterWithCoreTemplate
|
|
69
|
+
.replace(/{{context}}/g, context)
|
|
70
|
+
: presenterWithSharedTemplate
|
|
101
71
|
.replace(/{{name}}/g, pascalName)
|
|
102
|
-
.replace(/{{
|
|
103
|
-
.replace(/{{
|
|
104
|
-
.replace(/{{serviceInit}}/g, serviceInit);
|
|
72
|
+
.replace(/{{sharedPresenter}}/g, presenterType)
|
|
73
|
+
.replace(/{{context}}/g, context);
|
|
105
74
|
|
|
106
75
|
await writeIfNotExists(filePath, content);
|
|
107
76
|
await writeIfNotExists(
|
|
@@ -110,4 +79,5 @@ export default async function generatePresenter() {
|
|
|
110
79
|
);
|
|
111
80
|
|
|
112
81
|
console.log(`✅ Presenter created at ${filePath}`);
|
|
82
|
+
console.log(`\n💡 Remember to extract needed services from ApplicationProvider in the presenter.`);
|
|
113
83
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import prompts from 'prompts';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { selectContext, getContextPath, toPascalCase, getApplicationProviderServices, getAvailableFiles } from '../../utils/contextUtils.js';
|
|
4
|
+
import { writeIfNotExists } from '../../utils/fileUtils.js';
|
|
5
|
+
|
|
6
|
+
const presenterWithSharedTemplate = `import { {{presenterFactory}} } from '$shared/Presenter';
|
|
7
|
+
import { ApplicationProvider } from '\${{context}}/Application';
|
|
8
|
+
|
|
9
|
+
export const {{name}}Presenter = {{presenterFactory}}('{{name}}Presenter', ({ createAsyncResource, createAsyncAction }) => {
|
|
10
|
+
\tconst { {{serviceName}} } = ApplicationProvider();
|
|
11
|
+
\t
|
|
12
|
+
{{methods}}
|
|
13
|
+
\t
|
|
14
|
+
\treturn { {{exports}} };
|
|
15
|
+
});`;
|
|
16
|
+
|
|
17
|
+
const presenterWithPackageTemplate = `import { createPresenter } from '@azure-net/kit';
|
|
18
|
+
import { ApplicationProvider } from '\${{context}}/Application';
|
|
19
|
+
|
|
20
|
+
export const {{name}}Presenter = createPresenter('{{name}}Presenter', () => {
|
|
21
|
+
\tconst { {{serviceName}} } = ApplicationProvider();
|
|
22
|
+
\t
|
|
23
|
+
{{methods}}
|
|
24
|
+
\t
|
|
25
|
+
\treturn { {{exports}} };
|
|
26
|
+
});`;
|
|
27
|
+
|
|
28
|
+
export default async function generatePresenterByService() {
|
|
29
|
+
const context = await selectContext('Select context:');
|
|
30
|
+
|
|
31
|
+
// Get available services from ApplicationProvider
|
|
32
|
+
const services = await getApplicationProviderServices(context);
|
|
33
|
+
|
|
34
|
+
if (services.length === 0) {
|
|
35
|
+
console.error('❌ No services found in ApplicationProvider. Add services manually first.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { service } = await prompts({
|
|
40
|
+
type: 'select',
|
|
41
|
+
name: 'service',
|
|
42
|
+
message: 'Select service to create presenter from:',
|
|
43
|
+
choices: services.map(s => ({ title: s, value: s }))
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Get presenter factory
|
|
47
|
+
const sharedPresenters = await getAvailableFiles(
|
|
48
|
+
path.join(process.cwd(), 'src/app/shared/Presenter')
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const { presenterType } = await prompts({
|
|
52
|
+
type: 'select',
|
|
53
|
+
name: 'presenterType',
|
|
54
|
+
message: 'Select presenter factory:',
|
|
55
|
+
choices: [
|
|
56
|
+
{ title: 'Use createPresenter from package', value: 'package' },
|
|
57
|
+
...sharedPresenters.map(p => ({ title: `Use ${p} from shared`, value: p }))
|
|
58
|
+
]
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const entityName = service.replace('Service', '');
|
|
62
|
+
const pascalName = toPascalCase(entityName);
|
|
63
|
+
const contextPath = getContextPath(context);
|
|
64
|
+
const deliveryModulePath = path.join(contextPath, 'Delivery', pascalName);
|
|
65
|
+
|
|
66
|
+
// Generate method declarations based on common service patterns
|
|
67
|
+
const commonMethods = ['collection', 'resource', 'create', 'update', 'remove'];
|
|
68
|
+
|
|
69
|
+
const methods = presenterType === 'package'
|
|
70
|
+
? commonMethods.map(m => `\tconst ${m} = async (...args: Parameters<typeof ${service}['${m}']>) =>
|
|
71
|
+
\t\tawait ${service}.${m}(...args);`).join('\n\n')
|
|
72
|
+
: commonMethods.map(m => `\tconst ${m} = async (...args: Parameters<typeof ${service}['${m}']>) =>
|
|
73
|
+
\t\tawait createAsyncResource(${service}.${m}(...args));`).join('\n\n');
|
|
74
|
+
|
|
75
|
+
const exports = commonMethods.join(', ');
|
|
76
|
+
|
|
77
|
+
const template = presenterType === 'package'
|
|
78
|
+
? presenterWithPackageTemplate
|
|
79
|
+
: presenterWithSharedTemplate;
|
|
80
|
+
|
|
81
|
+
const presenterFactory = presenterType === 'package' ? 'createPresenter' : presenterType;
|
|
82
|
+
|
|
83
|
+
await writeIfNotExists(
|
|
84
|
+
path.join(deliveryModulePath, `${pascalName}Presenter.ts`),
|
|
85
|
+
template
|
|
86
|
+
.replace(/{{name}}/g, pascalName)
|
|
87
|
+
.replace(/{{context}}/g, context)
|
|
88
|
+
.replace(/{{serviceName}}/g, service)
|
|
89
|
+
.replace(/{{presenterFactory}}/g, presenterFactory)
|
|
90
|
+
.replace(/{{methods}}/g, methods)
|
|
91
|
+
.replace(/{{exports}}/g, exports)
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Create module index
|
|
95
|
+
await writeIfNotExists(
|
|
96
|
+
path.join(deliveryModulePath, 'index.ts'),
|
|
97
|
+
`export * from './${pascalName}Presenter';`
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
console.log(`✅ Presenter for ${service} created successfully!`);
|
|
101
|
+
console.log(`\n💡 Note: Methods are based on common patterns. Adjust them to match your actual service methods.`);
|
|
102
|
+
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import prompts from 'prompts';
|
|
2
|
-
import fs from 'fs/promises';
|
|
3
2
|
import path from 'path';
|
|
4
3
|
import { selectContext, getContextPath, toPascalCase, getAvailableFiles, toCamelCase } from '../../utils/contextUtils.js';
|
|
5
4
|
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
6
|
-
import { ensureProvider, addToProvider } from '../../utils/providerUtils.js';
|
|
7
5
|
|
|
8
6
|
const repositoryTemplate = `import { {{datasource}} } from '{{datasourceImport}}';
|
|
9
7
|
|
|
@@ -20,11 +18,6 @@ export class {{name}}Repository {
|
|
|
20
18
|
export default async function generateRepository() {
|
|
21
19
|
const context = await selectContext('Select context for repository:');
|
|
22
20
|
|
|
23
|
-
if (context === 'core') {
|
|
24
|
-
console.error('❌ Cannot create repository in core. Choose a specific context.');
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
21
|
const { name } = await prompts({
|
|
29
22
|
type: 'text',
|
|
30
23
|
name: 'name',
|
|
@@ -33,15 +26,15 @@ export default async function generateRepository() {
|
|
|
33
26
|
|
|
34
27
|
// Get available datasources
|
|
35
28
|
const contextPath = getContextPath(context);
|
|
36
|
-
const
|
|
37
|
-
path.join(process.cwd(), 'src/app/
|
|
29
|
+
const sharedDatasources = await getAvailableFiles(
|
|
30
|
+
path.join(process.cwd(), 'src/app/shared/Datasource')
|
|
38
31
|
);
|
|
39
32
|
const contextDatasources = await getAvailableFiles(
|
|
40
|
-
path.join(contextPath, 'Infrastructure
|
|
33
|
+
path.join(contextPath, 'Infrastructure/Http/Datasource')
|
|
41
34
|
);
|
|
42
35
|
|
|
43
36
|
const allDatasources = [
|
|
44
|
-
...
|
|
37
|
+
...sharedDatasources.map(d => ({ title: `${d} (shared)`, value: { name: d, from: 'shared' } })),
|
|
45
38
|
...contextDatasources.map(d => ({ title: `${d} (${context})`, value: { name: d, from: context } }))
|
|
46
39
|
];
|
|
47
40
|
|
|
@@ -58,14 +51,13 @@ export default async function generateRepository() {
|
|
|
58
51
|
});
|
|
59
52
|
|
|
60
53
|
const pascalName = toPascalCase(name);
|
|
61
|
-
const
|
|
62
|
-
const repoPath = path.join(contextPath, 'Infrastructure', 'Http', 'Repositories');
|
|
54
|
+
const repoPath = path.join(contextPath, 'Infrastructure/Http/Repositories');
|
|
63
55
|
const filePath = path.join(repoPath, `${pascalName}Repository.ts`);
|
|
64
56
|
|
|
65
57
|
// Generate repository
|
|
66
|
-
const datasourceImport = datasource.from === '
|
|
67
|
-
? '$
|
|
68
|
-
:
|
|
58
|
+
const datasourceImport = datasource.from === 'shared'
|
|
59
|
+
? '$shared/Datasource'
|
|
60
|
+
: `\$${context}/Infrastructure/Http/Datasource`;
|
|
69
61
|
|
|
70
62
|
const content = repositoryTemplate
|
|
71
63
|
.replace(/{{name}}/g, pascalName)
|
|
@@ -76,27 +68,6 @@ export default async function generateRepository() {
|
|
|
76
68
|
await writeIfNotExists(filePath, content);
|
|
77
69
|
await updateIndexTs(repoPath);
|
|
78
70
|
|
|
79
|
-
// Ensure DatasourceProvider exists
|
|
80
|
-
const datasourceProviderPath = path.join(contextPath, 'Infrastructure', 'Providers', 'DatasourceProvider.ts');
|
|
81
|
-
if (!(await fs.access(datasourceProviderPath).then(() => true).catch(() => false))) {
|
|
82
|
-
const datasourceProviderContent = `import { createBoundaryProvider } from '@azure-net/kit';
|
|
83
|
-
import { ${datasource.name} } from '${datasource.from === 'core' ? '$core/Datasource' : '../Http/Datasource'}';
|
|
84
|
-
|
|
85
|
-
export const DatasourceProvider = createBoundaryProvider('${contextName}DatasourceProvider', () => ({
|
|
86
|
-
\t${datasource.name}: () => new ${datasource.name}()
|
|
87
|
-
}));`;
|
|
88
|
-
await writeIfNotExists(datasourceProviderPath, datasourceProviderContent);
|
|
89
|
-
await updateIndexTs(path.dirname(datasourceProviderPath));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Ensure InfrastructureProvider and add repository
|
|
93
|
-
const infraProvider = await ensureProvider(context, 'Infrastructure', { hasDatasource: true });
|
|
94
|
-
await addToProvider(
|
|
95
|
-
infraProvider.path,
|
|
96
|
-
`${pascalName}Repository`,
|
|
97
|
-
'../Http/Repositories',
|
|
98
|
-
`DatasourceProvider.${datasource.name}`
|
|
99
|
-
);
|
|
100
|
-
|
|
101
71
|
console.log(`✅ Repository created at ${filePath}`);
|
|
72
|
+
console.log(`\n💡 Remember to manually add this repository to InfrastructureProvider when needed.`);
|
|
102
73
|
}
|
|
@@ -18,7 +18,7 @@ export class {{name}}Response<TData = unknown, TMeta = unknown> extends Response
|
|
|
18
18
|
}`;
|
|
19
19
|
|
|
20
20
|
export default async function generateResponse() {
|
|
21
|
-
const context = await selectContext();
|
|
21
|
+
const context = await selectContext('Select context for response (or shared):');
|
|
22
22
|
|
|
23
23
|
const { name } = await prompts({
|
|
24
24
|
type: 'text',
|
|
@@ -27,8 +27,11 @@ export default async function generateResponse() {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
const pascalName = toPascalCase(name);
|
|
30
|
-
const contextPath =
|
|
31
|
-
|
|
30
|
+
const contextPath = context === 'shared'
|
|
31
|
+
? path.join(process.cwd(), 'src/app/shared')
|
|
32
|
+
: getContextPath(context);
|
|
33
|
+
|
|
34
|
+
const responsePath = context === 'shared'
|
|
32
35
|
? path.join(contextPath, 'Response')
|
|
33
36
|
: path.join(contextPath, 'Infrastructure/Response');
|
|
34
37
|
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import prompts from 'prompts';
|
|
2
|
-
import fs from 'fs/promises';
|
|
3
2
|
import path from 'path';
|
|
4
3
|
import { selectContext, getContextPath, toPascalCase, getAvailableFiles } from '../../utils/contextUtils.js';
|
|
5
4
|
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
6
|
-
import { ensureProvider, addToProvider } from '../../utils/providerUtils.js';
|
|
7
5
|
|
|
8
6
|
const serviceTemplate = `import { ClassMirror } from '@azure-net/kit';
|
|
9
|
-
import { {{repository}} } from '
|
|
7
|
+
import { {{repository}} } from '\${{context}}/Infrastructure/Http/Repositories';
|
|
10
8
|
|
|
11
9
|
export class {{name}}Service extends ClassMirror<{{repository}}> {
|
|
12
10
|
\tconstructor(private {{repositoryVar}}: {{repository}}) {
|
|
@@ -28,11 +26,6 @@ const serviceWithoutRepoTemplate = `export class {{name}}Service {
|
|
|
28
26
|
export default async function generateService() {
|
|
29
27
|
const context = await selectContext('Select context for service:');
|
|
30
28
|
|
|
31
|
-
if (context === 'core') {
|
|
32
|
-
console.error('❌ Cannot create service in core. Choose a specific context.');
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
29
|
const { name } = await prompts({
|
|
37
30
|
type: 'text',
|
|
38
31
|
name: 'name',
|
|
@@ -67,28 +60,12 @@ export default async function generateService() {
|
|
|
67
60
|
.replace(/{{name}}/g, pascalName)
|
|
68
61
|
.replace(/{{repository}}/g, repository)
|
|
69
62
|
.replace(/{{repositoryVar}}/g, repository.charAt(0).toLowerCase() + repository.slice(1))
|
|
63
|
+
.replace(/{{context}}/g, context)
|
|
70
64
|
: serviceWithoutRepoTemplate.replace(/{{name}}/g, pascalName);
|
|
71
65
|
|
|
72
66
|
await writeIfNotExists(filePath, content);
|
|
73
67
|
await updateIndexTs(servicePath);
|
|
74
68
|
|
|
75
|
-
// Ensure ApplicationProvider exists and add service
|
|
76
|
-
const appProvider = await ensureProvider(context, 'Application', { infrastructure: true });
|
|
77
|
-
|
|
78
|
-
if (repository) {
|
|
79
|
-
await addToProvider(
|
|
80
|
-
appProvider.path,
|
|
81
|
-
`${pascalName}Service`,
|
|
82
|
-
'../Services',
|
|
83
|
-
`InfrastructureProvider.${repository}`
|
|
84
|
-
);
|
|
85
|
-
} else {
|
|
86
|
-
await addToProvider(
|
|
87
|
-
appProvider.path,
|
|
88
|
-
`${pascalName}Service`,
|
|
89
|
-
'../Services'
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
69
|
console.log(`✅ Service created at ${filePath}`);
|
|
70
|
+
console.log(`\n💡 Remember to manually add this service to ApplicationProvider when needed.`);
|
|
94
71
|
}
|
|
@@ -0,0 +1,86 @@
|
|
|
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 serviceTemplate = `import { ClassMirror } from '@azure-net/kit';
|
|
8
|
+
import { {{repository}} } from '\${{context}}/Infrastructure/Http/Repositories';
|
|
9
|
+
|
|
10
|
+
export class {{name}}Service extends ClassMirror<{{repository}}> {
|
|
11
|
+
\tconstructor(private {{repositoryVar}}: {{repository}}) {
|
|
12
|
+
\t\tsuper({{repositoryVar}});
|
|
13
|
+
\t}
|
|
14
|
+
\t
|
|
15
|
+
{{methodDeclarations}}
|
|
16
|
+
}`;
|
|
17
|
+
|
|
18
|
+
export default async function generateServiceByRepo() {
|
|
19
|
+
const context = await selectContext('Select context:');
|
|
20
|
+
|
|
21
|
+
const contextPath = getContextPath(context);
|
|
22
|
+
const repositories = await getAvailableFiles(
|
|
23
|
+
path.join(contextPath, 'Infrastructure/Http/Repositories')
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (repositories.length === 0) {
|
|
27
|
+
console.error('❌ No repositories available. Create a repository first.');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { repository } = await prompts({
|
|
32
|
+
type: 'select',
|
|
33
|
+
name: 'repository',
|
|
34
|
+
message: 'Select repository to create service from:',
|
|
35
|
+
choices: repositories.map(r => ({ title: r, value: r }))
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const serviceName = repository.replace('Repository', 'Service');
|
|
39
|
+
const servicePath = path.join(contextPath, 'Application/Services');
|
|
40
|
+
const filePath = path.join(servicePath, `${serviceName}.ts`);
|
|
41
|
+
|
|
42
|
+
// Try to get repository file to extract methods
|
|
43
|
+
const repoFilePath = path.join(contextPath, 'Infrastructure/Http/Repositories', `${repository}.ts`);
|
|
44
|
+
let methodDeclarations = '';
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const repoContent = await fs.readFile(repoFilePath, 'utf-8');
|
|
48
|
+
// Extract public methods from repository
|
|
49
|
+
const methodRegex = /public async (\w+)\([^)]*\)(?:\s*:\s*[^{]+)?/g;
|
|
50
|
+
const methods = [];
|
|
51
|
+
let match;
|
|
52
|
+
|
|
53
|
+
while ((match = methodRegex.exec(repoContent)) !== null) {
|
|
54
|
+
methods.push(match[1]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (methods.length > 0) {
|
|
58
|
+
methodDeclarations = methods
|
|
59
|
+
.map(m => `\tdeclare ${m}: ${repository}['${m}'];`)
|
|
60
|
+
.join('\n');
|
|
61
|
+
} else {
|
|
62
|
+
// Fallback to common CRUD methods
|
|
63
|
+
methodDeclarations = [
|
|
64
|
+
'collection', 'resource', 'create', 'update', 'remove'
|
|
65
|
+
].map(m => `\tdeclare ${m}: ${repository}['${m}'];`).join('\n');
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
// Fallback if can't read repository file
|
|
69
|
+
methodDeclarations = [
|
|
70
|
+
'collection', 'resource', 'create', 'update', 'remove'
|
|
71
|
+
].map(m => `\tdeclare ${m}: ${repository}['${m}'];`).join('\n');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const content = serviceTemplate
|
|
75
|
+
.replace(/{{name}}/g, serviceName.replace('Service', ''))
|
|
76
|
+
.replace(/{{repository}}/g, repository)
|
|
77
|
+
.replace(/{{repositoryVar}}/g, repository.charAt(0).toLowerCase() + repository.slice(1))
|
|
78
|
+
.replace(/{{context}}/g, context)
|
|
79
|
+
.replace(/{{methodDeclarations}}/g, methodDeclarations);
|
|
80
|
+
|
|
81
|
+
await writeIfNotExists(filePath, content);
|
|
82
|
+
await updateIndexTs(servicePath);
|
|
83
|
+
|
|
84
|
+
console.log(`✅ Service created at ${filePath}`);
|
|
85
|
+
console.log(`\n💡 Remember to manually add this service to ApplicationProvider when needed.`);
|
|
86
|
+
}
|
|
@@ -5,4 +5,7 @@ export { default as generateService } from './generateService.js';
|
|
|
5
5
|
export { default as generateSchema } from './generateSchema.js';
|
|
6
6
|
export { default as generatePresenter } from './generatePresenter.js';
|
|
7
7
|
export { default as generateModule } from './generateModule.js';
|
|
8
|
-
export { default as
|
|
8
|
+
export { default as generateCrudBase } from './generateCrudBase.js';
|
|
9
|
+
export { default as generateCrudPresenter } from './generateCrudPresenter.js';
|
|
10
|
+
export { default as generatePresenterByService } from './generatePresenterByService.js';
|
|
11
|
+
export { default as generateServiceByRepo } from './generateServiceByRepo.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { writeIfNotExists, injectIntoFile } from '../../utils/fileUtils.js';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
|
-
const middlewarePath = path.join(process.cwd(), 'src/app/
|
|
4
|
+
const middlewarePath = path.join(process.cwd(), 'src/app/shared/Middleware/MiddlewareManager.ts');
|
|
5
5
|
const hooksServerPath = path.join(process.cwd(), 'src/hooks.server.ts');
|
|
6
6
|
const layoutPath = path.join(process.cwd(), 'src/routes/+layout.svelte');
|
|
7
7
|
|
|
@@ -12,7 +12,7 @@ export const { clientMiddleware, serverMiddleware } = createMiddlewareManager([]
|
|
|
12
12
|
export default async function initMiddleware() {
|
|
13
13
|
await writeIfNotExists(middlewarePath, middlewareTemplate);
|
|
14
14
|
await writeIfNotExists(
|
|
15
|
-
path.join(process.cwd(), 'src/app/
|
|
15
|
+
path.join(process.cwd(), 'src/app/shared/Middleware/index.ts'),
|
|
16
16
|
`export * from './MiddlewareManager';`
|
|
17
17
|
);
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@ export default async function initMiddleware() {
|
|
|
20
20
|
await injectIntoFile(
|
|
21
21
|
hooksServerPath,
|
|
22
22
|
'import',
|
|
23
|
-
`import { serverMiddleware } from '$
|
|
23
|
+
`import { serverMiddleware } from '$shared';`,
|
|
24
24
|
'before'
|
|
25
25
|
);
|
|
26
26
|
|
|
@@ -35,7 +35,7 @@ export default async function initMiddleware() {
|
|
|
35
35
|
await injectIntoFile(
|
|
36
36
|
layoutPath,
|
|
37
37
|
'<script',
|
|
38
|
-
`\timport { clientMiddleware } from '$
|
|
38
|
+
`\timport { clientMiddleware } from '$shared';\n\tclientMiddleware();`,
|
|
39
39
|
'after'
|
|
40
40
|
);
|
|
41
41
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { writeIfNotExists } from '../../utils/fileUtils.js';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
|
-
const schemaPath = path.join(process.cwd(), 'src/app/
|
|
4
|
+
const schemaPath = path.join(process.cwd(), 'src/app/shared/Schema/Schema.ts');
|
|
5
5
|
|
|
6
6
|
const schemaTemplate = `import { createSchemaFactory } from '@azure-net/kit';
|
|
7
7
|
import { createRules, validationMessagesI18n } from '@azure-net/kit/schema';
|
|
@@ -11,7 +11,7 @@ export const Schema = createSchemaFactory(createRules(validationMessagesI18n));`
|
|
|
11
11
|
export default async function initSchema() {
|
|
12
12
|
await writeIfNotExists(schemaPath, schemaTemplate);
|
|
13
13
|
await writeIfNotExists(
|
|
14
|
-
path.join(process.cwd(), 'src/app/
|
|
14
|
+
path.join(process.cwd(), 'src/app/shared/Schema/index.ts'),
|
|
15
15
|
`export * from './Schema';`
|
|
16
16
|
);
|
|
17
17
|
|