@azure-net/cli 5.0.0-3 → 5.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 +5 -46
- package/bin/azure-net.ts +5 -5
- package/package.json +1 -1
- package/src/checks/checkDomain.js +8 -38
- package/src/checks/checkFoldersStructure.js +0 -14
- package/src/checks/checkHooks.js +0 -5
- package/src/checks/checkImports.js +0 -1
- package/src/checks/checkInternal.js +0 -1
- package/src/checks/checkLayerBoundaries.js +50 -54
- package/src/checks/checkLayerBoundaries.ts +55 -58
- package/src/checks/checkPresenterNames.js +1 -37
- package/src/checks/checkPresenterNames.ts +1 -6
- package/src/checks/checkProject.js +0 -6
- package/src/checks/checkProviderGraph.js +1 -38
- package/src/checks/checkProviderNames.js +0 -28
- package/src/checks/index.js +0 -1
- package/src/generate/layers/generateRepository.js +4 -19
- package/src/generate/layers/generateRepositoryMethod.js +0 -12
- package/src/generate/layers/generateUseCases.js +0 -6
- package/src/generate/layers/repositoryShared.js +41 -104
- package/src/generate/layers/repositoryShared.ts +17 -12
- package/src/generate/module/generateDomain.js +0 -25
- package/src/generate/module/generateModule.js +0 -10
- package/src/generate/module/generateModulePreset.js +10 -51
- package/src/generate/module/generateModulePreset.ts +9 -8
- package/src/generate/module/generatePresenter.js +366 -371
- package/src/generate/module/generatePresenter.ts +76 -20
- package/src/generate/module/generateRepository.js +0 -17
- package/src/generate/module/generateSchemaFromType.js +9 -58
- package/src/generate/module/generateSchemaFromType.ts +1 -2
- package/src/generate/module/generateTypesJson.js +4 -45
- package/src/generate/module/generateUseCases.js +0 -9
- package/src/generate/module/repositoryModuleShared.js +21 -98
- package/src/generate/module/repositoryModuleShared.ts +14 -10
- package/src/generate/ui/generateComponent.js +0 -16
- package/src/generate/ui/generateDesignComponent.js +0 -12
- package/src/generate/ui/generateWidget.js +0 -12
- package/src/init/initAliases.js +42 -64
- package/src/init/initAliases.ts +47 -42
- package/src/init/initEdges.js +0 -15
- package/src/init/initStructure.js +48 -21
- package/src/init/initStructure.ts +51 -3
- package/src/install/installFresh.js +0 -16
- package/src/plugins/addLint.js +11 -46
- package/src/scaffolds/createCoreSchema.js +6 -40
- package/src/scaffolds/createCoreSchema.ts +6 -18
- package/src/scaffolds/createDatasource.js +26 -61
- package/src/scaffolds/createDatasource.ts +26 -40
- package/src/scaffolds/createDatasourceProvider.js +19 -56
- package/src/scaffolds/createDatasourceProvider.ts +20 -34
- package/src/scaffolds/createPresenterFactory.js +67 -94
- package/src/scaffolds/createPresenterFactory.ts +7 -19
- package/src/scaffolds/createProgram.js +1 -5
- package/src/scaffolds/createResponse.js +3 -11
- package/src/scaffolds/createResponse.ts +3 -1
- package/src/scaffolds/createSchemaRule.js +3 -8
- package/src/scaffolds/createSchemaRule.ts +3 -1
- package/src/scaffolds/createTranslationManager.js +3 -14
- package/src/scaffolds/createTranslationManager.ts +3 -1
- package/src/utils/contextUtils.js +5 -20
- package/src/utils/contextUtils.ts +2 -3
- package/src/utils/fileUtils.js +3 -38
- package/src/utils/fileUtils.ts +0 -26
- package/src/utils/loadConfig.js +1 -14
- package/src/utils/loadConfig.ts +1 -3
- package/src/utils/sharedFoundation.js +48 -0
- package/src/utils/sharedFoundation.ts +70 -0
|
@@ -2,34 +2,26 @@ import fs from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import prompts from 'prompts';
|
|
4
4
|
import { selectContext } from './repositoryModuleShared.js';
|
|
5
|
-
|
|
6
5
|
const isValidIdentifier = (value) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value);
|
|
7
|
-
|
|
8
6
|
const toPropertyName = (key) => (isValidIdentifier(key) ? key : `'${String(key).replace(/'/g, "\\'")}'`);
|
|
9
|
-
|
|
10
7
|
const getIndent = (level) => '\t'.repeat(level);
|
|
11
|
-
|
|
12
8
|
const normalizeObjectInput = (rawValue) => {
|
|
13
9
|
let input = String(rawValue ?? '').trim();
|
|
14
10
|
if (input.endsWith(';')) {
|
|
15
11
|
input = input.slice(0, -1).trim();
|
|
16
12
|
}
|
|
17
|
-
|
|
18
13
|
const openCurly = (input.match(/\{/g) ?? []).length;
|
|
19
14
|
const closeCurly = (input.match(/\}/g) ?? []).length;
|
|
20
15
|
if (openCurly > closeCurly) {
|
|
21
16
|
input += '}'.repeat(openCurly - closeCurly);
|
|
22
17
|
}
|
|
23
|
-
|
|
24
18
|
return input;
|
|
25
19
|
};
|
|
26
|
-
|
|
27
20
|
const parseObjectInput = (rawValue) => {
|
|
28
21
|
const input = normalizeObjectInput(rawValue);
|
|
29
22
|
if (!input.length) {
|
|
30
23
|
throw new Error('Input is empty');
|
|
31
24
|
}
|
|
32
|
-
|
|
33
25
|
try {
|
|
34
26
|
const parsed = JSON.parse(input);
|
|
35
27
|
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
@@ -39,63 +31,49 @@ const parseObjectInput = (rawValue) => {
|
|
|
39
31
|
} catch {
|
|
40
32
|
// fallback to JS object literal
|
|
41
33
|
}
|
|
42
|
-
|
|
43
|
-
// eslint-disable-next-line no-new-func
|
|
44
34
|
const parsed = new Function(`"use strict"; return (${input});`)();
|
|
45
35
|
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
46
36
|
throw new Error('Input root must be an object');
|
|
47
37
|
}
|
|
48
38
|
return parsed;
|
|
49
39
|
};
|
|
50
|
-
|
|
51
40
|
const stringifyType = (value, level = 1) => {
|
|
52
41
|
if (value === null) return 'null';
|
|
53
|
-
|
|
54
42
|
const valueType = typeof value;
|
|
55
43
|
if (valueType === 'string') return 'string';
|
|
56
44
|
if (valueType === 'number') return Number.isFinite(value) ? 'number' : 'unknown';
|
|
57
45
|
if (valueType === 'boolean') return 'boolean';
|
|
58
46
|
if (valueType === 'bigint') return 'bigint';
|
|
59
47
|
if (valueType === 'undefined') return 'undefined';
|
|
60
|
-
|
|
61
48
|
if (Array.isArray(value)) {
|
|
62
49
|
if (!value.length) return 'unknown[]';
|
|
63
|
-
|
|
64
50
|
const itemTypes = Array.from(new Set(value.map((item) => stringifyType(item, level + 1))));
|
|
65
51
|
if (itemTypes.length === 1) {
|
|
66
|
-
const single = itemTypes[0];
|
|
52
|
+
const single = itemTypes[0] ?? 'unknown';
|
|
67
53
|
if (single.includes('\n')) return `Array<${single}>`;
|
|
68
54
|
return `${single}[]`;
|
|
69
55
|
}
|
|
70
|
-
|
|
71
56
|
const union = itemTypes.join(' | ');
|
|
72
57
|
if (union.includes('\n')) return `Array<${union}>`;
|
|
73
58
|
return `(${union})[]`;
|
|
74
59
|
}
|
|
75
|
-
|
|
76
60
|
if (valueType === 'object') {
|
|
77
61
|
const entries = Object.entries(value);
|
|
78
62
|
if (!entries.length) return 'Record<string, unknown>';
|
|
79
|
-
|
|
80
63
|
const lines = entries.map(([entryKey, entryValue]) => {
|
|
81
64
|
const propertyType = stringifyType(entryValue, level + 1);
|
|
82
65
|
return `${getIndent(level + 1)}${toPropertyName(entryKey)}: ${propertyType};`;
|
|
83
66
|
});
|
|
84
|
-
|
|
85
67
|
return `{\n${lines.join('\n')}\n${getIndent(level)}}`;
|
|
86
68
|
}
|
|
87
|
-
|
|
88
69
|
return 'unknown';
|
|
89
70
|
};
|
|
90
|
-
|
|
91
71
|
const findInterfaceDeclaration = (content) => {
|
|
92
72
|
const declarationMatch = content.match(/export\s+interface\s+([A-Za-z0-9_]+)\s*\{/);
|
|
93
73
|
if (!declarationMatch || declarationMatch.index === undefined) return null;
|
|
94
|
-
|
|
95
|
-
const name = declarationMatch[1];
|
|
74
|
+
const name = declarationMatch[1] ?? 'Interface';
|
|
96
75
|
const openBraceIndex = content.indexOf('{', declarationMatch.index);
|
|
97
76
|
if (openBraceIndex === -1) return null;
|
|
98
|
-
|
|
99
77
|
let depth = 0;
|
|
100
78
|
let closeBraceIndex = -1;
|
|
101
79
|
for (let index = openBraceIndex; index < content.length; index += 1) {
|
|
@@ -109,9 +87,7 @@ const findInterfaceDeclaration = (content) => {
|
|
|
109
87
|
}
|
|
110
88
|
}
|
|
111
89
|
}
|
|
112
|
-
|
|
113
90
|
if (closeBraceIndex === -1) return null;
|
|
114
|
-
|
|
115
91
|
const body = content.slice(openBraceIndex + 1, closeBraceIndex);
|
|
116
92
|
return {
|
|
117
93
|
name,
|
|
@@ -120,17 +96,16 @@ const findInterfaceDeclaration = (content) => {
|
|
|
120
96
|
body
|
|
121
97
|
};
|
|
122
98
|
};
|
|
123
|
-
|
|
124
99
|
const extractExistingRootKeys = (body) => {
|
|
125
100
|
const keys = new Set();
|
|
126
101
|
const keyRegex = /^\s*([A-Za-z_$][A-Za-z0-9_$]*)\??\s*:/gm;
|
|
127
102
|
let match;
|
|
128
103
|
while ((match = keyRegex.exec(body)) !== null) {
|
|
129
|
-
|
|
104
|
+
const key = match[1];
|
|
105
|
+
if (key) keys.add(key);
|
|
130
106
|
}
|
|
131
107
|
return keys;
|
|
132
108
|
};
|
|
133
|
-
|
|
134
109
|
const listDomains = async (contextName) => {
|
|
135
110
|
const domainRoot = path.join(process.cwd(), 'src', 'app', contextName, 'layers', 'domain');
|
|
136
111
|
try {
|
|
@@ -140,7 +115,6 @@ const listDomains = async (contextName) => {
|
|
|
140
115
|
return [];
|
|
141
116
|
}
|
|
142
117
|
};
|
|
143
|
-
|
|
144
118
|
const listModelFiles = async (contextName, domainName) => {
|
|
145
119
|
const modelRoot = path.join(process.cwd(), 'src', 'app', contextName, 'layers', 'domain', domainName, 'model');
|
|
146
120
|
try {
|
|
@@ -155,21 +129,18 @@ const listModelFiles = async (contextName, domainName) => {
|
|
|
155
129
|
return [];
|
|
156
130
|
}
|
|
157
131
|
};
|
|
158
|
-
|
|
159
132
|
export default async function generateTypesJson() {
|
|
160
133
|
const contextName = await selectContext('Select context for model update:');
|
|
161
134
|
if (!contextName) {
|
|
162
135
|
process.exitCode = 1;
|
|
163
136
|
return;
|
|
164
137
|
}
|
|
165
|
-
|
|
166
138
|
const domains = await listDomains(contextName);
|
|
167
139
|
if (!domains.length) {
|
|
168
140
|
console.error(`❌ No domains found in context "${contextName}".`);
|
|
169
141
|
process.exitCode = 1;
|
|
170
142
|
return;
|
|
171
143
|
}
|
|
172
|
-
|
|
173
144
|
const { domainName } = await prompts({
|
|
174
145
|
type: 'select',
|
|
175
146
|
name: 'domainName',
|
|
@@ -177,19 +148,16 @@ export default async function generateTypesJson() {
|
|
|
177
148
|
choices: domains.map((item) => ({ title: item, value: item })),
|
|
178
149
|
initial: 0
|
|
179
150
|
});
|
|
180
|
-
|
|
181
151
|
if (!domainName) {
|
|
182
152
|
process.exitCode = 1;
|
|
183
153
|
return;
|
|
184
154
|
}
|
|
185
|
-
|
|
186
155
|
const models = await listModelFiles(contextName, String(domainName));
|
|
187
156
|
if (!models.length) {
|
|
188
157
|
console.error(`❌ No model files found in domain "${domainName}".`);
|
|
189
158
|
process.exitCode = 1;
|
|
190
159
|
return;
|
|
191
160
|
}
|
|
192
|
-
|
|
193
161
|
const { modelPath } = await prompts({
|
|
194
162
|
type: 'select',
|
|
195
163
|
name: 'modelPath',
|
|
@@ -197,12 +165,10 @@ export default async function generateTypesJson() {
|
|
|
197
165
|
choices: models.map((item) => ({ title: item.name, value: item.path })),
|
|
198
166
|
initial: 0
|
|
199
167
|
});
|
|
200
|
-
|
|
201
168
|
if (!modelPath) {
|
|
202
169
|
process.exitCode = 1;
|
|
203
170
|
return;
|
|
204
171
|
}
|
|
205
|
-
|
|
206
172
|
const { rawJson } = await prompts({
|
|
207
173
|
type: 'text',
|
|
208
174
|
name: 'rawJson',
|
|
@@ -216,12 +182,10 @@ export default async function generateTypesJson() {
|
|
|
216
182
|
}
|
|
217
183
|
}
|
|
218
184
|
});
|
|
219
|
-
|
|
220
185
|
if (!rawJson) {
|
|
221
186
|
process.exitCode = 1;
|
|
222
187
|
return;
|
|
223
188
|
}
|
|
224
|
-
|
|
225
189
|
const parsedJson = parseObjectInput(rawJson);
|
|
226
190
|
const content = await fs.readFile(String(modelPath), 'utf-8');
|
|
227
191
|
const interfaceDeclaration = findInterfaceDeclaration(content);
|
|
@@ -230,23 +194,18 @@ export default async function generateTypesJson() {
|
|
|
230
194
|
process.exitCode = 1;
|
|
231
195
|
return;
|
|
232
196
|
}
|
|
233
|
-
|
|
234
197
|
const existingKeys = extractExistingRootKeys(interfaceDeclaration.body);
|
|
235
198
|
const generatedLines = Object.entries(parsedJson)
|
|
236
199
|
.filter(([key]) => !existingKeys.has(key))
|
|
237
200
|
.map(([key, value]) => `${getIndent(1)}${toPropertyName(key)}: ${stringifyType(value, 1)};`);
|
|
238
|
-
|
|
239
201
|
if (!generatedLines.length) {
|
|
240
202
|
console.log('ℹ️ No new keys to add. Model already contains all JSON keys.');
|
|
241
203
|
return;
|
|
242
204
|
}
|
|
243
|
-
|
|
244
205
|
const trimmedBody = interfaceDeclaration.body.trimEnd();
|
|
245
206
|
const bodyPrefix = trimmedBody.length ? `${trimmedBody}\n` : '';
|
|
246
207
|
const newBody = `${bodyPrefix}${generatedLines.join('\n')}\n`;
|
|
247
|
-
|
|
248
208
|
const updatedContent = `${content.slice(0, interfaceDeclaration.openBraceIndex + 1)}${newBody}${content.slice(interfaceDeclaration.closeBraceIndex)}`;
|
|
249
209
|
await fs.writeFile(String(modelPath), updatedContent, 'utf-8');
|
|
250
|
-
|
|
251
210
|
console.log(`✅ Model updated: ${modelPath}`);
|
|
252
211
|
}
|
|
@@ -8,14 +8,12 @@ import {
|
|
|
8
8
|
resolveRepositoriesPath,
|
|
9
9
|
selectContext
|
|
10
10
|
} from './repositoryModuleShared.js';
|
|
11
|
-
|
|
12
11
|
export default async function generateUseCases() {
|
|
13
12
|
const contextName = await selectContext('Select context for UseCases:');
|
|
14
13
|
if (!contextName) {
|
|
15
14
|
process.exitCode = 1;
|
|
16
15
|
return;
|
|
17
16
|
}
|
|
18
|
-
|
|
19
17
|
const repositoriesPath = resolveRepositoriesPath(contextName);
|
|
20
18
|
const repositories = await getAvailableTsNames(repositoriesPath);
|
|
21
19
|
if (!repositories.length) {
|
|
@@ -23,7 +21,6 @@ export default async function generateUseCases() {
|
|
|
23
21
|
process.exitCode = 1;
|
|
24
22
|
return;
|
|
25
23
|
}
|
|
26
|
-
|
|
27
24
|
const { repositoryName } = await prompts({
|
|
28
25
|
type: 'select',
|
|
29
26
|
name: 'repositoryName',
|
|
@@ -31,12 +28,10 @@ export default async function generateUseCases() {
|
|
|
31
28
|
choices: repositories.map((item) => ({ title: item, value: item })),
|
|
32
29
|
initial: 0
|
|
33
30
|
});
|
|
34
|
-
|
|
35
31
|
if (!repositoryName) {
|
|
36
32
|
process.exitCode = 1;
|
|
37
33
|
return;
|
|
38
34
|
}
|
|
39
|
-
|
|
40
35
|
const { contexts } = await getConfigState();
|
|
41
36
|
const contextAlias = resolveContextAlias(contexts, contextName);
|
|
42
37
|
const domainName = await resolveDomainForRepository({
|
|
@@ -44,24 +39,20 @@ export default async function generateUseCases() {
|
|
|
44
39
|
contextAlias,
|
|
45
40
|
repositoryName: String(repositoryName)
|
|
46
41
|
});
|
|
47
|
-
|
|
48
42
|
if (!domainName) {
|
|
49
43
|
console.error('❌ Unable to resolve domain from repository imports.');
|
|
50
44
|
process.exitCode = 1;
|
|
51
45
|
return;
|
|
52
46
|
}
|
|
53
|
-
|
|
54
47
|
const created = await createUseCasesForRepository({
|
|
55
48
|
contextName,
|
|
56
49
|
contextAlias,
|
|
57
50
|
domainName,
|
|
58
51
|
repositoryName: String(repositoryName)
|
|
59
52
|
});
|
|
60
|
-
|
|
61
53
|
if (!created) {
|
|
62
54
|
process.exitCode = 1;
|
|
63
55
|
return;
|
|
64
56
|
}
|
|
65
|
-
|
|
66
57
|
console.log(`✅ UseCases generated for ${repositoryName}`);
|
|
67
58
|
}
|