@azure-net/cli 2.0.4 → 2.0.5
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/package.json
CHANGED
|
@@ -3,9 +3,9 @@ import fs from 'fs/promises';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { selectContext, getContextPath, toPascalCase, toCamelCase, getAvailableFiles } from '../../utils/contextUtils.js';
|
|
5
5
|
import { writeIfNotExists, updateIndexTs, ensureIndexExports } from '../../utils/fileUtils.js';
|
|
6
|
-
import { ensureProvider, addToProvider } from '../../utils/providerUtils.js';
|
|
6
|
+
import { ensureProvider, addToProvider, ensureDatasourceProvider } from '../../utils/providerUtils.js';
|
|
7
7
|
|
|
8
|
-
// Templates
|
|
8
|
+
// Templates remain the same as before...
|
|
9
9
|
const entityTemplate = `export interface I{{name}} {
|
|
10
10
|
\tid: number;
|
|
11
11
|
\t// Add entity fields here
|
|
@@ -114,7 +114,6 @@ export const Update{{name}}Schema = {{schemaFactory}}<I{{name}}UpdateRequest>()
|
|
|
114
114
|
\t}))
|
|
115
115
|
\t.create();`;
|
|
116
116
|
|
|
117
|
-
// Presenter template with core factory (includes async helpers)
|
|
118
117
|
const presenterWithCoreTemplate = `import { {{presenterFactory}} } from '\$core/Presenter';
|
|
119
118
|
import { ApplicationProvider } from '\${{context}}/Application';
|
|
120
119
|
import { Create{{name}}Schema, Update{{name}}Schema } from './Schema';
|
|
@@ -145,7 +144,6 @@ export const {{name}}Presenter = {{presenterFactory}}('{{name}}Presenter', ({ cr
|
|
|
145
144
|
\treturn { collection, resource, create, update, remove };
|
|
146
145
|
});`;
|
|
147
146
|
|
|
148
|
-
// Presenter template without async helpers
|
|
149
147
|
const presenterWithoutCoreTemplate = `import { createPresenter } from '@azure-net/kit';
|
|
150
148
|
import { ApplicationProvider } from '\${{context}}/Application';
|
|
151
149
|
import { Create{{name}}Schema, Update{{name}}Schema } from './Schema';
|
|
@@ -308,7 +306,6 @@ export default async function generateCrud() {
|
|
|
308
306
|
: '$core/Schema';
|
|
309
307
|
|
|
310
308
|
if (schemaType === 'package') {
|
|
311
|
-
// Add the import for createSchemaFactory and rules
|
|
312
309
|
const schemaImportFull = `import { createSchemaFactory } from '@azure-net/kit';
|
|
313
310
|
import { createRules, validationMessagesI18n } from '@azure-net/kit/schema';
|
|
314
311
|
|
|
@@ -352,7 +349,7 @@ const Schema = createSchemaFactory(createRules(validationMessagesI18n));`;
|
|
|
352
349
|
}
|
|
353
350
|
await updateIndexTs(schemaPath);
|
|
354
351
|
|
|
355
|
-
// 6. Create Presenter
|
|
352
|
+
// 6. Create Presenter
|
|
356
353
|
const presenterTemplate = presenterType === 'package'
|
|
357
354
|
? presenterWithoutCoreTemplate
|
|
358
355
|
: presenterWithCoreTemplate;
|
|
@@ -375,24 +372,14 @@ const Schema = createSchemaFactory(createRules(validationMessagesI18n));`;
|
|
|
375
372
|
|
|
376
373
|
// 7. Setup Providers
|
|
377
374
|
// Ensure DatasourceProvider
|
|
378
|
-
|
|
379
|
-
if (!(await fs.access(datasourceProviderPath).then(() => true).catch(() => false))) {
|
|
380
|
-
const datasourceProviderContent = `import { createBoundaryProvider } from '@azure-net/kit';
|
|
381
|
-
import { ${datasource.name} } from '${datasource.from === 'core' ? '$core/Datasource' : '../Http/Datasource'}';
|
|
382
|
-
|
|
383
|
-
export const DatasourceProvider = createBoundaryProvider('${contextName}DatasourceProvider', () => ({
|
|
384
|
-
\t${datasource.name}: () => DatasourceProvider.${datasource.name}
|
|
385
|
-
}));`;
|
|
386
|
-
await writeIfNotExists(datasourceProviderPath, datasourceProviderContent);
|
|
387
|
-
await updateIndexTs(path.dirname(datasourceProviderPath));
|
|
388
|
-
}
|
|
375
|
+
await ensureDatasourceProvider(context, datasource.name, datasource.from === 'core');
|
|
389
376
|
|
|
390
377
|
// Ensure InfrastructureProvider
|
|
391
|
-
const infraProvider = await ensureProvider(context, 'Infrastructure', {});
|
|
378
|
+
const infraProvider = await ensureProvider(context, 'Infrastructure', { hasDatasource: true });
|
|
392
379
|
await addToProvider(
|
|
393
380
|
infraProvider.path,
|
|
394
381
|
`${pascalName}Repository`,
|
|
395
|
-
|
|
382
|
+
`\$${context}/Infrastructure/Http/Repositories`,
|
|
396
383
|
`DatasourceProvider.${datasource.name}`
|
|
397
384
|
);
|
|
398
385
|
|
|
@@ -401,7 +388,7 @@ export const DatasourceProvider = createBoundaryProvider('${contextName}Datasour
|
|
|
401
388
|
await addToProvider(
|
|
402
389
|
appProvider.path,
|
|
403
390
|
`${pascalName}Service`,
|
|
404
|
-
|
|
391
|
+
`\$${context}/Application/Services`,
|
|
405
392
|
`InfrastructureProvider.${pascalName}Repository`
|
|
406
393
|
);
|
|
407
394
|
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import prompts from 'prompts';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import
|
|
3
|
+
import fs from 'fs/promises';
|
|
4
|
+
import { selectContext, getContextPath, toPascalCase, getAvailableFiles } from '../../utils/contextUtils.js';
|
|
4
5
|
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
5
|
-
import { ensureProvider, addToProvider } from '../../utils/providerUtils.js';
|
|
6
6
|
|
|
7
7
|
const datasourceWithResponseTemplate = `import { BaseHttpDatasource, type CreateRequestCallbackType } from '@azure-net/kit/infra';
|
|
8
8
|
import { {{responseClass}}, type {{responseInterface}} } from '{{responseImport}}';
|
|
9
|
+
import { HttpService } from '@azure-net/kit/infra';
|
|
9
10
|
|
|
10
11
|
export class {{name}}Datasource extends BaseHttpDatasource {
|
|
11
|
-
\tconstructor(
|
|
12
|
-
\t\tsuper({
|
|
12
|
+
\tconstructor(config?: { baseUrl?: string; [key: string]: unknown }) {
|
|
13
|
+
\t\tsuper({
|
|
14
|
+
\t\t\thttp: new HttpService({
|
|
15
|
+
\t\t\t\tbaseUrl: config?.baseUrl || 'https://api.example.com',
|
|
16
|
+
\t\t\t\t...config
|
|
17
|
+
\t\t\t})
|
|
18
|
+
\t\t});
|
|
13
19
|
\t}
|
|
14
20
|
|
|
15
21
|
\tasync createRequest<T>(callback: CreateRequestCallbackType<{{responseInterface}}<T>>) {
|
|
@@ -17,14 +23,6 @@ export class {{name}}Datasource extends BaseHttpDatasource {
|
|
|
17
23
|
\t}
|
|
18
24
|
}`;
|
|
19
25
|
|
|
20
|
-
const datasourceWithoutResponseTemplate = `import { BaseHttpDatasource } from '@azure-net/kit/infra';
|
|
21
|
-
|
|
22
|
-
export class {{name}}Datasource extends BaseHttpDatasource {
|
|
23
|
-
\tconstructor(private http: HttpService) {
|
|
24
|
-
\t\tsuper({ http });
|
|
25
|
-
\t}
|
|
26
|
-
}`;
|
|
27
|
-
|
|
28
26
|
export default async function generateDatasource() {
|
|
29
27
|
const context = await selectContext();
|
|
30
28
|
|
|
@@ -35,7 +33,6 @@ export default async function generateDatasource() {
|
|
|
35
33
|
});
|
|
36
34
|
|
|
37
35
|
const pascalName = toPascalCase(name);
|
|
38
|
-
const camelName = toCamelCase(name);
|
|
39
36
|
const contextPath = getContextPath(context);
|
|
40
37
|
|
|
41
38
|
// Get available responses
|
|
@@ -70,17 +67,17 @@ export default async function generateDatasource() {
|
|
|
70
67
|
choices: allResponses
|
|
71
68
|
});
|
|
72
69
|
|
|
73
|
-
// Determine interface name
|
|
70
|
+
// Determine interface name
|
|
74
71
|
const responseInterface = `I${response.name.replace('Response', '')}Response`;
|
|
75
72
|
|
|
76
73
|
const datasourcePath = context === 'core'
|
|
77
74
|
? path.join(contextPath, 'Datasource')
|
|
78
|
-
: path.join(contextPath, 'Infrastructure
|
|
75
|
+
: path.join(contextPath, 'Infrastructure/Http/Datasource');
|
|
79
76
|
|
|
80
77
|
const responseImport = response.from === 'core'
|
|
81
|
-
? '$core/Response'
|
|
78
|
+
? context === 'core' ? '../Response' : '$core/Response'
|
|
82
79
|
: context === 'core'
|
|
83
|
-
?
|
|
80
|
+
? `../contexts/${context}/Infrastructure/Response`
|
|
84
81
|
: '../../Response';
|
|
85
82
|
|
|
86
83
|
const content = datasourceWithResponseTemplate
|
|
@@ -93,63 +90,6 @@ export default async function generateDatasource() {
|
|
|
93
90
|
await writeIfNotExists(filePath, content);
|
|
94
91
|
await updateIndexTs(datasourcePath);
|
|
95
92
|
|
|
96
|
-
// If not in core, ensure DatasourceProvider exists
|
|
97
|
-
if (context !== 'core') {
|
|
98
|
-
const contextName = toPascalCase(context);
|
|
99
|
-
const providerPath = path.join(contextPath, 'Infrastructure/Providers/DatasourceProvider.ts');
|
|
100
|
-
|
|
101
|
-
if (!(await fs.access(providerPath).then(() => true).catch(() => false))) {
|
|
102
|
-
const providerContent = `import { createBoundaryProvider } from '@azure-net/kit';
|
|
103
|
-
import { HttpService } from '@azure-net/kit/infra';
|
|
104
|
-
import { ${pascalName}Datasource } from '../Http/Datasource';
|
|
105
|
-
|
|
106
|
-
export const DatasourceProvider = createBoundaryProvider('${contextName}DatasourceProvider', () => ({
|
|
107
|
-
\t${pascalName}Datasource: () => new ${pascalName}Datasource(
|
|
108
|
-
\t\tnew HttpService({ baseUrl: 'https://api.example.com' })
|
|
109
|
-
\t)
|
|
110
|
-
}));`;
|
|
111
|
-
await writeIfNotExists(providerPath, providerContent);
|
|
112
|
-
await updateIndexTs(path.dirname(providerPath));
|
|
113
|
-
} else {
|
|
114
|
-
// Add datasource to existing provider
|
|
115
|
-
await addDatasourceToProvider(providerPath, pascalName);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
93
|
console.log(`✅ Datasource created at ${filePath}`);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
async function addDatasourceToProvider(providerPath, datasourceName) {
|
|
123
|
-
let content = await fs.readFile(providerPath, 'utf-8');
|
|
124
|
-
|
|
125
|
-
// Add import if not exists
|
|
126
|
-
if (!content.includes(`${datasourceName}Datasource`)) {
|
|
127
|
-
const importStatement = `import { ${datasourceName}Datasource } from '../Http/Datasource';`;
|
|
128
|
-
const lastImportIndex = content.lastIndexOf('import ');
|
|
129
|
-
const endOfImportLine = content.indexOf('\n', lastImportIndex);
|
|
130
|
-
content = content.slice(0, endOfImportLine + 1) + importStatement + '\n' + content.slice(endOfImportLine + 1);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Add factory method
|
|
134
|
-
const factoryLine = `\t${datasourceName}Datasource: () => new ${datasourceName}Datasource(
|
|
135
|
-
\t\tnew HttpService({ baseUrl: 'https://api.example.com' })
|
|
136
|
-
\t)`;
|
|
137
|
-
|
|
138
|
-
if (!content.includes(`${datasourceName}Datasource:`)) {
|
|
139
|
-
const returnIndex = content.indexOf('=> ({');
|
|
140
|
-
const endOfReturn = content.indexOf('})', returnIndex);
|
|
141
|
-
const beforeEnd = content.lastIndexOf('\n', endOfReturn);
|
|
142
|
-
|
|
143
|
-
// Check if there are existing entries
|
|
144
|
-
const servicesSection = content.substring(returnIndex, endOfReturn);
|
|
145
|
-
const hasServices = servicesSection.includes(':');
|
|
146
|
-
|
|
147
|
-
if (hasServices) {
|
|
148
|
-
content = content.slice(0, beforeEnd) + ',\n' + factoryLine + content.slice(beforeEnd);
|
|
149
|
-
} else {
|
|
150
|
-
content = content.slice(0, beforeEnd + 1) + factoryLine + content.slice(beforeEnd);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
await fs.writeFile(providerPath, content, 'utf-8');
|
|
94
|
+
console.log(`\n💡 Remember to configure the datasource in DatasourceProvider when using it in repositories.`);
|
|
155
95
|
}
|
|
@@ -3,7 +3,7 @@ import fs from 'fs/promises';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { selectContext, getContextPath, toPascalCase, getAvailableFiles, toCamelCase } from '../../utils/contextUtils.js';
|
|
5
5
|
import { writeIfNotExists, updateIndexTs } from '../../utils/fileUtils.js';
|
|
6
|
-
import { ensureProvider, addToProvider } from '../../utils/providerUtils.js';
|
|
6
|
+
import { ensureProvider, addToProvider, ensureDatasourceProvider } from '../../utils/providerUtils.js';
|
|
7
7
|
|
|
8
8
|
const repositoryTemplate = `import { {{datasource}} } from '{{datasourceImport}}';
|
|
9
9
|
|
|
@@ -37,7 +37,7 @@ export default async function generateRepository() {
|
|
|
37
37
|
path.join(process.cwd(), 'src/app/core/Datasource')
|
|
38
38
|
);
|
|
39
39
|
const contextDatasources = await getAvailableFiles(
|
|
40
|
-
path.join(contextPath, 'Infrastructure
|
|
40
|
+
path.join(contextPath, 'Infrastructure/Http/Datasource')
|
|
41
41
|
);
|
|
42
42
|
|
|
43
43
|
const allDatasources = [
|
|
@@ -59,7 +59,7 @@ export default async function generateRepository() {
|
|
|
59
59
|
|
|
60
60
|
const pascalName = toPascalCase(name);
|
|
61
61
|
const contextName = toPascalCase(context);
|
|
62
|
-
const repoPath = path.join(contextPath, 'Infrastructure
|
|
62
|
+
const repoPath = path.join(contextPath, 'Infrastructure/Http/Repositories');
|
|
63
63
|
const filePath = path.join(repoPath, `${pascalName}Repository.ts`);
|
|
64
64
|
|
|
65
65
|
// Generate repository
|
|
@@ -77,24 +77,14 @@ export default async function generateRepository() {
|
|
|
77
77
|
await updateIndexTs(repoPath);
|
|
78
78
|
|
|
79
79
|
// Ensure DatasourceProvider exists
|
|
80
|
-
|
|
81
|
-
if (!(await fs.access(datasourceProviderPath).then(() => true).catch(() => false))) {
|
|
82
|
-
const datasourceProviderContent = `import { createBoundaryProvider } from '@azure-net/kit';
|
|
83
|
-
import { ${datasource.name} } from '${datasource.from === 'core' ? '$core/Datasource' : '../Http/Datasource'}';
|
|
84
|
-
|
|
85
|
-
export const DatasourceProvider = createBoundaryProvider('${contextName}DatasourceProvider', () => ({
|
|
86
|
-
\t${datasource.name}: () => new ${datasource.name}()
|
|
87
|
-
}));`;
|
|
88
|
-
await writeIfNotExists(datasourceProviderPath, datasourceProviderContent);
|
|
89
|
-
await updateIndexTs(path.dirname(datasourceProviderPath));
|
|
90
|
-
}
|
|
80
|
+
await ensureDatasourceProvider(context, datasource.name, datasource.from === 'core');
|
|
91
81
|
|
|
92
82
|
// Ensure InfrastructureProvider and add repository
|
|
93
83
|
const infraProvider = await ensureProvider(context, 'Infrastructure', { hasDatasource: true });
|
|
94
84
|
await addToProvider(
|
|
95
85
|
infraProvider.path,
|
|
96
86
|
`${pascalName}Repository`,
|
|
97
|
-
|
|
87
|
+
`\$${context}/Infrastructure/Http/Repositories`,
|
|
98
88
|
`DatasourceProvider.${datasource.name}`
|
|
99
89
|
);
|
|
100
90
|
|
|
@@ -35,7 +35,6 @@ function generateProviderContent(context, layer, dependencies) {
|
|
|
35
35
|
|
|
36
36
|
let imports = [`import { createBoundaryProvider } from '@azure-net/kit';`];
|
|
37
37
|
let deps = [];
|
|
38
|
-
let depParams = '';
|
|
39
38
|
|
|
40
39
|
if (dependencies.hasDatasource && layer === 'Infrastructure') {
|
|
41
40
|
imports.push(`import { DatasourceProvider } from './DatasourceProvider';`);
|
|
@@ -47,10 +46,7 @@ function generateProviderContent(context, layer, dependencies) {
|
|
|
47
46
|
deps.push('InfrastructureProvider');
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
depParams = `{ ${deps.join(', ')} }`;
|
|
52
|
-
}
|
|
53
|
-
|
|
49
|
+
const depParams = deps.length > 0 ? `{ ${deps.join(', ')} }` : '';
|
|
54
50
|
const dependsOnStr = deps.length > 0
|
|
55
51
|
? `,\n\t{ dependsOn: { ${deps.join(', ')} } }`
|
|
56
52
|
: '';
|
|
@@ -59,7 +55,7 @@ function generateProviderContent(context, layer, dependencies) {
|
|
|
59
55
|
|
|
60
56
|
export const ${varName} = createBoundaryProvider(
|
|
61
57
|
\t'${boundaryName}',
|
|
62
|
-
\t(${depParams
|
|
58
|
+
\t(${depParams}) => ({
|
|
63
59
|
\t\t// Services will be added here
|
|
64
60
|
\t})${dependsOnStr}
|
|
65
61
|
);`;
|
|
@@ -68,17 +64,69 @@ export const ${varName} = createBoundaryProvider(
|
|
|
68
64
|
export async function addToProvider(providerPath, serviceName, importPath, dependency = null) {
|
|
69
65
|
let content = await fs.readFile(providerPath, 'utf-8');
|
|
70
66
|
|
|
71
|
-
//
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
67
|
+
// Parse existing imports to group them
|
|
68
|
+
const importRegex = /^import\s+{([^}]+)}\s+from\s+['"]([^'"]+)['"]/gm;
|
|
69
|
+
const imports = new Map();
|
|
70
|
+
let match;
|
|
71
|
+
|
|
72
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
73
|
+
const [fullMatch, importedItems, fromPath] = match;
|
|
74
|
+
if (!imports.has(fromPath)) {
|
|
75
|
+
imports.set(fromPath, new Set());
|
|
76
|
+
}
|
|
77
|
+
importedItems.split(',').forEach(item => {
|
|
78
|
+
imports.get(fromPath).add(item.trim());
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Add new import to the map
|
|
83
|
+
if (!Array.from(imports.values()).some(set => set.has(serviceName))) {
|
|
84
|
+
if (!imports.has(importPath)) {
|
|
85
|
+
imports.set(importPath, new Set());
|
|
86
|
+
}
|
|
87
|
+
imports.get(importPath).add(serviceName);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Rebuild import section
|
|
91
|
+
const newImports = [`import { createBoundaryProvider } from '@azure-net/kit';`];
|
|
92
|
+
|
|
93
|
+
// Add DatasourceProvider import if exists
|
|
94
|
+
if (content.includes('DatasourceProvider') && !content.includes("import { DatasourceProvider }")) {
|
|
95
|
+
newImports.push(`import { DatasourceProvider } from './DatasourceProvider';`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Add other imports
|
|
99
|
+
for (const [fromPath, items] of imports) {
|
|
100
|
+
if (fromPath !== '@azure-net/kit' && !fromPath.includes('DatasourceProvider')) {
|
|
101
|
+
const itemsStr = Array.from(items).join(', ');
|
|
102
|
+
newImports.push(`import { ${itemsStr} } from '${fromPath}';`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Find where imports end and provider starts
|
|
107
|
+
const providerStartIndex = content.indexOf('export const');
|
|
108
|
+
const beforeProvider = content.substring(0, providerStartIndex);
|
|
109
|
+
const afterProvider = content.substring(providerStartIndex);
|
|
110
|
+
|
|
111
|
+
// Check if DatasourceProvider dependency needs to be added
|
|
112
|
+
let updatedAfterProvider = afterProvider;
|
|
113
|
+
if (dependency && dependency.includes('DatasourceProvider')) {
|
|
114
|
+
// Check if provider already has dependencies
|
|
115
|
+
if (!afterProvider.includes('({ DatasourceProvider })')) {
|
|
116
|
+
// Add DatasourceProvider to function params
|
|
117
|
+
updatedAfterProvider = updatedAfterProvider.replace(
|
|
118
|
+
/createBoundaryProvider\(\s*'[^']+',\s*\(\)/,
|
|
119
|
+
`createBoundaryProvider(\n\t'$1',\n\t({ DatasourceProvider })`
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// Add dependsOn if not exists
|
|
123
|
+
if (!updatedAfterProvider.includes('dependsOn')) {
|
|
124
|
+
updatedAfterProvider = updatedAfterProvider.replace(
|
|
125
|
+
/\)\s*\);$/,
|
|
126
|
+
`),\n\t{ dependsOn: { DatasourceProvider } }\n);`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
82
130
|
}
|
|
83
131
|
|
|
84
132
|
// Add factory method with dependency
|
|
@@ -86,27 +134,121 @@ export async function addToProvider(providerPath, serviceName, importPath, depen
|
|
|
86
134
|
? `\t\t${serviceName}: () => new ${serviceName}(${dependency})`
|
|
87
135
|
: `\t\t${serviceName}: () => new ${serviceName}()`;
|
|
88
136
|
|
|
89
|
-
if (!
|
|
137
|
+
if (!updatedAfterProvider.includes(`${serviceName}:`)) {
|
|
90
138
|
// Find the position to insert
|
|
91
|
-
const returnIndex =
|
|
92
|
-
const endOfReturn =
|
|
139
|
+
const returnIndex = updatedAfterProvider.indexOf('=> ({');
|
|
140
|
+
const endOfReturn = updatedAfterProvider.indexOf('\t})', returnIndex);
|
|
93
141
|
|
|
94
142
|
// Check if there are existing services
|
|
95
|
-
const servicesSection =
|
|
96
|
-
const hasServices = servicesSection.includes(':');
|
|
143
|
+
const servicesSection = updatedAfterProvider.substring(returnIndex, endOfReturn);
|
|
144
|
+
const hasServices = servicesSection.includes(':') && !servicesSection.includes('// Services will be added here');
|
|
97
145
|
|
|
98
146
|
if (hasServices) {
|
|
99
147
|
// Add comma before new service
|
|
100
|
-
const beforeEnd =
|
|
101
|
-
|
|
148
|
+
const beforeEnd = updatedAfterProvider.lastIndexOf('\n', endOfReturn);
|
|
149
|
+
updatedAfterProvider = updatedAfterProvider.slice(0, beforeEnd) + ',\n' + factoryLine + updatedAfterProvider.slice(beforeEnd);
|
|
102
150
|
} else {
|
|
103
151
|
// First service, replace comment
|
|
104
|
-
|
|
152
|
+
updatedAfterProvider = updatedAfterProvider.replace(
|
|
105
153
|
'// Services will be added here',
|
|
106
154
|
factoryLine
|
|
107
155
|
);
|
|
108
156
|
}
|
|
109
157
|
}
|
|
110
158
|
|
|
111
|
-
|
|
159
|
+
// Combine everything
|
|
160
|
+
const finalContent = newImports.join('\n') + '\n\n' + updatedAfterProvider;
|
|
161
|
+
await fs.writeFile(providerPath, finalContent, 'utf-8');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export async function ensureDatasourceProvider(context, datasourceName, isFromCore = true) {
|
|
165
|
+
const contextName = toPascalCase(context);
|
|
166
|
+
const contextPath = path.join(process.cwd(), 'src/app/contexts', context);
|
|
167
|
+
const providerPath = path.join(contextPath, 'Infrastructure/Providers/DatasourceProvider.ts');
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
await fs.access(providerPath);
|
|
171
|
+
// Provider exists, add datasource if needed
|
|
172
|
+
await addDatasourceToProvider(providerPath, datasourceName, isFromCore);
|
|
173
|
+
} catch {
|
|
174
|
+
// Create new DatasourceProvider
|
|
175
|
+
const content = `import { createBoundaryProvider } from '@azure-net/kit';
|
|
176
|
+
import { ${datasourceName} } from '${isFromCore ? '$core' : '../Http/Datasource'}';
|
|
177
|
+
|
|
178
|
+
export const DatasourceProvider = createBoundaryProvider('${contextName}DatasourceProvider', () => ({
|
|
179
|
+
\t${datasourceName}: () => new ${datasourceName}({})
|
|
180
|
+
}));`;
|
|
181
|
+
|
|
182
|
+
await writeIfNotExists(providerPath, content);
|
|
183
|
+
await updateIndexTs(path.dirname(providerPath));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function addDatasourceToProvider(providerPath, datasourceName, isFromCore = true) {
|
|
188
|
+
let content = await fs.readFile(providerPath, 'utf-8');
|
|
189
|
+
|
|
190
|
+
// Check if datasource already exists
|
|
191
|
+
if (content.includes(`${datasourceName}:`)) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Parse existing imports to group them
|
|
196
|
+
const importRegex = /^import\s+{([^}]+)}\s+from\s+['"]([^'"]+)['"]/gm;
|
|
197
|
+
const imports = new Map();
|
|
198
|
+
let match;
|
|
199
|
+
|
|
200
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
201
|
+
const [fullMatch, importedItems, fromPath] = match;
|
|
202
|
+
if (!imports.has(fromPath)) {
|
|
203
|
+
imports.set(fromPath, new Set());
|
|
204
|
+
}
|
|
205
|
+
importedItems.split(',').forEach(item => {
|
|
206
|
+
imports.get(fromPath).add(item.trim());
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Add datasource to imports
|
|
211
|
+
const importPath = isFromCore ? '$core' : '../Http/Datasource';
|
|
212
|
+
if (!imports.has(importPath)) {
|
|
213
|
+
imports.set(importPath, new Set());
|
|
214
|
+
}
|
|
215
|
+
imports.get(importPath).add(datasourceName);
|
|
216
|
+
|
|
217
|
+
// Rebuild import section
|
|
218
|
+
const newImports = [`import { createBoundaryProvider } from '@azure-net/kit';`];
|
|
219
|
+
for (const [fromPath, items] of imports) {
|
|
220
|
+
if (fromPath !== '@azure-net/kit') {
|
|
221
|
+
const itemsStr = Array.from(items).join(', ');
|
|
222
|
+
newImports.push(`import { ${itemsStr} } from '${fromPath}';`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Find provider content
|
|
227
|
+
const providerStartIndex = content.indexOf('export const');
|
|
228
|
+
const afterProvider = content.substring(providerStartIndex);
|
|
229
|
+
|
|
230
|
+
// Add factory method
|
|
231
|
+
const factoryLine = `\t${datasourceName}: () => new ${datasourceName}({})`;
|
|
232
|
+
|
|
233
|
+
const returnIndex = afterProvider.indexOf('=> ({');
|
|
234
|
+
const endOfReturn = afterProvider.indexOf('})', returnIndex);
|
|
235
|
+
|
|
236
|
+
// Check if there are existing services
|
|
237
|
+
const servicesSection = afterProvider.substring(returnIndex, endOfReturn);
|
|
238
|
+
const hasServices = servicesSection.includes(':');
|
|
239
|
+
|
|
240
|
+
let updatedAfterProvider = afterProvider;
|
|
241
|
+
if (hasServices) {
|
|
242
|
+
// Add comma before new service
|
|
243
|
+
const beforeEnd = updatedAfterProvider.lastIndexOf('\n', endOfReturn);
|
|
244
|
+
updatedAfterProvider = updatedAfterProvider.slice(0, beforeEnd) + ',\n' + factoryLine + updatedAfterProvider.slice(beforeEnd);
|
|
245
|
+
} else {
|
|
246
|
+
// First service
|
|
247
|
+
const insertPoint = returnIndex + '=> ({\n'.length;
|
|
248
|
+
updatedAfterProvider = updatedAfterProvider.slice(0, insertPoint) + factoryLine + '\n' + updatedAfterProvider.slice(insertPoint);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Combine everything
|
|
252
|
+
const finalContent = newImports.join('\n') + '\n\n' + updatedAfterProvider;
|
|
253
|
+
await fs.writeFile(providerPath, finalContent, 'utf-8');
|
|
112
254
|
}
|