@azure-net/cli 1.4.2 → 2.0.1
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 +88 -37
- package/package.json +1 -1
- package/src/commands/generate/generateCrud.js +350 -0
- package/src/commands/generate/generateDatasource.js +41 -0
- package/src/commands/generate/generateModule.js +23 -0
- package/src/commands/generate/generatePresenter.js +113 -0
- package/src/commands/generate/generateRepository.js +102 -0
- package/src/commands/generate/generateResponse.js +42 -0
- package/src/commands/generate/generateSchema.js +95 -0
- package/src/commands/generate/generateService.js +93 -0
- package/src/commands/generate/index.js +8 -0
- package/src/commands/init/index.js +7 -0
- package/src/commands/init/initAliases.js +50 -0
- package/src/commands/init/initEdges.js +42 -0
- package/src/commands/init/initMiddleware.js +43 -0
- package/src/commands/init/initSchema.js +19 -0
- package/src/commands/init/initStructure.js +79 -0
- package/src/commands/init/initTranslations.js +102 -0
- package/src/utils/contextUtils.js +53 -0
- package/src/utils/fileUtils.js +79 -0
- package/src/utils/loadConfig.js +2 -2
- package/src/utils/providerUtils.js +107 -0
- package/.idea/azure-net-ecosystem-cli.iml +0 -9
- package/.idea/modules.xml +0 -8
- package/src/commands/generateCrud.js +0 -135
- package/src/commands/generateDatasource.js +0 -44
- package/src/commands/generateRepo.js +0 -69
- package/src/commands/generateRequest.js +0 -95
- package/src/commands/generateService.js +0 -77
- package/src/commands/generateStructure.js +0 -65
- package/src/commands/initAliases.js +0 -101
- /package/src/commands/{initLint.js → init/initLint.js} +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import prompts from 'prompts';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { selectContext, getContextPath, toPascalCase, getAvailableFiles, toCamelCase } from '../../utils/contextUtils.js';
|
|
5
|
+
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
6
|
+
import { ensureProvider, addToProvider } from '../../utils/providerUtils.js';
|
|
7
|
+
|
|
8
|
+
const repositoryTemplate = `import { {{datasource}} } from '{{datasourceImport}}';
|
|
9
|
+
|
|
10
|
+
export class {{name}}Repository {
|
|
11
|
+
\tconstructor(private {{datasourceVar}}: {{datasource}}) {}
|
|
12
|
+
\t
|
|
13
|
+
\tpublic async example() {
|
|
14
|
+
\t\treturn this.{{datasourceVar}}.createRequest(({ http }) =>
|
|
15
|
+
\t\t\thttp.get('/endpoint')
|
|
16
|
+
\t\t).then(res => res.getData());
|
|
17
|
+
\t}
|
|
18
|
+
}`;
|
|
19
|
+
|
|
20
|
+
export default async function generateRepository() {
|
|
21
|
+
const context = await selectContext('Select context for repository:');
|
|
22
|
+
|
|
23
|
+
if (context === 'core') {
|
|
24
|
+
console.error('❌ Cannot create repository in core. Choose a specific context.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { name } = await prompts({
|
|
29
|
+
type: 'text',
|
|
30
|
+
name: 'name',
|
|
31
|
+
message: 'Repository name (without "Repository" suffix):'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Get available datasources
|
|
35
|
+
const contextPath = getContextPath(context);
|
|
36
|
+
const coreDatasources = await getAvailableFiles(
|
|
37
|
+
path.join(process.cwd(), 'src/app/core/Datasource')
|
|
38
|
+
);
|
|
39
|
+
const contextDatasources = await getAvailableFiles(
|
|
40
|
+
path.join(contextPath, 'Infrastructure', 'Http', 'Datasource')
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const allDatasources = [
|
|
44
|
+
...coreDatasources.map(d => ({ title: `${d} (core)`, value: { name: d, from: 'core' } })),
|
|
45
|
+
...contextDatasources.map(d => ({ title: `${d} (${context})`, value: { name: d, from: context } }))
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
if (allDatasources.length === 0) {
|
|
49
|
+
console.error('❌ No datasources available. Create a datasource first.');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { datasource } = await prompts({
|
|
54
|
+
type: 'select',
|
|
55
|
+
name: 'datasource',
|
|
56
|
+
message: 'Select datasource:',
|
|
57
|
+
choices: allDatasources
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const pascalName = toPascalCase(name);
|
|
61
|
+
const contextName = toPascalCase(context);
|
|
62
|
+
const repoPath = path.join(contextPath, 'Infrastructure', 'Http', 'Repositories');
|
|
63
|
+
const filePath = path.join(repoPath, `${pascalName}Repository.ts`);
|
|
64
|
+
|
|
65
|
+
// Generate repository
|
|
66
|
+
const datasourceImport = datasource.from === 'core'
|
|
67
|
+
? '$core/Datasource'
|
|
68
|
+
: '../Datasource';
|
|
69
|
+
|
|
70
|
+
const content = repositoryTemplate
|
|
71
|
+
.replace(/{{name}}/g, pascalName)
|
|
72
|
+
.replace(/{{datasource}}/g, datasource.name)
|
|
73
|
+
.replace(/{{datasourceImport}}/g, datasourceImport)
|
|
74
|
+
.replace(/{{datasourceVar}}/g, toCamelCase(datasource.name));
|
|
75
|
+
|
|
76
|
+
await writeIfNotExists(filePath, content);
|
|
77
|
+
await updateIndexTs(repoPath);
|
|
78
|
+
|
|
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
|
+
console.log(`✅ Repository created at ${filePath}`);
|
|
102
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import prompts from 'prompts';
|
|
2
|
+
import { selectContext, getContextPath, toPascalCase } from '../../utils/contextUtils.js';
|
|
3
|
+
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
const responseTemplate = `import { ResponseBuilder } from '@azure-net/kit';
|
|
7
|
+
|
|
8
|
+
export interface I{{name}}Response<T = unknown> {
|
|
9
|
+
\tdata: T;
|
|
10
|
+
\tsuccess: boolean;
|
|
11
|
+
\tmessage: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class {{name}}Response<TData = unknown, TMeta = unknown> extends ResponseBuilder<TData, TMeta, I{{name}}Response<TData>> {
|
|
15
|
+
\toverride unwrapData(data: I{{name}}Response<TData>): TData {
|
|
16
|
+
\t\treturn data.data;
|
|
17
|
+
\t}
|
|
18
|
+
}`;
|
|
19
|
+
|
|
20
|
+
export default async function generateResponse() {
|
|
21
|
+
const context = await selectContext();
|
|
22
|
+
|
|
23
|
+
const { name } = await prompts({
|
|
24
|
+
type: 'text',
|
|
25
|
+
name: 'name',
|
|
26
|
+
message: 'Response name (PascalCase):'
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const pascalName = toPascalCase(name);
|
|
30
|
+
const contextPath = getContextPath(context);
|
|
31
|
+
const responsePath = context === 'core'
|
|
32
|
+
? path.join(contextPath, 'Responses')
|
|
33
|
+
: path.join(contextPath, 'Infrastructure', 'Responses');
|
|
34
|
+
|
|
35
|
+
const content = responseTemplate.replace(/{{name}}/g, pascalName);
|
|
36
|
+
const filePath = path.join(responsePath, `${pascalName}Response.ts`);
|
|
37
|
+
|
|
38
|
+
await writeIfNotExists(filePath, content);
|
|
39
|
+
await updateIndexTs(responsePath);
|
|
40
|
+
|
|
41
|
+
console.log(`✅ Response created at ${filePath}`);
|
|
42
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
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 schemaWithCoreTemplate = `import { {{coreSchema}} } from '$core/Schema';
|
|
7
|
+
import type { I{{name}}Request } from '${{context}}/Domain/Ports/{{entity}}';
|
|
8
|
+
|
|
9
|
+
export const {{name}}Schema = {{coreSchema}}<I{{name}}Request>()
|
|
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
|
+
import type { I{{name}}Request } from '${{context}}/Domain/Ports/{{entity}}';
|
|
18
|
+
|
|
19
|
+
const Schema = createSchemaFactory(createRules(validationMessagesI18n));
|
|
20
|
+
|
|
21
|
+
export const {{name}}Schema = Schema<I{{name}}Request>()
|
|
22
|
+
\t.rules((rules) => ({
|
|
23
|
+
\t\t// Add validation rules here
|
|
24
|
+
\t}))
|
|
25
|
+
\t.create();`;
|
|
26
|
+
|
|
27
|
+
export default async function generateSchema() {
|
|
28
|
+
const context = await selectContext('Select context for schema:');
|
|
29
|
+
|
|
30
|
+
if (context === 'core') {
|
|
31
|
+
console.error('❌ Cannot create schema in core. Choose a specific context.');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { module } = await prompts({
|
|
36
|
+
type: 'text',
|
|
37
|
+
name: 'module',
|
|
38
|
+
message: 'Module name (folder in Delivery):'
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const { name } = await prompts({
|
|
42
|
+
type: 'text',
|
|
43
|
+
name: 'name',
|
|
44
|
+
message: 'Schema name (without "Schema" suffix):'
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Check for core schemas
|
|
48
|
+
const coreSchemas = await getAvailableFiles(
|
|
49
|
+
path.join(process.cwd(), 'src/app/core/Schema')
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const choices = [
|
|
53
|
+
{ title: 'Use createSchemaFactory from package', value: 'package' },
|
|
54
|
+
...coreSchemas.map(s => ({ title: `Use ${s} from core`, value: s }))
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const { schemaType } = await prompts({
|
|
58
|
+
type: 'select',
|
|
59
|
+
name: 'schemaType',
|
|
60
|
+
message: 'Select schema factory:',
|
|
61
|
+
choices
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const pascalName = toPascalCase(name);
|
|
65
|
+
const moduleName = toPascalCase(module);
|
|
66
|
+
const contextPath = getContextPath(context);
|
|
67
|
+
const schemaPath = path.join(contextPath, 'Delivery', moduleName, 'Schema');
|
|
68
|
+
const filePath = path.join(schemaPath, `${pascalName}Schema.ts`);
|
|
69
|
+
|
|
70
|
+
const content = schemaType === 'package'
|
|
71
|
+
? schemaWithPackageTemplate
|
|
72
|
+
.replace(/{{name}}/g, pascalName)
|
|
73
|
+
.replace(/{{context}}/g, context)
|
|
74
|
+
.replace(/{{entity}}/g, moduleName)
|
|
75
|
+
: schemaWithCoreTemplate
|
|
76
|
+
.replace(/{{name}}/g, pascalName)
|
|
77
|
+
.replace(/{{context}}/g, context)
|
|
78
|
+
.replace(/{{entity}}/g, moduleName)
|
|
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', moduleName, 'index.ts');
|
|
86
|
+
if (await fs.access(moduleIndexPath).then(() => true).catch(() => false)) {
|
|
87
|
+
let indexContent = await fs.readFile(moduleIndexPath, 'utf-8');
|
|
88
|
+
if (!indexContent.includes(`export * from './Schema'`)) {
|
|
89
|
+
indexContent += `\nexport * from './Schema';`;
|
|
90
|
+
await fs.writeFile(moduleIndexPath, indexContent, 'utf-8');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.log(`✅ Schema created at ${filePath}`);
|
|
95
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import prompts from 'prompts';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { selectContext, getContextPath, toPascalCase, getAvailableFiles } from '../../utils/contextUtils.js';
|
|
5
|
+
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
6
|
+
import { ensureProvider, addToProvider } from '../../utils/providerUtils.js';
|
|
7
|
+
|
|
8
|
+
const serviceTemplate = `import { ClassMirror } from '@azure-net/kit';
|
|
9
|
+
import { {{repository}} } from '../../Infrastructure/Repositories/index.js';
|
|
10
|
+
|
|
11
|
+
export class {{name}}Service extends ClassMirror<{{repository}}> {
|
|
12
|
+
\tconstructor(private {{repositoryVar}}: {{repository}}) {
|
|
13
|
+
\t\tsuper({{repositoryVar}});
|
|
14
|
+
\t}
|
|
15
|
+
\t
|
|
16
|
+
\tdeclare example: {{repository}}['example'];
|
|
17
|
+
}`;
|
|
18
|
+
|
|
19
|
+
const serviceWithoutRepoTemplate = `export class {{name}}Service {
|
|
20
|
+
\tconstructor() {}
|
|
21
|
+
\t
|
|
22
|
+
\tpublic async example() {
|
|
23
|
+
\t\t// Implement service logic
|
|
24
|
+
\t\treturn {};
|
|
25
|
+
\t}
|
|
26
|
+
}`;
|
|
27
|
+
|
|
28
|
+
export default async function generateService() {
|
|
29
|
+
const context = await selectContext('Select context for service:');
|
|
30
|
+
|
|
31
|
+
if (context === 'core') {
|
|
32
|
+
console.error('❌ Cannot create service in core. Choose a specific context.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const { name } = await prompts({
|
|
37
|
+
type: 'text',
|
|
38
|
+
name: 'name',
|
|
39
|
+
message: 'Service name (without "Service" suffix):'
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Get available repositories
|
|
43
|
+
const contextPath = getContextPath(context);
|
|
44
|
+
const repositories = await getAvailableFiles(
|
|
45
|
+
path.join(contextPath, 'Infrastructure', 'Repositories')
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const choices = [
|
|
49
|
+
{ title: 'Without repository', value: null },
|
|
50
|
+
...repositories.map(r => ({ title: `${r}Repository`, value: `${r}Repository` }))
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
const { repository } = await prompts({
|
|
54
|
+
type: 'select',
|
|
55
|
+
name: 'repository',
|
|
56
|
+
message: 'Select repository:',
|
|
57
|
+
choices
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const pascalName = toPascalCase(name);
|
|
61
|
+
const servicePath = path.join(contextPath, 'Application', 'Services');
|
|
62
|
+
const filePath = path.join(servicePath, `${pascalName}Service.ts`);
|
|
63
|
+
|
|
64
|
+
// Generate service
|
|
65
|
+
const content = repository
|
|
66
|
+
? serviceTemplate
|
|
67
|
+
.replace(/{{name}}/g, pascalName)
|
|
68
|
+
.replace(/{{repository}}/g, repository)
|
|
69
|
+
.replace(/{{repositoryVar}}/g, repository.charAt(0).toLowerCase() + repository.slice(1))
|
|
70
|
+
: serviceWithoutRepoTemplate.replace(/{{name}}/g, pascalName);
|
|
71
|
+
|
|
72
|
+
await writeIfNotExists(filePath, content);
|
|
73
|
+
await updateIndexTs(servicePath);
|
|
74
|
+
|
|
75
|
+
// Ensure ApplicationProvider exists and add service
|
|
76
|
+
const appProvider = await ensureProvider(context, 'Application', { infrastructure: true });
|
|
77
|
+
await addToProvider(
|
|
78
|
+
appProvider.path,
|
|
79
|
+
`${pascalName}Service`,
|
|
80
|
+
'../Services/index.js'
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Add repository dependency if selected
|
|
84
|
+
if (repository) {
|
|
85
|
+
let providerContent = await fs.readFile(appProvider.path, 'utf-8');
|
|
86
|
+
const serviceFactory = `${pascalName}Service: () => new ${pascalName}Service()`;
|
|
87
|
+
const serviceWithRepo = `${pascalName}Service: () => new ${pascalName}Service(InfrastructureProvider.${repository})`;
|
|
88
|
+
providerContent = providerContent.replace(serviceFactory, serviceWithRepo);
|
|
89
|
+
await fs.writeFile(appProvider.path, providerContent, 'utf-8');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log(`✅ Service created at ${filePath}`);
|
|
93
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { default as generateDatasource } from './generateDatasource.js';
|
|
2
|
+
export { default as generateResponse } from './generateResponse.js';
|
|
3
|
+
export { default as generateRepository } from './generateRepository.js';
|
|
4
|
+
export { default as generateService } from './generateService.js';
|
|
5
|
+
export { default as generateSchema } from './generateSchema.js';
|
|
6
|
+
export { default as generatePresenter } from './generatePresenter.js';
|
|
7
|
+
export { default as generateModule } from './generateModule.js';
|
|
8
|
+
export { default as generateCrud } from './generateCrud.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as initStructure } from './initStructure.js';
|
|
2
|
+
export { default as initAliases } from './initAliases.js';
|
|
3
|
+
export { default as initMiddleware } from './initMiddleware.js';
|
|
4
|
+
export { default as initEdges } from './initEdges.js';
|
|
5
|
+
export { default as initTranslations } from './initTranslations.js';
|
|
6
|
+
export { default as initSchema } from './initSchema.js';
|
|
7
|
+
export { default as initLint } from './initLint.js';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { loadUserConfig } from '../../utils/loadConfig.js';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
|
|
6
|
+
const svelteConfigPath = path.resolve('svelte.config.js');
|
|
7
|
+
|
|
8
|
+
function generateAliases(config) {
|
|
9
|
+
const contexts = config.contexts || ['app'];
|
|
10
|
+
|
|
11
|
+
return Object.fromEntries([
|
|
12
|
+
...contexts.map(c => [`$${c}`, `./src/app/contexts/${c}`]),
|
|
13
|
+
['$core', './src/app/core'],
|
|
14
|
+
['$lib', './src/lib']
|
|
15
|
+
]);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function serializeObjectLiteral(obj) {
|
|
19
|
+
return Object.entries(obj)
|
|
20
|
+
.map(([key, value]) => `\t\t\t'${key}': '${value}'`)
|
|
21
|
+
.join(',\n');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default async function initAliases() {
|
|
25
|
+
const config = await loadUserConfig();
|
|
26
|
+
const newAliases = generateAliases(config);
|
|
27
|
+
|
|
28
|
+
let content = await fs.readFile(svelteConfigPath, 'utf-8');
|
|
29
|
+
|
|
30
|
+
const aliasRegex = /alias:\s*{([\s\S]*?)}/m;
|
|
31
|
+
const aliasMatch = content.match(aliasRegex);
|
|
32
|
+
|
|
33
|
+
const newAliasBlock = `alias: {\n${serializeObjectLiteral(newAliases)}\n\t\t}`;
|
|
34
|
+
|
|
35
|
+
if (aliasMatch) {
|
|
36
|
+
content = content.replace(aliasRegex, newAliasBlock);
|
|
37
|
+
} else {
|
|
38
|
+
const kitRegex = /kit:\s*{/;
|
|
39
|
+
content = content.replace(kitRegex, `kit: {\n\t\t${newAliasBlock},`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await fs.writeFile(svelteConfigPath, content, 'utf-8');
|
|
43
|
+
console.log('✅ Aliases updated in svelte.config.js');
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
execSync('npm run format', { stdio: 'inherit' });
|
|
47
|
+
} catch {
|
|
48
|
+
console.warn('⚠️ Failed to run format');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { injectIntoFile, writeIfNotExists } from '../../utils/fileUtils.js';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const hooksServerPath = path.join(process.cwd(), 'src/hooks.server.ts');
|
|
5
|
+
|
|
6
|
+
const hooksTemplate = `import { dev } from '$app/environment';
|
|
7
|
+
import { edgesHandle } from '@azure-net/kit/edges/server';
|
|
8
|
+
import { type Handle } from '@sveltejs/kit';
|
|
9
|
+
|
|
10
|
+
export const handle: Handle = async ({ event, resolve }) => {
|
|
11
|
+
\treturn edgesHandle(
|
|
12
|
+
\t\tevent,
|
|
13
|
+
\t\tasync ({ edgesEvent, serialize }) => {
|
|
14
|
+
\t\t\treturn resolve(edgesEvent, {
|
|
15
|
+
\t\t\t\ttransformPageChunk: ({ html }) => serialize(html)
|
|
16
|
+
\t\t\t});
|
|
17
|
+
\t\t},
|
|
18
|
+
\t\tdev
|
|
19
|
+
\t);
|
|
20
|
+
};`;
|
|
21
|
+
|
|
22
|
+
export default async function initEdges() {
|
|
23
|
+
const created = await writeIfNotExists(hooksServerPath, hooksTemplate);
|
|
24
|
+
|
|
25
|
+
if (!created) {
|
|
26
|
+
const importStatement = `import { edgesHandle } from '@azure-net/kit/edges/server';`;
|
|
27
|
+
await injectIntoFile(hooksServerPath, 'import {', importStatement, 'before');
|
|
28
|
+
|
|
29
|
+
const handleCode = `\treturn edgesHandle(
|
|
30
|
+
\t\tevent,
|
|
31
|
+
\t\tasync ({ edgesEvent, serialize }) => {`;
|
|
32
|
+
|
|
33
|
+
await injectIntoFile(
|
|
34
|
+
hooksServerPath,
|
|
35
|
+
'export const handle: Handle = async ({ event, resolve }) => {',
|
|
36
|
+
handleCode,
|
|
37
|
+
'after'
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log('✅ Edges-svelte initialized');
|
|
42
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { writeIfNotExists, injectIntoFile } from '../../utils/fileUtils.js';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const middlewarePath = path.join(process.cwd(), 'src/app/core/Middleware/MiddlewareManager.ts');
|
|
5
|
+
const hooksServerPath = path.join(process.cwd(), 'src/hooks.server.ts');
|
|
6
|
+
const layoutPath = path.join(process.cwd(), 'src/routes/+layout.svelte');
|
|
7
|
+
|
|
8
|
+
const middlewareTemplate = `import { createMiddlewareManager } from '@azure-net/kit';
|
|
9
|
+
|
|
10
|
+
export const { clientMiddleware, serverMiddleware } = createMiddlewareManager([]);`;
|
|
11
|
+
|
|
12
|
+
export default async function initMiddleware() {
|
|
13
|
+
await writeIfNotExists(middlewarePath, middlewareTemplate);
|
|
14
|
+
await writeIfNotExists(
|
|
15
|
+
path.join(process.cwd(), 'src/app/core/Middleware/index.ts'),
|
|
16
|
+
`export * from './MiddlewareManager';`
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// Add to hooks.server.ts
|
|
20
|
+
await injectIntoFile(
|
|
21
|
+
hooksServerPath,
|
|
22
|
+
'import',
|
|
23
|
+
`import { serverMiddleware } from '$core';`,
|
|
24
|
+
'before'
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
await injectIntoFile(
|
|
28
|
+
hooksServerPath,
|
|
29
|
+
'async ({ edgesEvent, serialize }) => {',
|
|
30
|
+
'\t\t\tawait serverMiddleware();',
|
|
31
|
+
'after'
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// Add to +layout.svelte
|
|
35
|
+
await injectIntoFile(
|
|
36
|
+
layoutPath,
|
|
37
|
+
'<script',
|
|
38
|
+
`\timport { clientMiddleware } from '$core';\n\tclientMiddleware();`,
|
|
39
|
+
'after'
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
console.log('✅ Middleware initialized');
|
|
43
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { writeIfNotExists } from '../../utils/fileUtils.js';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const schemaPath = path.join(process.cwd(), 'src/app/core/Schemas/Schema.ts');
|
|
5
|
+
|
|
6
|
+
const schemaTemplate = `import { createSchemaFactory } from '@azure-net/kit';
|
|
7
|
+
import { createRules, validationMessagesI18n } from '@azure-net/kit/schema';
|
|
8
|
+
|
|
9
|
+
export const Schema = createSchemaFactory(createRules(validationMessagesI18n));`;
|
|
10
|
+
|
|
11
|
+
export default async function initSchema() {
|
|
12
|
+
await writeIfNotExists(schemaPath, schemaTemplate);
|
|
13
|
+
await writeIfNotExists(
|
|
14
|
+
path.join(process.cwd(), 'src/app/core/Schemas/index.ts'),
|
|
15
|
+
`export * from './Schema';`
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
console.log('✅ Schema factory initialized');
|
|
19
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { loadUserConfig } from '../../utils/loadConfig.js';
|
|
4
|
+
|
|
5
|
+
const APP_ROOT = path.join(process.cwd(), 'src', 'app');
|
|
6
|
+
const CONTEXTS_PATH = path.join(APP_ROOT, 'contexts');
|
|
7
|
+
const CORE_PATH = path.join(APP_ROOT, 'core');
|
|
8
|
+
|
|
9
|
+
async function createDirIfNotExists(dirPath) {
|
|
10
|
+
try {
|
|
11
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
12
|
+
console.log(`📁 Created: ${dirPath}`);
|
|
13
|
+
} catch (e) {
|
|
14
|
+
console.error(`❌ Failed to create ${dirPath}:`, e.message);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function createIndexFile(dirPath, exportPatterns = []) {
|
|
19
|
+
const indexPath = path.join(dirPath, 'index.ts');
|
|
20
|
+
if (exportPatterns.length > 0) {
|
|
21
|
+
const content = exportPatterns.map(pattern => `export * from '${pattern}';`).join('\n') + '\n';
|
|
22
|
+
await fs.writeFile(indexPath, content, 'utf-8');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function createBaseStructure(root) {
|
|
27
|
+
// Domain
|
|
28
|
+
const domainPath = path.join(root, 'Domain');
|
|
29
|
+
await createDirIfNotExists(path.join(domainPath, 'Entities'));
|
|
30
|
+
await createDirIfNotExists(path.join(domainPath, 'Ports'));
|
|
31
|
+
|
|
32
|
+
// Infrastructure
|
|
33
|
+
const infraPath = path.join(root, 'Infrastructure');
|
|
34
|
+
await createDirIfNotExists(path.join(infraPath, 'Http', 'Repositories'));
|
|
35
|
+
await createDirIfNotExists(path.join(infraPath, 'Http', 'Datasource'));
|
|
36
|
+
await createDirIfNotExists(path.join(infraPath, 'Providers'));
|
|
37
|
+
|
|
38
|
+
// Application
|
|
39
|
+
const appPath = path.join(root, 'Application');
|
|
40
|
+
await createDirIfNotExists(path.join(appPath, 'Services'));
|
|
41
|
+
await createDirIfNotExists(path.join(appPath, 'Providers'));
|
|
42
|
+
|
|
43
|
+
// Delivery - organized by modules, not by type
|
|
44
|
+
const deliveryPath = path.join(root, 'Delivery');
|
|
45
|
+
await createDirIfNotExists(deliveryPath);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default async function initStructure() {
|
|
49
|
+
const config = await loadUserConfig();
|
|
50
|
+
const contexts = config.contexts || ['app'];
|
|
51
|
+
|
|
52
|
+
console.log('📦 Generating architecture...');
|
|
53
|
+
|
|
54
|
+
// Create contexts
|
|
55
|
+
for (const context of contexts) {
|
|
56
|
+
const contextPath = path.join(CONTEXTS_PATH, context);
|
|
57
|
+
await createBaseStructure(contextPath);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Create core structure
|
|
61
|
+
await createDirIfNotExists(CORE_PATH);
|
|
62
|
+
await createDirIfNotExists(path.join(CORE_PATH, 'Datasource'));
|
|
63
|
+
await createDirIfNotExists(path.join(CORE_PATH, 'Response'));
|
|
64
|
+
await createDirIfNotExists(path.join(CORE_PATH, 'Schema'));
|
|
65
|
+
await createDirIfNotExists(path.join(CORE_PATH, 'Middleware'));
|
|
66
|
+
await createDirIfNotExists(path.join(CORE_PATH, 'Presenter'));
|
|
67
|
+
await createDirIfNotExists(path.join(CORE_PATH, 'Translation'));
|
|
68
|
+
|
|
69
|
+
// Create core index.ts that exports all subdirectories
|
|
70
|
+
await createIndexFile(CORE_PATH, [
|
|
71
|
+
'./Schema',
|
|
72
|
+
'./Datasource',
|
|
73
|
+
'./Response',
|
|
74
|
+
'./Middleware',
|
|
75
|
+
'./Translation'
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
console.log('✅ Structure initialization complete!');
|
|
79
|
+
}
|