@azure-net/cli 5.1.0 → 6.0.0-next.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.
Files changed (176) hide show
  1. package/README.md +189 -0
  2. package/bin/azure-net.js +236 -221
  3. package/dist/bin/azure-net.d.ts +2 -0
  4. package/dist/src/checks/architecture.d.ts +20 -0
  5. package/dist/src/checks/checkDomain.d.ts +1 -0
  6. package/dist/src/checks/checkFoldersStructure.d.ts +1 -0
  7. package/dist/src/checks/checkHooks.d.ts +1 -0
  8. package/dist/src/checks/checkImports.d.ts +1 -0
  9. package/dist/src/checks/checkInternal.d.ts +1 -0
  10. package/dist/src/checks/checkLayerBoundaries.d.ts +1 -0
  11. package/dist/src/checks/checkLayerImports.d.ts +1 -0
  12. package/dist/src/checks/checkPresenterNames.d.ts +1 -0
  13. package/dist/src/checks/checkProject.d.ts +1 -0
  14. package/dist/src/checks/checkProviderGraph.d.ts +1 -0
  15. package/dist/src/checks/checkProviderNames.d.ts +1 -0
  16. package/dist/src/generate/layers/generateRepository.d.ts +1 -0
  17. package/dist/src/generate/layers/generateRepositoryMethod.d.ts +1 -0
  18. package/dist/src/generate/layers/generateUseCases.d.ts +1 -0
  19. package/dist/src/generate/module/generateDomain.d.ts +8 -0
  20. package/dist/src/generate/module/generateModule.d.ts +1 -0
  21. package/dist/src/generate/module/generateModulePreset.d.ts +1 -0
  22. package/dist/src/generate/module/generatePresenter.d.ts +29 -0
  23. package/dist/src/generate/module/generateRepository.d.ts +15 -0
  24. package/dist/src/generate/module/generateRepositoryMethod.d.ts +2 -0
  25. package/dist/src/generate/module/generateSchemaFromType.d.ts +9 -0
  26. package/dist/src/generate/module/generateStore.d.ts +1 -0
  27. package/dist/src/generate/module/generateTypesJson.d.ts +2 -0
  28. package/dist/src/generate/module/generateUseCases.d.ts +1 -0
  29. package/dist/src/generate/module/repositoryModuleShared.d.ts +89 -0
  30. package/dist/src/generate/routes/generateRoutes.d.ts +14 -0
  31. package/dist/src/generate/ui/generateComponent.d.ts +1 -0
  32. package/dist/src/generate/ui/generateDesignComponent.d.ts +1 -0
  33. package/dist/src/generate/ui/generateWidget.d.ts +1 -0
  34. package/dist/src/git/commit.d.ts +23 -0
  35. package/dist/src/git/push.d.ts +11 -0
  36. package/dist/src/git/runGit.d.ts +2 -0
  37. package/dist/src/init/initAliases.d.ts +12 -0
  38. package/dist/src/init/initEdges.d.ts +2 -0
  39. package/dist/src/init/initStructure.d.ts +1 -0
  40. package/dist/src/install/configureCommitTools.d.ts +1 -0
  41. package/dist/src/install/installFresh.d.ts +1 -0
  42. package/dist/src/migrate/migrate.d.ts +22 -0
  43. package/dist/src/migrate/presenters.d.ts +7 -0
  44. package/dist/src/plugins/addLint.d.ts +5 -0
  45. package/dist/src/scaffolds/createCoreSchema.d.ts +1 -0
  46. package/dist/src/scaffolds/createDatasource.d.ts +1 -0
  47. package/dist/src/scaffolds/createProgram.d.ts +1 -0
  48. package/dist/src/scaffolds/createResponse.d.ts +1 -0
  49. package/dist/src/scaffolds/createSchemaRule.d.ts +1 -0
  50. package/dist/src/scaffolds/createTranslationManager.d.ts +1 -0
  51. package/{src/scaffolds/index.ts → dist/src/scaffolds/index.d.ts} +0 -2
  52. package/dist/src/scaffolds/registerDatasource.d.ts +2 -0
  53. package/dist/src/scaffolds/updateDefaultFactoryConfig.d.ts +1 -0
  54. package/dist/src/utils/architecture.d.ts +31 -0
  55. package/dist/src/utils/contextUtils.d.ts +6 -0
  56. package/dist/src/utils/fileUtils.d.ts +5 -0
  57. package/dist/src/utils/flattenConfig.d.ts +2 -0
  58. package/dist/src/utils/legacyAliases.d.ts +1 -0
  59. package/dist/src/utils/loadConfig.d.ts +16 -0
  60. package/dist/src/utils/packageImports.d.ts +4 -0
  61. package/dist/src/utils/sharedFoundation.d.ts +20 -0
  62. package/dist/src/utils/viteConfig.d.ts +9 -0
  63. package/package.json +48 -36
  64. package/src/checks/architecture.js +154 -0
  65. package/src/checks/checkDomain.js +124 -154
  66. package/src/checks/checkFoldersStructure.js +64 -52
  67. package/src/checks/checkHooks.js +12 -12
  68. package/src/checks/checkImports.js +26 -142
  69. package/src/checks/checkInternal.js +27 -24
  70. package/src/checks/checkLayerBoundaries.js +22 -197
  71. package/src/checks/checkLayerImports.js +14 -134
  72. package/src/checks/checkPresenterNames.js +156 -143
  73. package/src/checks/checkProject.js +27 -26
  74. package/src/checks/checkProviderGraph.js +182 -166
  75. package/src/checks/checkProviderNames.js +123 -112
  76. package/src/generate/layers/generateRepository.js +1 -109
  77. package/src/generate/layers/generateRepositoryMethod.js +1 -90
  78. package/src/generate/layers/generateUseCases.js +1 -44
  79. package/src/generate/module/generateDomain.js +81 -105
  80. package/src/generate/module/generateModule.js +34 -68
  81. package/src/generate/module/generateModulePreset.js +188 -248
  82. package/src/generate/module/generatePresenter.js +441 -369
  83. package/src/generate/module/generateRepository.js +102 -121
  84. package/src/generate/module/generateRepositoryMethod.js +117 -0
  85. package/src/generate/module/generateSchemaFromType.js +283 -280
  86. package/src/generate/module/generateStore.js +41 -0
  87. package/src/generate/module/generateTypesJson.js +196 -195
  88. package/src/generate/module/generateUseCases.js +47 -55
  89. package/src/generate/module/repositoryModuleShared.js +480 -459
  90. package/src/generate/routes/generateRoutes.js +165 -174
  91. package/src/generate/ui/generateComponent.js +44 -64
  92. package/src/generate/ui/generateDesignComponent.js +21 -41
  93. package/src/generate/ui/generateWidget.js +21 -41
  94. package/src/git/commit.js +67 -0
  95. package/src/git/push.js +19 -0
  96. package/src/git/runGit.js +11 -0
  97. package/src/init/initAliases.js +19 -135
  98. package/src/init/initEdges.js +79 -54
  99. package/src/init/initStructure.js +31 -145
  100. package/src/install/configureCommitTools.js +1 -0
  101. package/src/install/installFresh.js +39 -68
  102. package/src/migrate/migrate.js +914 -0
  103. package/src/migrate/presenters.js +265 -0
  104. package/src/plugins/addLint.js +52 -219
  105. package/src/scaffolds/createCoreSchema.js +65 -91
  106. package/src/scaffolds/createDatasource.js +67 -101
  107. package/src/scaffolds/createProgram.js +8 -8
  108. package/src/scaffolds/createResponse.js +29 -29
  109. package/src/scaffolds/createSchemaRule.js +19 -19
  110. package/src/scaffolds/createTranslationManager.js +84 -37
  111. package/src/scaffolds/index.js +0 -2
  112. package/src/scaffolds/registerDatasource.js +59 -0
  113. package/src/scaffolds/updateDefaultFactoryConfig.js +31 -0
  114. package/src/utils/architecture.js +145 -0
  115. package/src/utils/contextUtils.js +32 -65
  116. package/src/utils/fileUtils.js +69 -50
  117. package/src/utils/flattenConfig.js +38 -0
  118. package/src/utils/legacyAliases.js +75 -0
  119. package/src/utils/loadConfig.js +76 -40
  120. package/src/utils/packageImports.js +63 -0
  121. package/src/utils/sharedFoundation.js +36 -42
  122. package/src/utils/viteConfig.js +295 -0
  123. package/.prettierrc +0 -7
  124. package/bin/azure-net.ts +0 -308
  125. package/eslint.config.js +0 -34
  126. package/src/checks/checkDomain.ts +0 -223
  127. package/src/checks/checkFoldersStructure.ts +0 -85
  128. package/src/checks/checkHooks.ts +0 -22
  129. package/src/checks/checkImports.ts +0 -193
  130. package/src/checks/checkInternal.ts +0 -48
  131. package/src/checks/checkLayerBoundaries.ts +0 -255
  132. package/src/checks/checkLayerImports.ts +0 -185
  133. package/src/checks/checkPresenterNames.ts +0 -203
  134. package/src/checks/checkProject.ts +0 -45
  135. package/src/checks/checkProviderGraph.ts +0 -234
  136. package/src/checks/checkProviderNames.ts +0 -165
  137. package/src/generate/layers/generateRepository.ts +0 -123
  138. package/src/generate/layers/generateRepositoryMethod.ts +0 -102
  139. package/src/generate/layers/generateUseCases.ts +0 -50
  140. package/src/generate/layers/repositoryShared.js +0 -506
  141. package/src/generate/layers/repositoryShared.ts +0 -662
  142. package/src/generate/module/generateDomain.ts +0 -147
  143. package/src/generate/module/generateModule.ts +0 -84
  144. package/src/generate/module/generateModulePreset.ts +0 -338
  145. package/src/generate/module/generatePresenter.ts +0 -498
  146. package/src/generate/module/generateRepository.ts +0 -158
  147. package/src/generate/module/generateSchemaFromType.ts +0 -368
  148. package/src/generate/module/generateTypesJson.ts +0 -259
  149. package/src/generate/module/generateUseCases.ts +0 -67
  150. package/src/generate/module/repositoryModuleShared.ts +0 -669
  151. package/src/generate/routes/generateRoutes.ts +0 -282
  152. package/src/generate/ui/generateComponent.ts +0 -100
  153. package/src/generate/ui/generateDesignComponent.ts +0 -71
  154. package/src/generate/ui/generateWidget.ts +0 -71
  155. package/src/init/initAliases.ts +0 -172
  156. package/src/init/initEdges.ts +0 -74
  157. package/src/init/initStructure.ts +0 -172
  158. package/src/install/installFresh.ts +0 -93
  159. package/src/plugins/addLint.ts +0 -274
  160. package/src/scaffolds/createCoreSchema.ts +0 -130
  161. package/src/scaffolds/createDatasource.ts +0 -161
  162. package/src/scaffolds/createDatasourceProvider.js +0 -127
  163. package/src/scaffolds/createDatasourceProvider.ts +0 -161
  164. package/src/scaffolds/createPresenterFactory.js +0 -83
  165. package/src/scaffolds/createPresenterFactory.ts +0 -102
  166. package/src/scaffolds/createProgram.ts +0 -19
  167. package/src/scaffolds/createResponse.ts +0 -66
  168. package/src/scaffolds/createSchemaRule.ts +0 -44
  169. package/src/scaffolds/createTranslationManager.ts +0 -80
  170. package/src/utils/contextUtils.ts +0 -88
  171. package/src/utils/fileUtils.ts +0 -74
  172. package/src/utils/loadConfig.ts +0 -68
  173. package/src/utils/sharedFoundation.ts +0 -70
  174. package/tsconfig.json +0 -19
  175. /package/{src/checks/index.ts → dist/src/checks/index.d.ts} +0 -0
  176. /package/{src/plugins/index.ts → dist/src/plugins/index.d.ts} +0 -0
@@ -1,130 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import fsSync from 'node:fs';
3
- import path from 'node:path';
4
- import prompts from 'prompts';
5
- import { writeIfNotExists, updateIndexTs } from '../utils/fileUtils.js';
6
- import { toPascalCase } from '../utils/contextUtils.js';
7
- import { getFoundationConstructPath, getSharedState } from '../utils/sharedFoundation.js';
8
-
9
- type MessagePreset = 'ru' | 'en' | 'i18n';
10
- type ConfigPath = 'ts' | 'js';
11
-
12
- const resolvePresetImportName = (preset: MessagePreset): string => {
13
- switch (preset) {
14
- case 'ru':
15
- return 'validationMessagesRu';
16
- case 'en':
17
- return 'validationMessagesEn';
18
- case 'i18n':
19
- return 'validationMessagesI18n';
20
- }
21
- };
22
-
23
- const createSchemaFactoryTemplate = (
24
- factoryName: string,
25
- messagesImportName: string
26
- ): string => `import { createSchemaFactory, createRules, ${messagesImportName} } from '@azure-net/kit/delivery';
27
-
28
- export const ${factoryName} = createSchemaFactory(createRules(${messagesImportName}));
29
- `;
30
-
31
- const resolveConfigFile = (cwd: string): { filepath: string; type: ConfigPath; exists: boolean; content: string } => {
32
- const tsPath = path.join(cwd, 'azure-net.config.ts');
33
- const jsPath = path.join(cwd, 'azure-net.config.js');
34
-
35
- if (fsSync.existsSync(tsPath)) {
36
- return { filepath: tsPath, type: 'ts', exists: true, content: fsSync.readFileSync(tsPath, 'utf-8') };
37
- }
38
- if (fsSync.existsSync(jsPath)) {
39
- return { filepath: jsPath, type: 'js', exists: true, content: fsSync.readFileSync(jsPath, 'utf-8') };
40
- }
41
-
42
- return { filepath: tsPath, type: 'ts', exists: false, content: '' };
43
- };
44
-
45
- const buildDefaultSchemaFactoryConfigEntry = (factoryName: string): string => {
46
- return `defaultSchemaFactory: '${factoryName}'`;
47
- };
48
-
49
- const upsertDefaultSchemaFactoryConfig = (content: string, factoryName: string): string => {
50
- const hasExportDefaultObject = /export\s+default\s*\{[\s\S]*\}\s*;?/.test(content);
51
- const defaultFactoryEntry = buildDefaultSchemaFactoryConfigEntry(factoryName);
52
-
53
- if (!hasExportDefaultObject) {
54
- return `export default {\n\t${defaultFactoryEntry}\n};\n`;
55
- }
56
-
57
- let nextContent = content;
58
-
59
- if (/defaultSchemaFactory\s*:/.test(nextContent)) {
60
- nextContent = nextContent.replace(/defaultSchemaFactory\s*:\s*(\{[\s\S]*?\n\s*\}|['"`][^'"`]+['"`])/m, defaultFactoryEntry);
61
- } else if (/defaultSchema\s*:/.test(nextContent)) {
62
- nextContent = nextContent.replace(/defaultSchema\s*:\s*(\{[\s\S]*?\n\s*\}|['"`][^'"`]+['"`])/m, defaultFactoryEntry);
63
- } else {
64
- nextContent = nextContent.replace(/export\s+default\s*\{([\s\S]*)\}\s*;?/, (_full, body: string) => {
65
- const trimmedRight = body.replace(/\s*$/, '');
66
- if (!trimmedRight.length) {
67
- return `export default {\n\t${defaultFactoryEntry}\n};`;
68
- }
69
-
70
- const withComma = trimmedRight.endsWith(',') ? trimmedRight : `${trimmedRight},`;
71
- return `export default {${withComma}\n\t${defaultFactoryEntry}\n};`;
72
- });
73
- }
74
- return nextContent;
75
- };
76
-
77
- export default async function createCoreSchema(): Promise<void> {
78
- const { schemaFactoryNameRaw } = await prompts({
79
- type: 'text',
80
- name: 'schemaFactoryNameRaw',
81
- message: 'Schema factory name:',
82
- initial: 'Schema'
83
- });
84
-
85
- const schemaFactoryName = toPascalCase(String(schemaFactoryNameRaw ?? 'Schema')) || 'Schema';
86
-
87
- const { preset } = await prompts({
88
- type: 'select',
89
- name: 'preset',
90
- message: 'Choose validation messages:',
91
- choices: [
92
- { title: 'Russian', value: 'ru' },
93
- { title: 'English', value: 'en' },
94
- { title: 'i18n', value: 'i18n' }
95
- ],
96
- initial: 2
97
- });
98
-
99
- const selectedPreset = (preset ?? 'i18n') as MessagePreset;
100
- const messagesImportName = resolvePresetImportName(selectedPreset);
101
- const { sharedContext } = await getSharedState();
102
- const coreSchemaPath = getFoundationConstructPath(sharedContext.name, 'schema');
103
- const customRulesPath = path.join(coreSchemaPath, 'custom-rules');
104
- const filePath = path.join(coreSchemaPath, `${schemaFactoryName}.ts`);
105
-
106
- await fs.mkdir(coreSchemaPath, { recursive: true });
107
- await fs.mkdir(customRulesPath, { recursive: true });
108
-
109
- const created = await writeIfNotExists(filePath, createSchemaFactoryTemplate(schemaFactoryName, messagesImportName));
110
- if (!created) {
111
- console.log(`⚠️ Schema factory "${schemaFactoryName}" already exists. File was not overwritten.`);
112
- } else {
113
- await updateIndexTs(coreSchemaPath);
114
- console.log(`✅ Shared schema factory created: ${filePath}`);
115
- }
116
-
117
- const { useAsDefault } = await prompts({
118
- type: 'confirm',
119
- name: 'useAsDefault',
120
- message: 'Use this schema factory as default for the project?',
121
- initial: true
122
- });
123
-
124
- if (!useAsDefault) return;
125
-
126
- const config = resolveConfigFile(process.cwd());
127
- const nextContent = upsertDefaultSchemaFactoryConfig(config.content, schemaFactoryName);
128
- await fs.writeFile(config.filepath, nextContent, 'utf-8');
129
- console.log(`✅ Default schema factory saved to ${path.basename(config.filepath)}`);
130
- }
@@ -1,161 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import prompts from 'prompts';
4
- import { writeIfNotExists, updateIndexTs } from '../utils/fileUtils.js';
5
- import { toPascalCase } from '../utils/contextUtils.js';
6
- import { loadUserConfig } from '../utils/loadConfig.js';
7
- import { normalizeContexts } from '../init/initAliases.js';
8
- import { getFoundationConstructImportPath, getFoundationConstructPath, getSharedState } from '../utils/sharedFoundation.js';
9
-
10
- type ContextChoice = { title: string; value: string };
11
-
12
- const createDatasourceTemplateWithoutResponse = (
13
- className: string
14
- ): string => `import { BaseHttpDatasource, type CreateRequestCallbackType } from '@azure-net/kit/infra';
15
-
16
- export class ${className} extends BaseHttpDatasource {
17
- \tasync createRequest<T>(callback: CreateRequestCallbackType<T>) {
18
- \t\treturn await this.createRawRequest<T>(callback);
19
- \t}
20
- }
21
- `;
22
-
23
- const createDatasourceTemplateWithResponseAndInterface = (
24
- className: string,
25
- responseName: string,
26
- responseImportPath: string
27
- ): string => `import { BaseHttpDatasource, type CreateRequestCallbackType } from '@azure-net/kit/infra';
28
- import { ${responseName}, type I${responseName} } from '${responseImportPath}';
29
-
30
- export class ${className} extends BaseHttpDatasource {
31
- \tasync createRequest<T>(callback: CreateRequestCallbackType<I${responseName}<T>>) {
32
- \t\treturn new ${responseName}<T>(await this.createRawRequest<I${responseName}<T>>(callback));
33
- \t}
34
- }
35
- `;
36
-
37
- const createDatasourceTemplateWithResponse = (
38
- className: string,
39
- responseName: string,
40
- responseImportPath: string
41
- ): string => `import { BaseHttpDatasource, type CreateRequestCallbackType } from '@azure-net/kit/infra';
42
- import { ${responseName} } from '${responseImportPath}';
43
-
44
- export class ${className} extends BaseHttpDatasource {
45
- \tasync createRequest<T>(callback: CreateRequestCallbackType<T>) {
46
- \t\treturn new ${responseName}<T>(await this.createRawRequest<T>(callback));
47
- \t}
48
- }
49
- `;
50
-
51
- const ensureDatasourceClassName = (rawName: string): string => {
52
- const normalized = toPascalCase(rawName || 'MockApi');
53
- return normalized.endsWith('Datasource') ? normalized : `${normalized}Datasource`;
54
- };
55
-
56
- const getContextChoices = async (): Promise<ContextChoice[]> => {
57
- const config = await loadUserConfig();
58
- const contexts = normalizeContexts(config.contexts);
59
-
60
- const choices: ContextChoice[] = [{ title: 'shared foundation', value: '__shared__' }];
61
- for (const context of contexts) {
62
- choices.push({ title: context.name, value: context.name });
63
- }
64
-
65
- return choices;
66
- };
67
-
68
- const getSharedResponses = async (): Promise<string[]> => {
69
- const { sharedContext } = await getSharedState();
70
- const responsesPath = getFoundationConstructPath(sharedContext.name, 'response');
71
- try {
72
- const files = await fs.readdir(responsesPath);
73
- return files.filter((file) => file.endsWith('.ts') && file !== 'index.ts').map((file) => file.replace(/\.ts$/, ''));
74
- } catch {
75
- return [];
76
- }
77
- };
78
-
79
- const hasResponseInterface = async (responseName: string): Promise<boolean> => {
80
- const { sharedContext } = await getSharedState();
81
- const responsePath = path.join(getFoundationConstructPath(sharedContext.name, 'response'), `${responseName}.ts`);
82
- try {
83
- const content = await fs.readFile(responsePath, 'utf-8');
84
- const interfaceRegex = new RegExp(`export\\s+interface\\s+I${responseName}\\b`);
85
- return interfaceRegex.test(content);
86
- } catch {
87
- return false;
88
- }
89
- };
90
-
91
- const resolveTargetPath = (target: string): string => {
92
- if (target === '__shared__') {
93
- throw new Error('Shared target path must be resolved async.');
94
- }
95
-
96
- return path.join(process.cwd(), 'src', 'app', target, 'layers', 'infrastructure', 'http', 'datasources');
97
- };
98
-
99
- export default async function createDatasource(): Promise<void> {
100
- const { datasourceNameRaw } = await prompts({
101
- type: 'text',
102
- name: 'datasourceNameRaw',
103
- message: 'Datasource name:',
104
- initial: 'MockApi'
105
- });
106
-
107
- const className = ensureDatasourceClassName(String(datasourceNameRaw ?? 'MockApi'));
108
-
109
- const contextChoices = await getContextChoices();
110
- const { target } = await prompts({
111
- type: 'select',
112
- name: 'target',
113
- message: 'Where to create datasource?',
114
- choices: contextChoices,
115
- initial: 0
116
- });
117
-
118
- const selectedTarget = String(target ?? '__shared__');
119
- const sharedResponses = await getSharedResponses();
120
-
121
- let selectedResponse: string | null = null;
122
- if (sharedResponses.length > 0) {
123
- const { responseName } = await prompts({
124
- type: 'select',
125
- name: 'responseName',
126
- message: 'Select response for datasource:',
127
- choices: [{ title: 'No response', value: null }, ...sharedResponses.map((response) => ({ title: response, value: response }))],
128
- initial: 0
129
- });
130
- selectedResponse = responseName ? String(responseName) : null;
131
- }
132
-
133
- let content: string;
134
- if (!selectedResponse) {
135
- content = createDatasourceTemplateWithoutResponse(className);
136
- } else {
137
- const { sharedAlias } = await getSharedState();
138
- const responseImportPath = getFoundationConstructImportPath(sharedAlias, 'response');
139
- const withInterface = await hasResponseInterface(selectedResponse);
140
- content = withInterface
141
- ? createDatasourceTemplateWithResponseAndInterface(className, selectedResponse, responseImportPath)
142
- : createDatasourceTemplateWithResponse(className, selectedResponse, responseImportPath);
143
- }
144
-
145
- const targetPath =
146
- selectedTarget === '__shared__'
147
- ? getFoundationConstructPath((await getSharedState()).sharedContext.name, 'datasource')
148
- : resolveTargetPath(selectedTarget);
149
- await fs.mkdir(targetPath, { recursive: true });
150
-
151
- const filePath = path.join(targetPath, `${className}.ts`);
152
- const created = await writeIfNotExists(filePath, content);
153
- await updateIndexTs(targetPath);
154
-
155
- if (!created) {
156
- console.log(`⚠️ Datasource "${className}" already exists. File was not overwritten.`);
157
- return;
158
- }
159
-
160
- console.log(`✅ Datasource created: ${filePath}`);
161
- }
@@ -1,127 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import prompts from 'prompts';
4
- import { writeIfNotExists, updateIndexTs } from '../utils/fileUtils.js';
5
- import { toPascalCase } from '../utils/contextUtils.js';
6
- import { loadUserConfig } from '../utils/loadConfig.js';
7
- import { normalizeContexts } from '../init/initAliases.js';
8
- import { getFoundationConstructImportPath, getFoundationConstructPath, getSharedState } from '../utils/sharedFoundation.js';
9
- const createProviderTemplateWithoutDatasource = (providerName, contextPrefix) => `import { createBoundaryProvider } from '@azure-net/kit';
10
-
11
- export const ${providerName} = createBoundaryProvider('${contextPrefix}${providerName}', {
12
- \tregister: () => ({})
13
- });
14
- `;
15
- const createProviderTemplateWithDatasource = (providerName, contextPrefix, datasourceName, datasourceImportPath) => {
16
- const factoryNameBase = datasourceName.endsWith('Datasource') ? datasourceName.slice(0, -'Datasource'.length) : datasourceName;
17
- const datasourceFactoryName = `${factoryNameBase || datasourceName}Rest`;
18
- return `import { ${datasourceName} } from '${datasourceImportPath}';
19
- import { createHttpServiceInstance } from '@azure-net/kit/infra';
20
- import { createBoundaryProvider } from '@azure-net/kit';
21
-
22
- export const ${providerName} = createBoundaryProvider('${contextPrefix}${providerName}', {
23
- \tregister: () => ({
24
- \t\t${datasourceFactoryName}: () =>
25
- \t\t\tnew ${datasourceName}({
26
- \t\t\t\thttp: createHttpServiceInstance({
27
- \t\t\t\t\tprefixUrl: 'https://localhost'
28
- \t\t\t\t})
29
- \t\t\t})
30
- \t})
31
- });
32
- `;
33
- };
34
- const getDatasourcesFromPath = async (targetPath) => {
35
- try {
36
- const files = await fs.readdir(targetPath);
37
- return files.filter((file) => file.endsWith('.ts') && file !== 'index.ts').map((file) => file.replace(/\.ts$/, ''));
38
- } catch {
39
- return [];
40
- }
41
- };
42
- const resolveContextPrefix = (target) => (target === '__shared__' ? 'Shared' : toPascalCase(target));
43
- const resolveProviderPath = (target) => {
44
- if (target === '__shared__') {
45
- throw new Error('Shared provider path must be resolved async.');
46
- }
47
- return path.join(process.cwd(), 'src', 'app', target, 'layers', 'infrastructure', 'providers');
48
- };
49
- const resolveContextAlias = (contexts, targetContext) => {
50
- const found = contexts.find((context) => context.name === targetContext);
51
- if (!found) {
52
- return `$${targetContext}`;
53
- }
54
- return found.alias.startsWith('$') ? found.alias : `$${found.alias}`;
55
- };
56
- const ensureProviderName = (rawName) => {
57
- const normalized = toPascalCase(rawName || 'DatasourceProvider') || 'DatasourceProvider';
58
- return normalized.endsWith('Provider') ? normalized : `${normalized}Provider`;
59
- };
60
- export default async function createDatasourceProvider() {
61
- const { providerNameRaw } = await prompts({
62
- type: 'text',
63
- name: 'providerNameRaw',
64
- message: 'Datasource provider name:',
65
- initial: 'DatasourceProvider'
66
- });
67
- const providerName = ensureProviderName(String(providerNameRaw ?? 'DatasourceProvider'));
68
- const config = await loadUserConfig();
69
- const contexts = normalizeContexts(config.contexts);
70
- const contextChoices = [
71
- { title: 'shared foundation', value: '__shared__' },
72
- ...contexts.map((context) => ({ title: context.name, value: context.name }))
73
- ];
74
- const { target } = await prompts({
75
- type: 'select',
76
- name: 'target',
77
- message: 'Where to create datasource provider?',
78
- choices: contextChoices,
79
- initial: 0
80
- });
81
- const selectedTarget = String(target ?? '__shared__');
82
- const { sharedAlias, sharedContext } = await getSharedState();
83
- const sharedDatasources = await getDatasourcesFromPath(getFoundationConstructPath(sharedContext.name, 'datasource'));
84
- const contextDatasources =
85
- selectedTarget === '__shared__'
86
- ? []
87
- : await getDatasourcesFromPath(
88
- path.join(process.cwd(), 'src', 'app', selectedTarget, 'layers', 'infrastructure', 'http', 'datasources')
89
- );
90
- const datasourceChoices = [{ title: 'No datasource', value: null }];
91
- for (const datasource of sharedDatasources) {
92
- datasourceChoices.push({ title: `${datasource} (shared foundation)`, value: { name: datasource, source: 'shared' } });
93
- }
94
- for (const datasource of contextDatasources) {
95
- datasourceChoices.push({ title: `${datasource} (${selectedTarget})`, value: { name: datasource, source: 'context' } });
96
- }
97
- const { datasourceSelection } = await prompts({
98
- type: 'select',
99
- name: 'datasourceSelection',
100
- message: 'Select datasource:',
101
- choices: datasourceChoices,
102
- initial: 0
103
- });
104
- const selectedDatasource = datasourceSelection ?? null;
105
- const contextPrefix = resolveContextPrefix(selectedTarget);
106
- let content;
107
- if (!selectedDatasource) {
108
- content = createProviderTemplateWithoutDatasource(providerName, contextPrefix);
109
- } else {
110
- const importPath =
111
- selectedDatasource.source === 'shared'
112
- ? getFoundationConstructImportPath(sharedAlias, 'datasource')
113
- : `${resolveContextAlias(contexts, selectedTarget)}/layers/infrastructure/http/datasources`;
114
- content = createProviderTemplateWithDatasource(providerName, contextPrefix, selectedDatasource.name, importPath);
115
- }
116
- const providerPath =
117
- selectedTarget === '__shared__' ? getFoundationConstructPath(sharedContext.name, 'provider') : resolveProviderPath(selectedTarget);
118
- await fs.mkdir(providerPath, { recursive: true });
119
- const filePath = path.join(providerPath, `${providerName}.ts`);
120
- const created = await writeIfNotExists(filePath, content);
121
- await updateIndexTs(providerPath);
122
- if (!created) {
123
- console.log(`⚠️ Datasource provider "${providerName}" already exists. File was not overwritten.`);
124
- return;
125
- }
126
- console.log(`✅ Datasource provider created: ${filePath}`);
127
- }
@@ -1,161 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import prompts from 'prompts';
4
- import { writeIfNotExists, updateIndexTs } from '../utils/fileUtils.js';
5
- import { toPascalCase } from '../utils/contextUtils.js';
6
- import { loadUserConfig } from '../utils/loadConfig.js';
7
- import { normalizeContexts } from '../init/initAliases.js';
8
- import { getFoundationConstructImportPath, getFoundationConstructPath, getSharedState } from '../utils/sharedFoundation.js';
9
-
10
- type NormalizedContext = { name: string; alias: string };
11
- type DatasourceChoiceValue = null | { name: string; source: 'shared' | 'context' };
12
-
13
- const createProviderTemplateWithoutDatasource = (
14
- providerName: string,
15
- contextPrefix: string
16
- ): string => `import { createBoundaryProvider } from '@azure-net/kit';
17
-
18
- export const ${providerName} = createBoundaryProvider('${contextPrefix}${providerName}', {
19
- \tregister: () => ({})
20
- });
21
- `;
22
-
23
- const createProviderTemplateWithDatasource = (
24
- providerName: string,
25
- contextPrefix: string,
26
- datasourceName: string,
27
- datasourceImportPath: string
28
- ): string => {
29
- const factoryNameBase = datasourceName.endsWith('Datasource') ? datasourceName.slice(0, -'Datasource'.length) : datasourceName;
30
- const datasourceFactoryName = `${factoryNameBase || datasourceName}Rest`;
31
-
32
- return `import { ${datasourceName} } from '${datasourceImportPath}';
33
- import { createHttpServiceInstance } from '@azure-net/kit/infra';
34
- import { createBoundaryProvider } from '@azure-net/kit';
35
-
36
- export const ${providerName} = createBoundaryProvider('${contextPrefix}${providerName}', {
37
- \tregister: () => ({
38
- \t\t${datasourceFactoryName}: () =>
39
- \t\t\tnew ${datasourceName}({
40
- \t\t\t\thttp: createHttpServiceInstance({
41
- \t\t\t\t\tprefixUrl: 'https://localhost'
42
- \t\t\t\t})
43
- \t\t\t})
44
- \t})
45
- });
46
- `;
47
- };
48
-
49
- const getDatasourcesFromPath = async (targetPath: string): Promise<string[]> => {
50
- try {
51
- const files = await fs.readdir(targetPath);
52
- return files.filter((file) => file.endsWith('.ts') && file !== 'index.ts').map((file) => file.replace(/\.ts$/, ''));
53
- } catch {
54
- return [];
55
- }
56
- };
57
-
58
- const resolveContextPrefix = (target: string): string => (target === '__shared__' ? 'Shared' : toPascalCase(target));
59
-
60
- const resolveProviderPath = (target: string): string => {
61
- if (target === '__shared__') {
62
- throw new Error('Shared provider path must be resolved async.');
63
- }
64
-
65
- return path.join(process.cwd(), 'src', 'app', target, 'layers', 'infrastructure', 'providers');
66
- };
67
-
68
- const resolveContextAlias = (contexts: NormalizedContext[], targetContext: string): string => {
69
- const found = contexts.find((context) => context.name === targetContext);
70
- if (!found) {
71
- return `$${targetContext}`;
72
- }
73
-
74
- return found.alias.startsWith('$') ? found.alias : `$${found.alias}`;
75
- };
76
-
77
- const ensureProviderName = (rawName: string): string => {
78
- const normalized = toPascalCase(rawName || 'DatasourceProvider') || 'DatasourceProvider';
79
- return normalized.endsWith('Provider') ? normalized : `${normalized}Provider`;
80
- };
81
-
82
- export default async function createDatasourceProvider(): Promise<void> {
83
- const { providerNameRaw } = await prompts({
84
- type: 'text',
85
- name: 'providerNameRaw',
86
- message: 'Datasource provider name:',
87
- initial: 'DatasourceProvider'
88
- });
89
-
90
- const providerName = ensureProviderName(String(providerNameRaw ?? 'DatasourceProvider'));
91
- const config = await loadUserConfig();
92
- const contexts = normalizeContexts(config.contexts) as NormalizedContext[];
93
- const contextChoices = [
94
- { title: 'shared foundation', value: '__shared__' },
95
- ...contexts.map((context) => ({ title: context.name, value: context.name }))
96
- ];
97
-
98
- const { target } = await prompts({
99
- type: 'select',
100
- name: 'target',
101
- message: 'Where to create datasource provider?',
102
- choices: contextChoices,
103
- initial: 0
104
- });
105
-
106
- const selectedTarget = String(target ?? '__shared__');
107
- const { sharedAlias, sharedContext } = await getSharedState();
108
- const sharedDatasources = await getDatasourcesFromPath(getFoundationConstructPath(sharedContext.name, 'datasource'));
109
- const contextDatasources =
110
- selectedTarget === '__shared__'
111
- ? []
112
- : await getDatasourcesFromPath(
113
- path.join(process.cwd(), 'src', 'app', selectedTarget, 'layers', 'infrastructure', 'http', 'datasources')
114
- );
115
-
116
- const datasourceChoices: Array<{ title: string; value: DatasourceChoiceValue }> = [{ title: 'No datasource', value: null }];
117
- for (const datasource of sharedDatasources) {
118
- datasourceChoices.push({ title: `${datasource} (shared foundation)`, value: { name: datasource, source: 'shared' } });
119
- }
120
- for (const datasource of contextDatasources) {
121
- datasourceChoices.push({ title: `${datasource} (${selectedTarget})`, value: { name: datasource, source: 'context' } });
122
- }
123
-
124
- const { datasourceSelection } = await prompts({
125
- type: 'select',
126
- name: 'datasourceSelection',
127
- message: 'Select datasource:',
128
- choices: datasourceChoices,
129
- initial: 0
130
- });
131
-
132
- const selectedDatasource = (datasourceSelection ?? null) as DatasourceChoiceValue;
133
- const contextPrefix = resolveContextPrefix(selectedTarget);
134
- let content: string;
135
-
136
- if (!selectedDatasource) {
137
- content = createProviderTemplateWithoutDatasource(providerName, contextPrefix);
138
- } else {
139
- const importPath =
140
- selectedDatasource.source === 'shared'
141
- ? getFoundationConstructImportPath(sharedAlias, 'datasource')
142
- : `${resolveContextAlias(contexts, selectedTarget)}/layers/infrastructure/http/datasources`;
143
-
144
- content = createProviderTemplateWithDatasource(providerName, contextPrefix, selectedDatasource.name, importPath);
145
- }
146
-
147
- const providerPath =
148
- selectedTarget === '__shared__' ? getFoundationConstructPath(sharedContext.name, 'provider') : resolveProviderPath(selectedTarget);
149
- await fs.mkdir(providerPath, { recursive: true });
150
-
151
- const filePath = path.join(providerPath, `${providerName}.ts`);
152
- const created = await writeIfNotExists(filePath, content);
153
- await updateIndexTs(providerPath);
154
-
155
- if (!created) {
156
- console.log(`⚠️ Datasource provider "${providerName}" already exists. File was not overwritten.`);
157
- return;
158
- }
159
-
160
- console.log(`✅ Datasource provider created: ${filePath}`);
161
- }
@@ -1,83 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import fsSync from 'node:fs';
3
- import path from 'node:path';
4
- import prompts from 'prompts';
5
- import { writeIfNotExists, updateIndexTs } from '../utils/fileUtils.js';
6
- import { toPascalCase } from '../utils/contextUtils.js';
7
- import { getFoundationConstructPath, getSharedState } from '../utils/sharedFoundation.js';
8
- const createPresenterFactoryTemplate = (
9
- factoryName
10
- ) => `import { createAsyncHelpers, createPresenterFactory } from '@azure-net/kit/delivery';
11
-
12
- export const AsyncHelpers = createAsyncHelpers();
13
-
14
- export const ${factoryName} = createPresenterFactory({ ...AsyncHelpers });
15
- `;
16
- const resolveConfigFile = (cwd) => {
17
- const tsPath = path.join(cwd, 'azure-net.config.ts');
18
- const jsPath = path.join(cwd, 'azure-net.config.js');
19
- if (fsSync.existsSync(tsPath)) {
20
- return { filepath: tsPath, type: 'ts', exists: true, content: fsSync.readFileSync(tsPath, 'utf-8') };
21
- }
22
- if (fsSync.existsSync(jsPath)) {
23
- return { filepath: jsPath, type: 'js', exists: true, content: fsSync.readFileSync(jsPath, 'utf-8') };
24
- }
25
- return { filepath: tsPath, type: 'ts', exists: false, content: '' };
26
- };
27
- const buildDefaultPresenterFactoryConfigEntry = (factoryName) => {
28
- return `defaultPresenterFactory: '${factoryName}'`;
29
- };
30
- const upsertDefaultPresenterFactoryConfig = (content, factoryName) => {
31
- const hasExportDefaultObject = /export\s+default\s*\{[\s\S]*\}\s*;?/.test(content);
32
- const defaultFactoryEntry = buildDefaultPresenterFactoryConfigEntry(factoryName);
33
- if (!hasExportDefaultObject) {
34
- return `export default {\n\t${defaultFactoryEntry}\n};\n`;
35
- }
36
- let nextContent = content;
37
- if (/defaultPresenterFactory\s*:/.test(nextContent)) {
38
- nextContent = nextContent.replace(/defaultPresenterFactory\s*:\s*(\{[\s\S]*?\n\s*\}|['"`][^'"`]+['"`])/m, defaultFactoryEntry);
39
- } else if (/defaultPresenter\s*:/.test(nextContent)) {
40
- nextContent = nextContent.replace(/defaultPresenter\s*:\s*(\{[\s\S]*?\n\s*\}|['"`][^'"`]+['"`])/m, defaultFactoryEntry);
41
- } else {
42
- nextContent = nextContent.replace(/export\s+default\s*\{([\s\S]*)\}\s*;?/, (_full, body) => {
43
- const trimmedRight = body.replace(/\s*$/, '');
44
- if (!trimmedRight.length) {
45
- return `export default {\n\t${defaultFactoryEntry}\n};`;
46
- }
47
- const withComma = trimmedRight.endsWith(',') ? trimmedRight : `${trimmedRight},`;
48
- return `export default {${withComma}\n\t${defaultFactoryEntry}\n};`;
49
- });
50
- }
51
- return nextContent;
52
- };
53
- export default async function createPresenterFactory() {
54
- const { presenterFactoryNameRaw } = await prompts({
55
- type: 'text',
56
- name: 'presenterFactoryNameRaw',
57
- message: 'Presenter factory name:',
58
- initial: 'AppPresenter'
59
- });
60
- const presenterFactoryName = toPascalCase(String(presenterFactoryNameRaw ?? 'AppPresenter')) || 'AppPresenter';
61
- const { sharedContext } = await getSharedState();
62
- const presenterRootPath = getFoundationConstructPath(sharedContext.name, 'presenter');
63
- const filePath = path.join(presenterRootPath, `${presenterFactoryName}.ts`);
64
- await fs.mkdir(presenterRootPath, { recursive: true });
65
- const created = await writeIfNotExists(filePath, createPresenterFactoryTemplate(presenterFactoryName));
66
- if (!created) {
67
- console.log(`⚠️ Presenter factory "${presenterFactoryName}" already exists. File was not overwritten.`);
68
- } else {
69
- await updateIndexTs(presenterRootPath);
70
- console.log(`✅ Presenter factory created: ${filePath}`);
71
- }
72
- const { useAsDefault } = await prompts({
73
- type: 'confirm',
74
- name: 'useAsDefault',
75
- message: 'Use this presenter factory as default for the project?',
76
- initial: true
77
- });
78
- if (!useAsDefault) return;
79
- const config = resolveConfigFile(process.cwd());
80
- const nextContent = upsertDefaultPresenterFactoryConfig(config.content, presenterFactoryName);
81
- await fs.writeFile(config.filepath, nextContent, 'utf-8');
82
- console.log(`✅ Default presenter factory saved to ${path.basename(config.filepath)}`);
83
- }