@azure-net/cli 2.0.9 → 2.1.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 CHANGED
@@ -8,7 +8,8 @@ import {
8
8
  initEdges,
9
9
  initTranslations,
10
10
  initSchema,
11
- initLint
11
+ initLint,
12
+ initPresenter
12
13
  } from '../src/commands/init/index.js';
13
14
  import {
14
15
  generateDatasource,
@@ -67,6 +68,11 @@ program
67
68
  .description('Initialize schema factory')
68
69
  .action(initSchema);
69
70
 
71
+ program
72
+ .command('init:presenter')
73
+ .description('Initialize presenter factory')
74
+ .action(initPresenter);
75
+
70
76
  program
71
77
  .command('init')
72
78
  .description('Run all initialization steps')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-net/cli",
3
- "version": "2.0.9",
3
+ "version": "2.1.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "azure-net": "bin/azure-net.js"
@@ -1,7 +1,7 @@
1
1
  import prompts from 'prompts';
2
2
  import path from 'path';
3
3
  import { selectContext, getContextPath, toPascalCase, toCamelCase, getAvailableFiles } from '../../utils/contextUtils.js';
4
- import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
4
+ import { writeIfNotExists, updateIndexTs, updateCoreIndex } from '../../utils/fileUtils.js';
5
5
 
6
6
  // Templates for CRUD base generation
7
7
  const entityTemplate = `export interface I{{name}} {
@@ -11,7 +11,7 @@ const entityTemplate = `export interface I{{name}} {
11
11
  \tupdated_at: string;
12
12
  }`;
13
13
 
14
- const portsIndexTemplate = `import type { I{{name}} } from '\${{context}}/Domain/Entities/{{name}}';
14
+ const portsIndexTemplate = `import type { I{{name}} } from '\${{context}}/Domain/{{name}}/Model';
15
15
 
16
16
  export interface I{{name}}Collection {
17
17
  \tdata: I{{name}}[];
@@ -35,13 +35,13 @@ export interface I{{name}}UpdateRequest {
35
35
  }`;
36
36
 
37
37
  const repositoryTemplate = `import { {{datasource}} } from '{{datasourceImport}}';
38
- import type { I{{name}} } from '\${{context}}/Domain/Entities/{{name}}';
38
+ import type { I{{name}} } from '\${{context}}/Domain/{{name}}/Model';
39
39
  import type {
40
40
  \tI{{name}}Collection,
41
41
  \tI{{name}}CollectionQuery,
42
42
  \tI{{name}}CreateRequest,
43
43
  \tI{{name}}UpdateRequest
44
- } from '\${{context}}/Domain/Ports/{{name}}';
44
+ } from '\${{context}}/Domain/{{name}}/Ports';
45
45
 
46
46
  export class {{name}}Repository {
47
47
  \tprivate endpoint = '{{endpoint}}';
@@ -111,15 +111,15 @@ export default async function generateCrudBase() {
111
111
 
112
112
  // Get available datasources
113
113
  const contextPath = getContextPath(context);
114
- const sharedDatasources = await getAvailableFiles(
115
- path.join(process.cwd(), 'src/app/shared/Datasource')
114
+ const coreDatasources = await getAvailableFiles(
115
+ path.join(process.cwd(), 'src/app/core/Datasource')
116
116
  );
117
117
  const contextDatasources = await getAvailableFiles(
118
118
  path.join(contextPath, 'Infrastructure/Http/Datasource')
119
119
  );
120
120
 
121
121
  const allDatasources = [
122
- ...sharedDatasources.map(d => ({ title: `${d} (shared)`, value: { name: d, from: 'shared' } })),
122
+ ...coreDatasources.map(d => ({ title: `${d} (core)`, value: { name: d, from: 'core' } })),
123
123
  ...contextDatasources.map(d => ({ title: `${d} (${context})`, value: { name: d, from: context } }))
124
124
  ];
125
125
 
@@ -135,15 +135,18 @@ export default async function generateCrudBase() {
135
135
 
136
136
  console.log('\nšŸš€ Generating CRUD base (repository & service)...\n');
137
137
 
138
- // 1. Create Entity
139
- const entityPath = path.join(contextPath, 'Domain/Entities', pascalName);
138
+ // 1. Create Domain structure
139
+ const domainPath = path.join(contextPath, 'Domain', pascalName);
140
+ const modelPath = path.join(domainPath, 'Model');
141
+ const portsPath = path.join(domainPath, 'Ports');
142
+
143
+ // Create Model
140
144
  await writeIfNotExists(
141
- path.join(entityPath, 'index.ts'),
145
+ path.join(modelPath, 'index.ts'),
142
146
  entityTemplate.replace(/{{name}}/g, pascalName)
143
147
  );
144
148
 
145
- // 2. Create Ports
146
- const portsPath = path.join(contextPath, 'Domain/Ports', pascalName);
149
+ // Create Ports
147
150
  await writeIfNotExists(
148
151
  path.join(portsPath, 'index.ts'),
149
152
  portsIndexTemplate
@@ -151,10 +154,16 @@ export default async function generateCrudBase() {
151
154
  .replace(/{{context}}/g, context)
152
155
  );
153
156
 
154
- // 3. Create Repository
157
+ // Create Domain module index
158
+ await writeIfNotExists(
159
+ path.join(domainPath, 'index.ts'),
160
+ `export * from './Model';\nexport * from './Ports';`
161
+ );
162
+
163
+ // 2. Create Repository
155
164
  const repoPath = path.join(contextPath, 'Infrastructure/Http/Repositories');
156
- const datasourceImport = datasource.from === 'shared'
157
- ? '$shared/Datasource'
165
+ const datasourceImport = datasource.from === 'core'
166
+ ? '$core/Datasource'
158
167
  : `\$${context}/Infrastructure/Http/Datasource`;
159
168
 
160
169
  await writeIfNotExists(
@@ -169,7 +178,7 @@ export default async function generateCrudBase() {
169
178
  );
170
179
  await updateIndexTs(repoPath);
171
180
 
172
- // 4. Create Service
181
+ // 3. Create Service
173
182
  const servicePath = path.join(contextPath, 'Application/Services');
174
183
  await writeIfNotExists(
175
184
  path.join(servicePath, `${pascalName}Service.ts`),
@@ -180,6 +189,9 @@ export default async function generateCrudBase() {
180
189
  );
181
190
  await updateIndexTs(servicePath);
182
191
 
192
+ // Update core index
193
+ await updateCoreIndex();
194
+
183
195
  console.log(`āœ… CRUD base for ${pascalName} created successfully!`);
184
196
  console.log(`\nšŸ’” Remember to:`);
185
197
  console.log(` 1. Add ${pascalName}Repository to InfrastructureProvider`);
@@ -1,11 +1,10 @@
1
1
  import prompts from 'prompts';
2
2
  import path from 'path';
3
- import fs from 'fs/promises';
4
3
  import { selectContext, getContextPath, toPascalCase, getAvailableFiles, getApplicationProviderServices } from '../../utils/contextUtils.js';
5
- import {updateIndexTs, writeIfNotExists} from '../../utils/fileUtils.js';
4
+ import { updateIndexTs, writeIfNotExists, updateCoreIndex } from '../../utils/fileUtils.js';
6
5
 
7
6
  const createSchemaTemplate = `import { {{schemaFactory}} } from '{{schemaImport}}';
8
- import type { I{{name}}CreateRequest } from '\${{context}}/Domain/Ports/{{entity}}';
7
+ import type { I{{name}}CreateRequest } from '\${{context}}/Domain/{{entity}}/Ports';
9
8
 
10
9
  export const Create{{name}}Schema = {{schemaFactory}}<I{{name}}CreateRequest>()
11
10
  \t.rules((rules) => ({
@@ -14,7 +13,7 @@ export const Create{{name}}Schema = {{schemaFactory}}<I{{name}}CreateRequest>()
14
13
  \t.create();`;
15
14
 
16
15
  const updateSchemaTemplate = `import { {{schemaFactory}} } from '{{schemaImport}}';
17
- import type { I{{name}}UpdateRequest } from '\${{context}}/Domain/Ports/{{entity}}';
16
+ import type { I{{name}}UpdateRequest } from '\${{context}}/Domain/{{entity}}/Ports';
18
17
 
19
18
  export const Update{{name}}Schema = {{schemaFactory}}<I{{name}}UpdateRequest>()
20
19
  \t.rules((rules) => ({
@@ -22,14 +21,14 @@ export const Update{{name}}Schema = {{schemaFactory}}<I{{name}}UpdateRequest>()
22
21
  \t}))
23
22
  \t.create();`;
24
23
 
25
- const presenterWithSharedTemplate = `import { {{presenterFactory}} } from '$shared/Presenter';
24
+ const presenterWithCoreTemplate = `import { {{presenterFactory}} } from '$core/Presenter';
26
25
  import { ApplicationProvider } from '\${{context}}/Application';
27
26
  import { Create{{name}}Schema, Update{{name}}Schema } from './Schema';
28
27
  import type {
29
28
  \tI{{name}}CollectionQuery,
30
29
  \tI{{name}}CreateRequest,
31
30
  \tI{{name}}UpdateRequest
32
- } from '\${{context}}/Domain/Ports/{{name}}';
31
+ } from '\${{context}}/Domain/{{name}}/Ports';
33
32
 
34
33
  export const {{name}}Presenter = {{presenterFactory}}('{{name}}Presenter', ({ createAsyncResource, createAsyncAction }) => {
35
34
  \tconst { {{serviceName}} } = ApplicationProvider();
@@ -52,14 +51,14 @@ export const {{name}}Presenter = {{presenterFactory}}('{{name}}Presenter', ({ cr
52
51
  \treturn { collection, resource, create, update, remove };
53
52
  });`;
54
53
 
55
- const presenterWithoutSharedTemplate = `import { createPresenter } from '@azure-net/kit';
54
+ const presenterWithoutCoreTemplate = `import { createPresenter } from '@azure-net/kit';
56
55
  import { ApplicationProvider } from '\${{context}}/Application';
57
56
  import { Create{{name}}Schema, Update{{name}}Schema } from './Schema';
58
57
  import type {
59
58
  \tI{{name}}CollectionQuery,
60
59
  \tI{{name}}CreateRequest,
61
60
  \tI{{name}}UpdateRequest
62
- } from '\${{context}}/Domain/Ports/{{name}}';
61
+ } from '\${{context}}/Domain/{{name}}/Ports';
63
62
 
64
63
  export const {{name}}Presenter = createPresenter('{{name}}Presenter', () => {
65
64
  \tconst { {{serviceName}} } = ApplicationProvider();
@@ -74,7 +73,7 @@ export const {{name}}Presenter = createPresenter('{{name}}Presenter', () => {
74
73
  \t\tawait {{serviceName}}.create(Create{{name}}Schema.from(request).json());
75
74
  \t
76
75
  \tconst update = async (id: number, request: I{{name}}UpdateRequest) =>
77
- \t\tawait {{serviceName}}.update(id, Update{{name}}Schema.from(request).json());
76
+ \t\tawait {{serviceName}}.update(id, Update{{name}}Schema.from(request).json()));
78
77
  \t
79
78
  \tconst remove = async (id: number) =>
80
79
  \t\tawait {{serviceName}}.remove(id);
@@ -105,8 +104,8 @@ export default async function generateCrudPresenter() {
105
104
  const pascalName = toPascalCase(entityName);
106
105
 
107
106
  // Get schema factory
108
- const sharedSchemas = await getAvailableFiles(
109
- path.join(process.cwd(), 'src/app/shared/Schema')
107
+ const coreSchemas = await getAvailableFiles(
108
+ path.join(process.cwd(), 'src/app/core/Schema')
110
109
  );
111
110
 
112
111
  const { schemaType } = await prompts({
@@ -115,13 +114,13 @@ export default async function generateCrudPresenter() {
115
114
  message: 'Select schema factory:',
116
115
  choices: [
117
116
  { title: 'Use createSchemaFactory from package', value: 'package' },
118
- ...sharedSchemas.map(s => ({ title: `Use ${s} from shared`, value: s }))
117
+ ...coreSchemas.map(s => ({ title: `Use ${s} from core`, value: s }))
119
118
  ]
120
119
  });
121
120
 
122
121
  // Get presenter factory
123
- const sharedPresenters = await getAvailableFiles(
124
- path.join(process.cwd(), 'src/app/shared/Presenter')
122
+ const corePresenters = await getAvailableFiles(
123
+ path.join(process.cwd(), 'src/app/core/Presenter')
125
124
  );
126
125
 
127
126
  const { presenterType } = await prompts({
@@ -130,7 +129,7 @@ export default async function generateCrudPresenter() {
130
129
  message: 'Select presenter factory:',
131
130
  choices: [
132
131
  { title: 'Use createPresenter from package', value: 'package' },
133
- ...sharedPresenters.map(p => ({ title: `Use ${p} from shared`, value: p }))
132
+ ...corePresenters.map(p => ({ title: `Use ${p} from core`, value: p }))
134
133
  ]
135
134
  });
136
135
 
@@ -144,7 +143,7 @@ export default async function generateCrudPresenter() {
144
143
  const schemaFactory = schemaType === 'package' ? 'Schema' : schemaType;
145
144
  const schemaImport = schemaType === 'package'
146
145
  ? '@azure-net/kit'
147
- : '$shared/Schema';
146
+ : '$core/Schema';
148
147
 
149
148
  if (schemaType === 'package') {
150
149
  const schemaImportFull = `import { createSchemaFactory } from '@azure-net/kit';
@@ -196,8 +195,8 @@ const Schema = createSchemaFactory(createRules(validationMessagesI18n));`;
196
195
 
197
196
  // Create Presenter
198
197
  const presenterTemplate = presenterType === 'package'
199
- ? presenterWithoutSharedTemplate
200
- : presenterWithSharedTemplate;
198
+ ? presenterWithoutCoreTemplate
199
+ : presenterWithCoreTemplate;
201
200
 
202
201
  const presenterFactory = presenterType === 'package' ? 'createPresenter' : presenterType;
203
202
 
@@ -216,5 +215,8 @@ const Schema = createSchemaFactory(createRules(validationMessagesI18n));`;
216
215
  `export * from './${pascalName}Presenter';\nexport * from './Schema';`
217
216
  );
218
217
 
218
+ // Update core index
219
+ await updateCoreIndex();
220
+
219
221
  console.log(`āœ… CRUD presenter for ${pascalName} created successfully!`);
220
222
  }
@@ -1,19 +1,19 @@
1
1
  import prompts from 'prompts';
2
2
  import path from 'path';
3
3
  import { selectContext, getContextPath, toPascalCase, getAvailableFiles } from '../../utils/contextUtils.js';
4
- import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
4
+ import { writeIfNotExists, updateIndexTs, updateCoreIndex } from '../../utils/fileUtils.js';
5
5
 
6
6
  const datasourceWithResponseTemplate = `import { BaseHttpDatasource, type CreateRequestCallbackType } from '@azure-net/kit/infra';
7
- import { {{responseClass}}, type {{responseInterface}} } from '{{responseImport}}';
7
+ import { {{responseClass}} } from '{{responseImport}}';
8
8
 
9
9
  export class {{name}}Datasource extends BaseHttpDatasource {
10
- \tasync createRequest<T>(callback: CreateRequestCallbackType<{{responseInterface}}<T>>) {
11
- \t\treturn new {{responseClass}}<T>(await this.createRawRequest<{{responseInterface}}<T>>(callback));
10
+ \tasync createRequest<T>(callback: CreateRequestCallbackType<T>) {
11
+ \t\treturn new {{responseClass}}<T>(await this.createRawRequest<T>(callback));
12
12
  \t}
13
13
  }`;
14
14
 
15
15
  export default async function generateDatasource() {
16
- const context = await selectContext('Select context for datasource (or shared):');
16
+ const context = await selectContext('Select context for datasource (or core):');
17
17
 
18
18
  const { name } = await prompts({
19
19
  type: 'text',
@@ -22,23 +22,23 @@ export default async function generateDatasource() {
22
22
  });
23
23
 
24
24
  const pascalName = toPascalCase(name);
25
- const contextPath = context === 'shared'
26
- ? path.join(process.cwd(), 'src/app/shared')
25
+ const contextPath = context === 'core'
26
+ ? path.join(process.cwd(), 'src/app/core')
27
27
  : getContextPath(context);
28
28
 
29
29
  // Get available responses
30
- const sharedResponses = await getAvailableFiles(
31
- path.join(process.cwd(), 'src/app/shared/Response')
30
+ const coreResponses = await getAvailableFiles(
31
+ path.join(process.cwd(), 'src/app/core/Response')
32
32
  );
33
33
 
34
- const contextResponses = context !== 'shared'
34
+ const contextResponses = context !== 'core'
35
35
  ? await getAvailableFiles(path.join(contextPath, 'Infrastructure/Response'))
36
36
  : [];
37
37
 
38
38
  const allResponses = [
39
- ...sharedResponses.map(r => ({
40
- title: `${r} (shared)`,
41
- value: { name: r, from: 'shared' }
39
+ ...coreResponses.map(r => ({
40
+ title: `${r} (core)`,
41
+ value: { name: r, from: 'core' }
42
42
  })),
43
43
  ...contextResponses.map(r => ({
44
44
  title: `${r} (${context})`,
@@ -58,26 +58,27 @@ export default async function generateDatasource() {
58
58
  choices: allResponses
59
59
  });
60
60
 
61
- // Determine interface name
62
- const responseInterface = `I${response.name.replace('Response', '')}Response`;
63
-
64
- const datasourcePath = context === 'shared'
61
+ const datasourcePath = context === 'core'
65
62
  ? path.join(contextPath, 'Datasource')
66
63
  : path.join(contextPath, 'Infrastructure/Http/Datasource');
67
64
 
68
- const responseImport = response.from === 'shared'
69
- ? context === 'shared' ? '../Response' : '$shared/Response'
65
+ const responseImport = response.from === 'core'
66
+ ? context === 'core' ? '../Response' : '$core/Response'
70
67
  : `\$${context}/Infrastructure/Response`;
71
68
 
72
69
  const content = datasourceWithResponseTemplate
73
70
  .replace(/{{name}}/g, pascalName)
74
71
  .replace(/{{responseClass}}/g, response.name)
75
- .replace(/{{responseInterface}}/g, responseInterface)
76
72
  .replace(/{{responseImport}}/g, responseImport);
77
73
 
78
74
  const filePath = path.join(datasourcePath, `${pascalName}Datasource.ts`);
79
75
  await writeIfNotExists(filePath, content);
80
76
  await updateIndexTs(datasourcePath);
81
77
 
78
+ // Update core index if needed
79
+ if (context === 'core') {
80
+ await updateCoreIndex();
81
+ }
82
+
82
83
  console.log(`āœ… Datasource created at ${filePath}`);
83
84
  }
@@ -1,17 +1,16 @@
1
1
  import prompts from 'prompts';
2
2
  import path from 'path';
3
- import fs from 'fs/promises';
4
3
  import { selectContext, getContextPath, toPascalCase, getAvailableFiles } from '../../utils/contextUtils.js';
5
- import { writeIfNotExists } from '../../utils/fileUtils.js';
4
+ import { writeIfNotExists, updateCoreIndex } from '../../utils/fileUtils.js';
6
5
 
7
- const presenterWithSharedTemplate = `import { {{sharedPresenter}} } from '$shared/Presenter';
6
+ const presenterWithCoreTemplate = `import { {{corePresenter}} } from '$core/Presenter';
8
7
  import { ApplicationProvider } from '\${{context}}/Application';
9
8
 
10
- export const {{name}}Presenter = {{sharedPresenter}}('{{name}}Presenter', ({ createAsyncResource, createAsyncAction }) => {
9
+ export const {{name}}Presenter = {{corePresenter}}('{{name}}Presenter', ({ createAsyncResource, createAsyncAction }) => {
11
10
  \tconst { /* extract services from ApplicationProvider */ } = ApplicationProvider();
12
11
  \t
13
12
  \tconst example = async () => {
14
- \t\t// Using async helpers from shared presenter factory
13
+ \t\t// Using async helpers from core presenter factory
15
14
  \t\treturn await createAsyncResource(Promise.resolve({}));
16
15
  \t};
17
16
  \t
@@ -41,14 +40,14 @@ export default async function generatePresenter() {
41
40
  message: 'Module name (will create folder in Delivery):'
42
41
  });
43
42
 
44
- // Check for shared presenters
45
- const sharedPresenters = await getAvailableFiles(
46
- path.join(process.cwd(), 'src/app/shared/Presenter')
43
+ // Check for core presenters
44
+ const corePresenters = await getAvailableFiles(
45
+ path.join(process.cwd(), 'src/app/core/Presenter')
47
46
  );
48
47
 
49
48
  const presenterChoices = [
50
49
  { title: 'Use createPresenter from package', value: 'package' },
51
- ...sharedPresenters.map(p => ({ title: `Use ${p} from shared`, value: p }))
50
+ ...corePresenters.map(p => ({ title: `Use ${p} from core`, value: p }))
52
51
  ];
53
52
 
54
53
  const { presenterType } = await prompts({
@@ -67,9 +66,9 @@ export default async function generatePresenter() {
67
66
  ? presenterWithPackageTemplate
68
67
  .replace(/{{name}}/g, pascalName)
69
68
  .replace(/{{context}}/g, context)
70
- : presenterWithSharedTemplate
69
+ : presenterWithCoreTemplate
71
70
  .replace(/{{name}}/g, pascalName)
72
- .replace(/{{sharedPresenter}}/g, presenterType)
71
+ .replace(/{{corePresenter}}/g, presenterType)
73
72
  .replace(/{{context}}/g, context);
74
73
 
75
74
  await writeIfNotExists(filePath, content);
@@ -78,6 +77,9 @@ export default async function generatePresenter() {
78
77
  `export * from './${pascalName}Presenter';`
79
78
  );
80
79
 
80
+ // Update core index
81
+ await updateCoreIndex();
82
+
81
83
  console.log(`āœ… Presenter created at ${filePath}`);
82
84
  console.log(`\nšŸ’” Remember to extract needed services from ApplicationProvider in the presenter.`);
83
85
  }
@@ -1,7 +1,7 @@
1
1
  import prompts from 'prompts';
2
2
  import path from 'path';
3
3
  import { selectContext, getContextPath, toPascalCase, getAvailableFiles, toCamelCase } from '../../utils/contextUtils.js';
4
- import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
4
+ import { writeIfNotExists, updateIndexTs, updateCoreIndex } from '../../utils/fileUtils.js';
5
5
 
6
6
  const repositoryTemplate = `import { {{datasource}} } from '{{datasourceImport}}';
7
7
 
@@ -26,15 +26,15 @@ export default async function generateRepository() {
26
26
 
27
27
  // Get available datasources
28
28
  const contextPath = getContextPath(context);
29
- const sharedDatasources = await getAvailableFiles(
30
- path.join(process.cwd(), 'src/app/shared/Datasource')
29
+ const coreDatasources = await getAvailableFiles(
30
+ path.join(process.cwd(), 'src/app/core/Datasource')
31
31
  );
32
32
  const contextDatasources = await getAvailableFiles(
33
33
  path.join(contextPath, 'Infrastructure/Http/Datasource')
34
34
  );
35
35
 
36
36
  const allDatasources = [
37
- ...sharedDatasources.map(d => ({ title: `${d} (shared)`, value: { name: d, from: 'shared' } })),
37
+ ...coreDatasources.map(d => ({ title: `${d} (core)`, value: { name: d, from: 'core' } })),
38
38
  ...contextDatasources.map(d => ({ title: `${d} (${context})`, value: { name: d, from: context } }))
39
39
  ];
40
40
 
@@ -55,8 +55,8 @@ export default async function generateRepository() {
55
55
  const filePath = path.join(repoPath, `${pascalName}Repository.ts`);
56
56
 
57
57
  // Generate repository
58
- const datasourceImport = datasource.from === 'shared'
59
- ? '$shared/Datasource'
58
+ const datasourceImport = datasource.from === 'core'
59
+ ? '$core/Datasource'
60
60
  : `\$${context}/Infrastructure/Http/Datasource`;
61
61
 
62
62
  const content = repositoryTemplate
@@ -68,6 +68,9 @@ export default async function generateRepository() {
68
68
  await writeIfNotExists(filePath, content);
69
69
  await updateIndexTs(repoPath);
70
70
 
71
+ // Update core index
72
+ await updateCoreIndex();
73
+
71
74
  console.log(`āœ… Repository created at ${filePath}`);
72
75
  console.log(`\nšŸ’” Remember to manually add this repository to InfrastructureProvider when needed.`);
73
76
  }
@@ -1,7 +1,7 @@
1
1
  import prompts from 'prompts';
2
2
  import path from 'path';
3
3
  import { selectContext, getContextPath, toPascalCase } from '../../utils/contextUtils.js';
4
- import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
4
+ import { writeIfNotExists, updateIndexTs, updateCoreIndex } from '../../utils/fileUtils.js';
5
5
 
6
6
  const responseTemplate = `import { ResponseBuilder } from '@azure-net/kit/infra';
7
7
 
@@ -9,7 +9,7 @@ export class {{name}}Response<TData = unknown, TMeta = unknown> extends Response
9
9
  }`;
10
10
 
11
11
  export default async function generateResponse() {
12
- const context = await selectContext('Select context for response (or shared):');
12
+ const context = await selectContext('Select context for response (or core):');
13
13
 
14
14
  const { name } = await prompts({
15
15
  type: 'text',
@@ -18,11 +18,11 @@ export default async function generateResponse() {
18
18
  });
19
19
 
20
20
  const pascalName = toPascalCase(name);
21
- const contextPath = context === 'shared'
22
- ? path.join(process.cwd(), 'src/app/shared')
21
+ const contextPath = context === 'core'
22
+ ? path.join(process.cwd(), 'src/app/core')
23
23
  : getContextPath(context);
24
24
 
25
- const responsePath = context === 'shared'
25
+ const responsePath = context === 'core'
26
26
  ? path.join(contextPath, 'Response')
27
27
  : path.join(contextPath, 'Infrastructure/Response');
28
28
 
@@ -32,5 +32,10 @@ export default async function generateResponse() {
32
32
  await writeIfNotExists(filePath, content);
33
33
  await updateIndexTs(responsePath);
34
34
 
35
+ // Update core index if needed
36
+ if (context === 'core') {
37
+ await updateCoreIndex();
38
+ }
39
+
35
40
  console.log(`āœ… Response created at ${filePath}`);
36
41
  }
@@ -4,4 +4,5 @@ export { default as initMiddleware } from './initMiddleware.js';
4
4
  export { default as initEdges } from './initEdges.js';
5
5
  export { default as initTranslations } from './initTranslations.js';
6
6
  export { default as initSchema } from './initSchema.js';
7
- export { default as initLint } from './initLint.js';
7
+ export { default as initLint } from './initLint.js';
8
+ export { default as initPresenter } from './initPresenter.js';
@@ -11,6 +11,7 @@ function generateAliases(config) {
11
11
  return Object.fromEntries([
12
12
  ...contexts.map(c => [`$${c}`, `./src/app/contexts/${c}`]),
13
13
  ['$shared', './src/app/shared'],
14
+ ['$core', './src/app/core'],
14
15
  ['$lib', './src/lib']
15
16
  ]);
16
17
  }
@@ -1,7 +1,7 @@
1
- import { writeIfNotExists, injectIntoFile } from '../../utils/fileUtils.js';
1
+ import { writeIfNotExists, updateCoreIndex } from '../../utils/fileUtils.js';
2
2
  import path from 'path';
3
3
 
4
- const middlewarePath = path.join(process.cwd(), 'src/app/shared/Middleware/MiddlewareManager.ts');
4
+ const middlewarePath = path.join(process.cwd(), 'src/app/core/Middleware/MiddlewareManager.ts');
5
5
 
6
6
  const middlewareTemplate = `import { createMiddlewareManager } from '@azure-net/kit';
7
7
 
@@ -10,9 +10,12 @@ export const { clientMiddleware, serverMiddleware } = createMiddlewareManager([]
10
10
  export default async function initMiddleware() {
11
11
  await writeIfNotExists(middlewarePath, middlewareTemplate);
12
12
  await writeIfNotExists(
13
- path.join(process.cwd(), 'src/app/shared/Middleware/index.ts'),
13
+ path.join(process.cwd(), 'src/app/core/Middleware/index.ts'),
14
14
  `export * from './MiddlewareManager';`
15
15
  );
16
16
 
17
+ // Update core index
18
+ await updateCoreIndex();
19
+
17
20
  console.log('āœ… Middleware initialized');
18
21
  }
@@ -0,0 +1,22 @@
1
+ import { writeIfNotExists } from '../../utils/fileUtils.js';
2
+ import path from 'path';
3
+
4
+ const presenterPath = path.join(process.cwd(), 'src/app/core/Presenter/AppPresenter.ts');
5
+
6
+ const presenterTemplate = `import { createPresenterFactory } from '@azure-net/kit/edges';
7
+ import { createAsyncHelpers, createErrorParser } from '@azure-net/kit';
8
+
9
+ const ErrorHandler = createErrorParser();
10
+ const AsyncHelpers = createAsyncHelpers({ parseError: ErrorHandler });
11
+
12
+ export const AppPresenter = createPresenterFactory({ ...AsyncHelpers, handleError: ErrorHandler });`;
13
+
14
+ export default async function initPresenter() {
15
+ await writeIfNotExists(presenterPath, presenterTemplate);
16
+ await writeIfNotExists(
17
+ path.join(process.cwd(), 'src/app/core/Presenter/index.ts'),
18
+ `export * from './AppPresenter';`
19
+ );
20
+
21
+ console.log('āœ… Presenter factory initialized');
22
+ }
@@ -1,7 +1,7 @@
1
- import { writeIfNotExists } from '../../utils/fileUtils.js';
1
+ import { writeIfNotExists, updateCoreIndex } from '../../utils/fileUtils.js';
2
2
  import path from 'path';
3
3
 
4
- const schemaPath = path.join(process.cwd(), 'src/app/shared/Schema/Schema.ts');
4
+ const schemaPath = path.join(process.cwd(), 'src/app/core/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,9 +11,12 @@ 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/shared/Schema/index.ts'),
14
+ path.join(process.cwd(), 'src/app/core/Schema/index.ts'),
15
15
  `export * from './Schema';`
16
16
  );
17
17
 
18
+ // Update core index
19
+ await updateCoreIndex();
20
+
18
21
  console.log('āœ… Schema factory initialized');
19
22
  }
@@ -1,11 +1,12 @@
1
1
  import fs from 'fs/promises';
2
2
  import path from 'path';
3
3
  import { loadUserConfig } from '../../utils/loadConfig.js';
4
+ import { updateCoreIndex } from '../../utils/fileUtils.js';
4
5
 
5
6
  const APP_ROOT = path.join(process.cwd(), 'src', 'app');
6
7
  const CONTEXTS_PATH = path.join(APP_ROOT, 'contexts');
7
8
  const SHARED_PATH = path.join(APP_ROOT, 'shared');
8
- const CORE_PATH = path.join(APP_ROOT, 'shared', 'core');
9
+ const CORE_PATH = path.join(APP_ROOT, 'core');
9
10
 
10
11
  async function createDirIfNotExists(dirPath) {
11
12
  try {
@@ -25,10 +26,9 @@ async function createIndexFile(dirPath, exportPatterns = []) {
25
26
  }
26
27
 
27
28
  async function createBaseStructure(root, contextName, contextAlias) {
28
- // Domain
29
+ // Domain - Š½Š¾Š²Š°Ń ŃŃ‚Ń€ŃƒŠŗŃ‚ŃƒŃ€Š°
29
30
  const domainPath = path.join(root, 'Domain');
30
- await createDirIfNotExists(path.join(domainPath, 'Entities'));
31
- await createDirIfNotExists(path.join(domainPath, 'Ports'));
31
+ await createDirIfNotExists(domainPath);
32
32
 
33
33
  // Infrastructure
34
34
  const infraPath = path.join(root, 'Infrastructure');
@@ -119,23 +119,20 @@ export default async function initStructure() {
119
119
  await createBaseStructure(contextPath, contextName, context);
120
120
  }
121
121
 
122
- // Create shared structure (former core)
122
+ // Create empty shared folder
123
123
  await createDirIfNotExists(SHARED_PATH);
124
- await createDirIfNotExists(path.join(SHARED_PATH, 'Datasource'));
125
- await createDirIfNotExists(path.join(SHARED_PATH, 'Response'));
126
- await createDirIfNotExists(path.join(SHARED_PATH, 'Schema'));
127
- await createDirIfNotExists(path.join(SHARED_PATH, 'Middleware'));
128
- await createDirIfNotExists(path.join(SHARED_PATH, 'Presenter'));
129
- await createDirIfNotExists(path.join(SHARED_PATH, 'Translation'));
130
-
131
- // Create shared index.ts that exports all subdirectories
132
- await createIndexFile(SHARED_PATH, [
133
- './Schema',
134
- './Datasource',
135
- './Response',
136
- './Middleware',
137
- './Translation'
138
- ]);
124
+
125
+ // Create core structure with all functionality
126
+ await createDirIfNotExists(CORE_PATH);
127
+ await createDirIfNotExists(path.join(CORE_PATH, 'Datasource'));
128
+ await createDirIfNotExists(path.join(CORE_PATH, 'Response'));
129
+ await createDirIfNotExists(path.join(CORE_PATH, 'Schema'));
130
+ await createDirIfNotExists(path.join(CORE_PATH, 'Middleware'));
131
+ await createDirIfNotExists(path.join(CORE_PATH, 'Presenter'));
132
+ await createDirIfNotExists(path.join(CORE_PATH, 'Translation'));
133
+
134
+ // Update core index
135
+ await updateCoreIndex();
139
136
 
140
137
  console.log('āœ… Structure initialization complete!');
141
138
  }
@@ -1,7 +1,7 @@
1
- import { writeIfNotExists } from '../../utils/fileUtils.js';
1
+ import { writeIfNotExists, updateCoreIndex } from '../../utils/fileUtils.js';
2
2
  import path from 'path';
3
3
 
4
- const translationsPath = path.join(process.cwd(), 'src/app/shared/Translation');
4
+ const translationsPath = path.join(process.cwd(), 'src/app/core/Translation');
5
5
 
6
6
  const translationProviderTemplate = `import { messages } from './Locales';
7
7
  import { createTranslations } from '@azure-net/kit/i18n';
@@ -52,5 +52,8 @@ export default async function initTranslations() {
52
52
  localesIndexTemplate
53
53
  );
54
54
 
55
+ // Update core index
56
+ await updateCoreIndex();
57
+
55
58
  console.log('āœ… Translations initialized');
56
59
  }
@@ -4,7 +4,7 @@ import prompts from 'prompts';
4
4
  import { loadUserConfig } from './loadConfig.js';
5
5
 
6
6
  const CONTEXTS_PATH = path.join(process.cwd(), 'src/app/contexts');
7
- const SHARED_PATH = path.join(process.cwd(), 'src/app/shared');
7
+ const CORE_PATH = path.join(process.cwd(), 'src/app/core');
8
8
 
9
9
  export async function selectContext(message = 'Select context:') {
10
10
  const config = await loadUserConfig();
@@ -16,7 +16,7 @@ export async function selectContext(message = 'Select context:') {
16
16
  message,
17
17
  choices: [
18
18
  ...contexts.map(c => ({ title: c, value: c })),
19
- { title: 'shared (former core)', value: 'shared' }
19
+ { title: 'core', value: 'core' }
20
20
  ]
21
21
  });
22
22
 
@@ -24,8 +24,8 @@ export async function selectContext(message = 'Select context:') {
24
24
  }
25
25
 
26
26
  export function getContextPath(context) {
27
- return context === 'shared'
28
- ? SHARED_PATH
27
+ return context === 'core'
28
+ ? CORE_PATH
29
29
  : path.join(CONTEXTS_PATH, context);
30
30
  }
31
31
 
@@ -61,28 +61,13 @@ export async function getApplicationProviderServices(context) {
61
61
  }
62
62
  }
63
63
 
64
- // Fixed to preserve PascalCase properly
65
64
  export function toPascalCase(str) {
66
- // If already in PascalCase with multiple words, preserve it
67
- if (/^[A-Z][a-z]+(?:[A-Z][a-z]+)*$/.test(str)) {
68
- return str;
69
- }
70
-
71
- // Split by common delimiters but preserve existing camelCase/PascalCase
72
- const words = str.split(/[-_\s]+/);
73
- return words
74
- .map((word, index) => {
75
- // If word is already in camelCase or PascalCase, preserve it
76
- if (/[a-z][A-Z]/.test(word)) {
77
- return word.charAt(0).toUpperCase() + word.slice(1);
78
- }
79
- // Otherwise capitalize first letter
80
- return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
81
- })
65
+ return str
66
+ .split(/[-_\s]+/)
67
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
82
68
  .join('');
83
69
  }
84
70
 
85
- // Fixed to preserve camelCase properly
86
71
  export function toCamelCase(str) {
87
72
  const pascal = toPascalCase(str);
88
73
  return pascal.charAt(0).toLowerCase() + pascal.slice(1);
@@ -28,6 +28,34 @@ export async function updateIndexTs(dir, filePattern = '.ts', ignore = ['index.t
28
28
  }
29
29
  }
30
30
 
31
+ export async function updateCoreIndex() {
32
+ const corePath = path.join(process.cwd(), 'src/app/core');
33
+ try {
34
+ const dirs = await fs.readdir(corePath, { withFileTypes: true });
35
+ const validDirs = [];
36
+
37
+ for (const dir of dirs) {
38
+ if (dir.isDirectory()) {
39
+ // Check if directory has any files
40
+ const dirPath = path.join(corePath, dir.name);
41
+ const files = await fs.readdir(dirPath);
42
+ if (files.length > 0) {
43
+ validDirs.push(dir.name);
44
+ }
45
+ }
46
+ }
47
+
48
+ if (validDirs.length > 0) {
49
+ const content = validDirs
50
+ .map(d => `export * from './${d}';`)
51
+ .join('\n') + '\n';
52
+ await fs.writeFile(path.join(corePath, 'index.ts'), content, 'utf-8');
53
+ }
54
+ } catch (error) {
55
+ // Core directory doesn't exist
56
+ }
57
+ }
58
+
31
59
  export async function ensureIndexExports(layerPath) {
32
60
  try {
33
61
  const subdirs = await fs.readdir(layerPath, { withFileTypes: true });