@azure-net/cli 1.3.0 → 1.3.2

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 CHANGED
@@ -5,6 +5,7 @@ import generateRepository from '../src/commands/generateCrudRepo.js';
5
5
  import generateCrud from '../src/commands/generateCrud.js';
6
6
  import initLint from '../src/commands/initLint.js';
7
7
  import initStructure from '../src/commands/generateStructure.js';
8
+ import initAliases from '../src/commands/initAliases.js';
8
9
 
9
10
  const program = new Command();
10
11
 
@@ -32,4 +33,9 @@ program
32
33
  .description('Generate base folder structure based on config')
33
34
  .action(initStructure);
34
35
 
36
+ program
37
+ .command('init:aliases')
38
+ .description('Generate alias mappings for modules or default architecture')
39
+ .action(initAliases);
40
+
35
41
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-net/cli",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "azure-net": "bin/azure-net.js"
@@ -17,98 +17,83 @@ async function writeIfNotExists(filepath, content) {
17
17
  }
18
18
  }
19
19
 
20
+ async function updateIndexTs(dir, filePattern = '.ts', ignore = ['index.ts']) {
21
+ const files = (await fs.readdir(dir)).filter(f => f.endsWith(filePattern) && !ignore.includes(f));
22
+ const content = files.map(f => `export * from './${f.replace('.ts', '')}';`).join('\n') + '\n';
23
+ await fs.writeFile(path.join(dir, 'index.ts'), content, 'utf-8');
24
+ }
25
+
20
26
  export default async function generateCrud() {
21
27
  const config = await loadUserConfig();
22
28
 
23
29
  const answers = await prompts([
30
+ config.modules?.length
31
+ ? {
32
+ type: 'select',
33
+ name: 'module',
34
+ message: 'Select target module:',
35
+ choices: config.modules.map(m => ({ title: m, value: m }))
36
+ }
37
+ : null,
24
38
  { type: 'text', name: 'className', message: 'Class name (PascalCase):' },
25
39
  { type: 'text', name: 'endpoint', message: 'API endpoint:' },
26
40
  { type: 'text', name: 'datasource', message: 'Datasource name:', initial: 'BaseDatasource' }
27
- ]);
41
+ ].filter(Boolean));
28
42
 
29
43
  const rawName = answers.className.trim();
30
44
  const capital = rawName[0].toUpperCase() + rawName.slice(1);
31
45
  const lower = rawName[0].toLowerCase() + rawName.slice(1);
32
46
  const endpoint = answers.endpoint.trim();
33
47
  const datasource = answers.datasource.trim();
48
+ const selectedModule = answers.module;
34
49
 
35
- // === Domain lowercase folder ===
36
- const domainPath = path.join(process.cwd(), config.output.domain, lower);
37
- const repoPath = path.join(process.cwd(), config.output.repo);
50
+ const baseArch = path.join(process.cwd(), 'src/app/context');
51
+ const basePath = selectedModule ? path.join(baseArch, selectedModule) : baseArch;
38
52
 
39
- // 1) Abstracts
53
+ const domainPath = path.join(basePath, 'domain', lower);
54
+ const serviceDir = path.join(basePath, 'application', 'services');
55
+ const repoPath = path.join(basePath, 'infra', 'repo');
56
+
57
+ // === 1) Abstracts
40
58
  const abstractsDir = path.join(domainPath, 'abstracts');
41
59
  for (const file of ['Class', 'ClassCreateRequest', 'ClassUpdateRequest']) {
42
60
  const tpl = await fs.readFile(path.join(__dirname, `../templates/domain/abstracts/${file}.ejs`), 'utf-8');
43
61
  const result = ejs.render(tpl, { className: capital });
44
62
  await writeIfNotExists(path.join(abstractsDir, `${capital}${file.replace('Class', '')}.ts`), result);
45
63
  }
46
- await writeIfNotExists(
47
- path.join(abstractsDir, `index.ts`),
48
- [
49
- `export * from './${capital}';`,
50
- `export * from './${capital}CreateRequest';`,
51
- `export * from './${capital}UpdateRequest';`
52
- ].join('\n')
53
- );
64
+ await updateIndexTs(abstractsDir);
54
65
 
55
- // 2) Request
66
+ // === 2) Request
56
67
  const requestDir = path.join(domainPath, 'request');
57
68
  for (const file of ['ClassCreateRequest', 'ClassUpdateRequest']) {
58
69
  const tpl = await fs.readFile(path.join(__dirname, `../templates/domain/request/${file}.ejs`), 'utf-8');
59
70
  const result = ejs.render(tpl, { className: capital });
60
71
  await writeIfNotExists(path.join(requestDir, `${capital}${file.replace('Class', '')}.ts`), result);
61
72
  }
62
- await writeIfNotExists(
63
- path.join(requestDir, `index.ts`),
64
- [
65
- `export * from './${capital}CreateRequest';`,
66
- `export * from './${capital}UpdateRequest';`
67
- ].join('\n')
68
- );
73
+ await updateIndexTs(requestDir);
69
74
 
70
- // === 3) Services ===
71
- const serviceDir = path.join(domainPath, 'services');
75
+ // === 3) Services
72
76
  const serviceTpl = await fs.readFile(path.join(__dirname, '../templates/domain/services/ClassService.ejs'), 'utf-8');
73
- const serviceResult = ejs.render(serviceTpl, {
74
- className: capital,
75
- domainName: lower
76
- });
77
+ const serviceResult = ejs.render(serviceTpl, { className: capital, domainName: lower });
77
78
  await writeIfNotExists(path.join(serviceDir, `${capital}Service.ts`), serviceResult);
79
+ await updateIndexTs(serviceDir);
78
80
 
79
- // ✅ Services index.ts
80
- await writeIfNotExists(
81
- path.join(serviceDir, 'index.ts'),
82
- `export * from './${capital}Service';\n`
83
- );
84
-
85
- // === 4) Domain Index ===
81
+ // === 4) Domain Index
86
82
  await writeIfNotExists(
87
83
  path.join(domainPath, 'index.ts'),
88
- [
89
- `export * from './abstracts';`,
90
- `export * from './request';`,
91
- `export * from './services';`
92
- ].join('\n')
84
+ [`export * from './abstracts';`, `export * from './request';`].join('\n') + '\n'
93
85
  );
94
86
 
95
- // === 5) Generate Repo ===
87
+ // === 5) Repo
96
88
  const repoTpl = await fs.readFile(path.join(__dirname, '../templates/data/repo/ClassRepo.ejs'), 'utf-8');
97
89
  const repoResult = ejs.render(repoTpl, {
98
90
  className: capital,
99
91
  endpoint,
100
92
  domainName: lower,
101
- datasource // <-- 👈 Передаём!
93
+ datasource
102
94
  });
103
95
  await writeIfNotExists(path.join(repoPath, `${capital}Repo.ts`), repoResult);
96
+ await updateIndexTs(repoPath);
104
97
 
105
- // === 6) Repo Index ===
106
- const files = await fs.readdir(repoPath);
107
- const exports = files
108
- .filter(f => f.endsWith('Repo.ts') && f !== 'index.ts')
109
- .map(f => `export * from './${f.replace('.ts', '')}';`)
110
- .join('\n');
111
- await fs.writeFile(path.join(repoPath, 'index.ts'), exports, 'utf-8');
112
-
113
- console.log(`✅ CRUD for ${capital} generated successfully!`);
98
+ console.log(`✅ CRUD for ${capital} generated in ${selectedModule || 'monolith'} structure`);
114
99
  }
@@ -0,0 +1,98 @@
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
+ /** Файл конфигурации */
7
+ const svelteConfigPath = path.resolve('svelte.config.js');
8
+
9
+ function generateAliases(config) {
10
+ const hasModules = Array.isArray(config.modules) && config.modules.length > 0;
11
+
12
+ if (hasModules) {
13
+ return Object.fromEntries(
14
+ config.modules.map(m => [`$${m}`, `./src/app/context/${m}`])
15
+ );
16
+ }
17
+
18
+ return {
19
+ '$domain': './src/app/context/domain',
20
+ '$infra': './src/app/context/infra',
21
+ '$application': './src/app/context/application',
22
+ '$presentation': './src/app/context/presentation',
23
+ '$services': './src/app/context/application/services'
24
+ };
25
+ }
26
+
27
+ function parseObjectLiteral(text) {
28
+ const obj = {};
29
+ const entries = text.split(/,(?![^{]*})/).filter(Boolean);
30
+ for (const entry of entries) {
31
+ const [key, value] = entry.split(':').map(s => s.trim());
32
+ if (key && value) {
33
+ obj[key.replace(/^['"]|['"]$/g, '')] = value.replace(/^['"]|['"]$/g, '');
34
+ }
35
+ }
36
+ return obj;
37
+ }
38
+
39
+ function serializeObjectLiteral(obj) {
40
+ return Object.entries(obj)
41
+ .map(([key, value]) => `\t\t\t'${key}': '${value}'`)
42
+ .join(',\n');
43
+ }
44
+
45
+ function insertAliasBlock(content, aliasBlock) {
46
+ const kitRegex = /kit:\s*{([\s\S]*?)}/m;
47
+ const match = content.match(kitRegex);
48
+
49
+ if (!match) {
50
+ throw new Error('❌ Cannot find `kit: {}` block in svelte.config.js');
51
+ }
52
+
53
+ const existingKit = match[0];
54
+ const newKit = existingKit.includes('alias:')
55
+ ? existingKit.replace(/alias:\s*{([\s\S]*?)}/m, aliasBlock)
56
+ : existingKit.replace(/{/, `{\n\t\t${aliasBlock},`);
57
+
58
+ return content.replace(kitRegex, newKit);
59
+ }
60
+
61
+ async function updateAliases() {
62
+ const config = await loadUserConfig();
63
+ const newAliases = generateAliases(config);
64
+
65
+ let content = await fs.readFile(svelteConfigPath, 'utf-8');
66
+
67
+ // если alias уже есть
68
+ const aliasRegex = /alias:\s*{([\s\S]*?)}/m;
69
+ const aliasMatch = content.match(aliasRegex);
70
+
71
+ let updatedAliases = {};
72
+
73
+ if (aliasMatch) {
74
+ const existingAliases = parseObjectLiteral(aliasMatch[1]);
75
+ updatedAliases = { ...existingAliases, ...newAliases };
76
+ } else {
77
+ updatedAliases = { ...newAliases };
78
+ }
79
+
80
+ const newAliasBlock = `alias: {\n${serializeObjectLiteral(updatedAliases)}\n\t\t}`;
81
+
82
+ content = aliasMatch
83
+ ? content.replace(aliasRegex, newAliasBlock)
84
+ : insertAliasBlock(content, newAliasBlock);
85
+
86
+ await fs.writeFile(svelteConfigPath, content, 'utf-8');
87
+ console.log('✅ Aliases updated in svelte.config.js');
88
+
89
+ // Run formatter
90
+ try {
91
+ execSync('npm run format', { stdio: 'inherit' });
92
+ console.log('✅ Ran npm run format');
93
+ } catch {
94
+ console.warn('⚠️ Failed to run format. Make sure you have a format script in package.json');
95
+ }
96
+ }
97
+
98
+ export default updateAliases;
@@ -1,6 +1,6 @@
1
1
  import { BaseService } from '@azure-net/kit';
2
2
  import { <%= className %>Repo } from '$data/repo';
3
- import type { <%= className %>CreateRequest, <%= className %>UpdateRequest } from '$domain/<%= domainName %>/request';
3
+ import type { <%= className %>CreateRequest, <%= className %>UpdateRequest } from '$domain/<%= domainName %>';
4
4
 
5
5
  export class <%= className %>Service extends BaseService {
6
6
  constructor(private <%= domainName %>Repo = new <%= className %>Repo()) {
@@ -8,10 +8,6 @@ export async function loadUserConfig() {
8
8
  return userConfig.default || {};
9
9
  } catch {
10
10
  return {
11
- output: {
12
- domain: 'src/app/architecture/domain',
13
- repo: 'src/app/architecture/infra/repo'
14
- },
15
11
  modules: ['admin', 'auth']
16
12
  };
17
13
  }