@azure-net/cli 1.4.2 → 2.0.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 (32) hide show
  1. package/bin/azure-net.js +82 -37
  2. package/package.json +1 -1
  3. package/src/commands/generate/generateCrud.js +323 -0
  4. package/src/commands/generate/generateDatasource.js +36 -0
  5. package/src/commands/generate/generateModule.js +23 -0
  6. package/src/commands/generate/generatePresenter.js +113 -0
  7. package/src/commands/generate/generateRepository.js +97 -0
  8. package/src/commands/generate/generateResponse.js +42 -0
  9. package/src/commands/generate/generateSchema.js +70 -0
  10. package/src/commands/generate/generateService.js +93 -0
  11. package/src/commands/generate/index.js +8 -0
  12. package/src/commands/init/index.js +6 -0
  13. package/src/commands/init/initAliases.js +50 -0
  14. package/src/commands/init/initEdges.js +42 -0
  15. package/src/commands/init/initMiddleware.js +58 -0
  16. package/src/commands/init/initSchema.js +19 -0
  17. package/src/commands/init/initStructure.js +68 -0
  18. package/src/commands/init/initTranslations.js +97 -0
  19. package/src/utils/contextUtils.js +53 -0
  20. package/src/utils/fileUtils.js +60 -0
  21. package/src/utils/loadConfig.js +2 -2
  22. package/src/utils/providerUtils.js +78 -0
  23. package/.idea/azure-net-ecosystem-cli.iml +0 -9
  24. package/.idea/modules.xml +0 -8
  25. package/src/commands/generateCrud.js +0 -135
  26. package/src/commands/generateDatasource.js +0 -44
  27. package/src/commands/generateRepo.js +0 -69
  28. package/src/commands/generateRequest.js +0 -95
  29. package/src/commands/generateService.js +0 -77
  30. package/src/commands/generateStructure.js +0 -65
  31. package/src/commands/initAliases.js +0 -101
  32. package/src/commands/initLint.js +0 -138
@@ -0,0 +1,97 @@
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 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/Datasources')
38
+ );
39
+ const contextDatasources = await getAvailableFiles(
40
+ path.join(contextPath, 'Infrastructure', 'Datasources')
41
+ );
42
+
43
+ const allDatasources = [
44
+ ...coreDatasources.map(d => ({ title: `${d}Datasource (core)`, value: { name: `${d}Datasource`, from: 'core' } })),
45
+ ...contextDatasources.map(d => ({ title: `${d}Datasource (${context})`, value: { name: `${d}Datasource`, 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 repoPath = path.join(contextPath, 'Infrastructure', 'Repositories');
62
+ const filePath = path.join(repoPath, `${pascalName}Repository.ts`);
63
+
64
+ // Generate repository
65
+ const datasourceImport = datasource.from === 'core'
66
+ ? '$core/Datasources/index.js'
67
+ : '../Datasources/index.js';
68
+
69
+ const content = repositoryTemplate
70
+ .replace(/{{name}}/g, pascalName)
71
+ .replace(/{{datasource}}/g, datasource.name)
72
+ .replace(/{{datasourceImport}}/g, datasourceImport)
73
+ .replace(/{{datasourceVar}}/g, toPascalCase(datasource.name).charAt(0).toLowerCase() + toPascalCase(datasource.name).slice(1));
74
+
75
+ await writeIfNotExists(filePath, content);
76
+ await updateIndexTs(repoPath);
77
+
78
+ // Ensure DatasourceProvider exists
79
+ const datasourceProvider = await ensureProvider(context, 'Infrastructure', { datasource: datasource.name });
80
+
81
+ // Ensure InfrastructureProvider exists and add repository
82
+ const infraProvider = await ensureProvider(context, 'Infrastructure', { datasource: datasource.name });
83
+ await addToProvider(
84
+ infraProvider.path,
85
+ `${pascalName}Repository`,
86
+ '../Repositories/index.js'
87
+ );
88
+
89
+ // Add datasource dependency to repository in provider
90
+ let providerContent = await fs.readFile(infraProvider.path, 'utf-8');
91
+ const repoFactory = `${pascalName}Repository: () => new ${pascalName}Repository()`;
92
+ const repoWithDatasource = `${pascalName}Repository: () => new ${pascalName}Repository(DatasourceProvider.${datasource.name})`;
93
+ providerContent = providerContent.replace(repoFactory, repoWithDatasource);
94
+ await fs.writeFile(infraProvider.path, providerContent, 'utf-8');
95
+
96
+ console.log(`✅ Repository created at ${filePath}`);
97
+ }
@@ -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,70 @@
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/Schemas/index.js';
7
+ import type { I{{name}}Request } from '../../Domain/Ports/{{name}}/index.js';
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 { schema } from '@azure-net/kit';
16
+ import type { I{{name}}Request } from '../../Domain/Ports/{{name}}/index.js';
17
+
18
+ export const {{name}}Schema = schema<I{{name}}Request>()
19
+ \t.rules((rules) => ({
20
+ \t\t// Add validation rules here
21
+ \t}))
22
+ \t.create();`;
23
+
24
+ export default async function generateSchema() {
25
+ const context = await selectContext('Select context for schema:');
26
+
27
+ if (context === 'core') {
28
+ console.error('❌ Cannot create schema in core. Choose a specific context.');
29
+ return;
30
+ }
31
+
32
+ const { name } = await prompts({
33
+ type: 'text',
34
+ name: 'name',
35
+ message: 'Schema name (without "Schema" suffix):'
36
+ });
37
+
38
+ // Check for core schemas
39
+ const coreSchemas = await getAvailableFiles(
40
+ path.join(process.cwd(), 'src/app/core/Schemas')
41
+ );
42
+
43
+ const choices = [
44
+ { title: 'Use schema from package', value: 'package' },
45
+ ...coreSchemas.map(s => ({ title: `Use ${s} from core`, value: s }))
46
+ ];
47
+
48
+ const { schemaType } = await prompts({
49
+ type: 'select',
50
+ name: 'schemaType',
51
+ message: 'Select schema factory:',
52
+ choices
53
+ });
54
+
55
+ const pascalName = toPascalCase(name);
56
+ const contextPath = getContextPath(context);
57
+ const schemaPath = path.join(contextPath, 'Delivery', 'Schemas');
58
+ const filePath = path.join(schemaPath, `${pascalName}Schema.ts`);
59
+
60
+ const content = schemaType === 'package'
61
+ ? schemaWithPackageTemplate.replace(/{{name}}/g, pascalName)
62
+ : schemaWithCoreTemplate
63
+ .replace(/{{name}}/g, pascalName)
64
+ .replace(/{{coreSchema}}/g, schemaType);
65
+
66
+ await writeIfNotExists(filePath, content);
67
+ await updateIndexTs(schemaPath);
68
+
69
+ console.log(`✅ Schema created at ${filePath}`);
70
+ }
@@ -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,6 @@
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';
@@ -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,58 @@
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, type IMiddleware } from '@azure-net/kit';
9
+
10
+ const AuthMiddleware: IMiddleware = async ({ next, page, event, isServer, cookies }) => {
11
+ \tconst user = isServer ? event?.locals?.user : page?.data?.user;
12
+ \tif (isServer && !user && cookies.get('token') && event) {
13
+ \t\t// Add auth logic here
14
+ \t}
15
+ \tnext();
16
+ };
17
+
18
+ const GuardMiddleware: IMiddleware = async ({ next, page, event, isServer, to }) => {
19
+ \tconst user = isServer ? event?.locals?.user : page?.data?.user;
20
+ \tif (!user && !to.pathname.startsWith('/login')) {
21
+ \t\tnext('/login');
22
+ \t}
23
+ \tif (user && to.pathname.startsWith('/login')) {
24
+ \t\tnext('/');
25
+ \t}
26
+ \tnext();
27
+ };
28
+
29
+ export const { clientMiddleware, serverMiddleware } = createMiddlewareManager([AuthMiddleware, GuardMiddleware]);`;
30
+
31
+ export default async function initMiddleware() {
32
+ await writeIfNotExists(middlewarePath, middlewareTemplate);
33
+
34
+ // Add to hooks.server.ts
35
+ await injectIntoFile(
36
+ hooksServerPath,
37
+ `import { serverMiddleware } from '$core/Middleware/index.js';`,
38
+ 'import',
39
+ 'before'
40
+ );
41
+
42
+ await injectIntoFile(
43
+ hooksServerPath,
44
+ 'async ({ edgesEvent, serialize }) => {',
45
+ '\t\t\tawait serverMiddleware();',
46
+ 'after'
47
+ );
48
+
49
+ // Add to +layout.svelte
50
+ await injectIntoFile(
51
+ layoutPath,
52
+ '<script',
53
+ `\timport { clientMiddleware } from '$core/Middleware/index.js';\n\tclientMiddleware();`,
54
+ 'after'
55
+ );
56
+
57
+ console.log('✅ Middleware initialized');
58
+ }
@@ -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/schema';
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.js';`
16
+ );
17
+
18
+ console.log('✅ Schema factory initialized');
19
+ }
@@ -0,0 +1,68 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { loadUserConfig } from '../../utils/loadConfig.js';
4
+
5
+ const BASE_STRUCTURE = ['Domain', 'Infrastructure', 'Application', 'Delivery'];
6
+ const APP_ROOT = path.join(process.cwd(), 'src', 'app');
7
+ const CONTEXTS_PATH = path.join(APP_ROOT, 'contexts');
8
+ const CORE_PATH = path.join(APP_ROOT, 'core');
9
+
10
+ async function createDirIfNotExists(dirPath) {
11
+ try {
12
+ await fs.mkdir(dirPath, { recursive: true });
13
+ console.log(`📁 Created: ${dirPath}`);
14
+ } catch (e) {
15
+ console.error(`❌ Failed to create ${dirPath}:`, e.message);
16
+ }
17
+ }
18
+
19
+ async function createBaseStructure(root) {
20
+ for (const section of BASE_STRUCTURE) {
21
+ const sectionPath = path.join(root, section);
22
+ await createDirIfNotExists(sectionPath);
23
+
24
+ if (section === 'Infrastructure') {
25
+ await createDirIfNotExists(path.join(sectionPath, 'Repositories'));
26
+ await createDirIfNotExists(path.join(sectionPath, 'Datasources'));
27
+ await createDirIfNotExists(path.join(sectionPath, 'Providers'));
28
+ }
29
+ if (section === 'Application') {
30
+ await createDirIfNotExists(path.join(sectionPath, 'Services'));
31
+ await createDirIfNotExists(path.join(sectionPath, 'Providers'));
32
+ }
33
+ if (section === 'Domain') {
34
+ await createDirIfNotExists(path.join(sectionPath, 'Entities'));
35
+ await createDirIfNotExists(path.join(sectionPath, 'Ports'));
36
+ }
37
+ if (section === 'Delivery') {
38
+ await createDirIfNotExists(path.join(sectionPath, 'Presenters'));
39
+ await createDirIfNotExists(path.join(sectionPath, 'Schemas'));
40
+ await createDirIfNotExists(path.join(sectionPath, 'Actions'));
41
+ await createDirIfNotExists(path.join(sectionPath, 'Stores'));
42
+ }
43
+ }
44
+ }
45
+
46
+ export default async function initStructure() {
47
+ const config = await loadUserConfig();
48
+ const contexts = config.contexts || ['app'];
49
+
50
+ console.log('📦 Generating architecture...');
51
+
52
+ // Create contexts
53
+ for (const context of contexts) {
54
+ const contextPath = path.join(CONTEXTS_PATH, context);
55
+ await createBaseStructure(contextPath);
56
+ }
57
+
58
+ // Create core structure
59
+ await createDirIfNotExists(CORE_PATH);
60
+ await createDirIfNotExists(path.join(CORE_PATH, 'Datasources'));
61
+ await createDirIfNotExists(path.join(CORE_PATH, 'Responses'));
62
+ await createDirIfNotExists(path.join(CORE_PATH, 'Schemas'));
63
+ await createDirIfNotExists(path.join(CORE_PATH, 'Middleware'));
64
+ await createDirIfNotExists(path.join(CORE_PATH, 'Presenters'));
65
+ await createDirIfNotExists(path.join(CORE_PATH, 'Translations'));
66
+
67
+ console.log('✅ Structure initialization complete!');
68
+ }
@@ -0,0 +1,97 @@
1
+ import { writeIfNotExists, updateIndexTs, injectIntoFile } from '../../utils/fileUtils.js';
2
+ import path from 'path';
3
+
4
+ const translationsPath = path.join(process.cwd(), 'src/app/core/Translations');
5
+ const layoutServerPath = path.join(process.cwd(), 'src/routes/+layout.server.ts');
6
+ const layoutTsPath = path.join(process.cwd(), 'src/routes/+layout.ts');
7
+
8
+ const translationProviderTemplate = `import { messages } from './Locales/index.js';
9
+ import { createTranslations } from '@azure-net/kit/i18n';
10
+
11
+ export const Translation = createTranslations({
12
+ \tmessages,
13
+ \tinitLang: 'en',
14
+ \tinitLangFromAcceptLanguage: true,
15
+ \tcookieName: 'lang'
16
+ });`;
17
+
18
+ const enLocaleTemplate = `export default {
19
+ \tapp: {
20
+ \t\ttitle: 'Application'
21
+ \t}
22
+ };`;
23
+
24
+ const ruLocaleTemplate = `export default {
25
+ \tapp: {
26
+ \t\ttitle: 'Приложение'
27
+ \t}
28
+ };`;
29
+
30
+ const localesIndexTemplate = `export const messages = {
31
+ \ten: () => import('./en.js').then((res) => res.default),
32
+ \tru: () => import('./ru.js').then((res) => res.default)
33
+ };`;
34
+
35
+ export default async function initTranslations() {
36
+ // Create translation files
37
+ await writeIfNotExists(
38
+ path.join(translationsPath, 'index.ts'),
39
+ translationProviderTemplate
40
+ );
41
+
42
+ await writeIfNotExists(
43
+ path.join(translationsPath, 'Locales', 'en.ts'),
44
+ enLocaleTemplate
45
+ );
46
+
47
+ await writeIfNotExists(
48
+ path.join(translationsPath, 'Locales', 'ru.ts'),
49
+ ruLocaleTemplate
50
+ );
51
+
52
+ await writeIfNotExists(
53
+ path.join(translationsPath, 'Locales', 'index.ts'),
54
+ localesIndexTemplate
55
+ );
56
+
57
+ await updateIndexTs(translationsPath);
58
+
59
+ // Add to hooks.server.ts
60
+ await injectIntoFile(
61
+ path.join(process.cwd(), 'src/hooks.server.ts'),
62
+ 'import',
63
+ `import { Translation } from '$core/Translations/index.js';`,
64
+ 'before'
65
+ );
66
+
67
+ await injectIntoFile(
68
+ path.join(process.cwd(), 'src/hooks.server.ts'),
69
+ 'await serverMiddleware();',
70
+ `\t\t\tconst { preloadTranslation, applyHtmlLocaleAttr } = Translation();\n\t\t\tawait preloadTranslation(edgesEvent);`,
71
+ 'after'
72
+ );
73
+
74
+ // Add to layout files
75
+ await injectIntoFile(
76
+ layoutServerPath,
77
+ 'export const load',
78
+ `\treturn { lang: locals.lang, user: locals.user };`,
79
+ 'after'
80
+ );
81
+
82
+ await injectIntoFile(
83
+ layoutTsPath,
84
+ 'import',
85
+ `import { Translation } from '$core/Translations/index.js';`,
86
+ 'before'
87
+ );
88
+
89
+ await injectIntoFile(
90
+ layoutTsPath,
91
+ 'export const load',
92
+ `\tconst { syncTranslation } = Translation();\n\tif (browser) {\n\t\tawait syncTranslation({ lang: data.lang }, false);\n\t}`,
93
+ 'after'
94
+ );
95
+
96
+ console.log('✅ Translations initialized');
97
+ }