@azure-net/cli 5.1.1 → 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 +4 -7
  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 -275
  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
@@ -0,0 +1,38 @@
1
+ import ts from 'typescript';
2
+ /** Flatten literal-only spreads without evaluating user configuration or duplicating effects. */
3
+ export function flattenConfigLiterals(content) {
4
+ const source = ts.createSourceFile('azure-net.config.ts', content, ts.ScriptTarget.Latest, true);
5
+ const exported = source.statements.find(ts.isExportAssignment);
6
+ if (!exported)
7
+ return content;
8
+ const unwrap = (node) => (ts.isParenthesizedExpression(node) ? unwrap(node.expression) : node);
9
+ const root = unwrap(exported.expression);
10
+ if (!ts.isObjectLiteralExpression(root))
11
+ return content;
12
+ let changed = false;
13
+ const flatten = (object) => object.properties.flatMap((property) => {
14
+ if (ts.isSpreadAssignment(property)) {
15
+ const value = unwrap(property.expression);
16
+ if (ts.isObjectLiteralExpression(value) &&
17
+ value.properties.every((p) => !ts.isGetAccessorDeclaration(p) &&
18
+ !ts.isSetAccessorDeclaration(p) &&
19
+ !(p.name && p.name.getText(source).replace(/['"]/g, '') === '__proto__'))) {
20
+ changed = true;
21
+ return flatten(value);
22
+ }
23
+ }
24
+ return [property];
25
+ });
26
+ const properties = flatten(root);
27
+ if (!changed)
28
+ return content;
29
+ const names = properties
30
+ .filter((p) => p.name && !ts.isComputedPropertyName(p.name))
31
+ .map((p) => p.name.getText(source).replace(/['"]/g, ''));
32
+ // Duplicate literal keys can produce invalid TypeScript; retain the original spread semantics.
33
+ if (new Set(names).size !== names.length)
34
+ return content;
35
+ const updated = ts.factory.updateObjectLiteralExpression(root, properties);
36
+ const printed = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }).printNode(ts.EmitHint.Expression, updated, source);
37
+ return content.slice(0, root.getStart(source)) + printed + content.slice(root.end);
38
+ }
@@ -0,0 +1,75 @@
1
+ import ts from 'typescript';
2
+ export function mergeAliasesInSvelteConfig(content, aliases) {
3
+ const source = ts.createSourceFile('svelte.config.js', content, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
4
+ function resolve(expression, seen = new Set()) {
5
+ if (ts.isObjectLiteralExpression(expression))
6
+ return expression;
7
+ if (ts.isParenthesizedExpression(expression) || ts.isAsExpression(expression) || ts.isSatisfiesExpression(expression))
8
+ return resolve(expression.expression, seen);
9
+ if (ts.isIdentifier(expression) && !seen.has(expression.text)) {
10
+ seen.add(expression.text);
11
+ for (const statement of source.statements)
12
+ if (ts.isVariableStatement(statement)) {
13
+ for (const declaration of statement.declarationList.declarations)
14
+ if (ts.isIdentifier(declaration.name) && declaration.name.text === expression.text && declaration.initializer)
15
+ return resolve(declaration.initializer, seen);
16
+ }
17
+ }
18
+ throw new Error('Cannot safely merge Svelte aliases: use an object literal or a local object variable for the config and kit.');
19
+ }
20
+ const exported = source.statements.find(ts.isExportAssignment);
21
+ if (!exported)
22
+ throw new Error('Cannot safely merge Svelte aliases: no default export found.');
23
+ const root = resolve(exported.expression);
24
+ const property = (object, name) => [...object.properties]
25
+ .reverse()
26
+ .find((entry) => entry.name && (ts.isIdentifier(entry.name) || ts.isStringLiteral(entry.name)) && entry.name.text === name);
27
+ const value = (entry) => {
28
+ if (ts.isPropertyAssignment(entry))
29
+ return entry.initializer;
30
+ if (ts.isShorthandPropertyAssignment(entry))
31
+ return entry.name;
32
+ throw new Error('Cannot safely merge Svelte aliases: unsupported property declaration.');
33
+ };
34
+ const insert = (object, text) => {
35
+ const last = object.properties.at(-1);
36
+ const comma = last && !object.properties.hasTrailingComma ? ',' : '';
37
+ // Insert the separator before any trailing line comment.
38
+ let next = content.slice(0, object.end - 1) + `\n${text}\n` + content.slice(object.end - 1);
39
+ if (last && comma)
40
+ next = next.slice(0, last.end) + comma + next.slice(last.end);
41
+ return next;
42
+ };
43
+ const entries = Object.entries(aliases)
44
+ .map(([key, target]) => `${JSON.stringify(key)}: ${JSON.stringify(target)}`)
45
+ .join(',\n');
46
+ const kit = property(root, 'kit');
47
+ if (!kit)
48
+ return insert(root, `kit: { alias: { ${entries} } }`);
49
+ const kitObject = resolve(value(kit));
50
+ const alias = property(kitObject, 'alias');
51
+ if (!alias)
52
+ return insert(kitObject, `alias: { ${entries} }`);
53
+ const expression = value(alias);
54
+ if (ts.isObjectLiteralExpression(expression)) {
55
+ const missing = Object.entries(aliases).filter(([key, target]) => {
56
+ const entry = property(expression, key);
57
+ if (!entry || !ts.isPropertyAssignment(entry) || !ts.isStringLiteral(entry.initializer) || entry.initializer.text !== target)
58
+ return true;
59
+ // Later spreads or computed keys can override an otherwise correct entry.
60
+ return expression.properties
61
+ .slice(expression.properties.indexOf(entry) + 1)
62
+ .some((later) => ts.isSpreadAssignment(later) || (later.name && ts.isComputedPropertyName(later.name)));
63
+ });
64
+ if (!missing.length)
65
+ return content;
66
+ if (missing.every(([key]) => !property(expression, key))) {
67
+ return insert(expression, missing.map(([key, target]) => `${JSON.stringify(key)}: ${JSON.stringify(target)}`).join(',\n'));
68
+ }
69
+ }
70
+ // Preserve every user expression, spread and comment; fixed architecture aliases win.
71
+ const replacement = `{ ...(${expression.getText(source)}), ${entries} }`;
72
+ if (ts.isShorthandPropertyAssignment(alias))
73
+ return content.slice(0, alias.getStart(source)) + `alias: ${replacement}` + content.slice(alias.end);
74
+ return content.slice(0, expression.getStart(source)) + replacement + content.slice(expression.end);
75
+ }
@@ -1,46 +1,82 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import fsSync from 'node:fs';
3
3
  import path from 'node:path';
4
- const DEFAULT_CONFIG = {
5
- contexts: [],
6
- defaultContext: 'web'
7
- };
8
- function toObjectFromDefaultExport(content) {
9
- const source = String(content ?? '').trim();
10
- if (!source.length) return {};
11
- const replacedExport = source.replace(/^\s*export\s+default\s+/m, 'return ');
12
- if (replacedExport === source) return {};
13
- const withSemicolon = /;\s*$/.test(replacedExport) ? replacedExport : `${replacedExport};`;
14
- try {
15
- return new Function(withSemicolon)() ?? {};
16
- } catch {
17
- return {};
18
- }
19
- }
4
+ import { createRequire } from 'node:module';
5
+ import ts from 'typescript';
6
+ import { flattenConfigLiterals } from './flattenConfig.js';
20
7
  export function resolveConfigFile(cwd = process.cwd()) {
21
- const tsPath = path.join(cwd, 'azure-net.config.ts');
22
- const jsPath = path.join(cwd, 'azure-net.config.js');
23
- if (fsSync.existsSync(tsPath)) {
24
- return { exists: true, filepath: tsPath, type: 'ts' };
25
- }
26
- if (fsSync.existsSync(jsPath)) {
27
- return { exists: true, filepath: jsPath, type: 'js' };
28
- }
29
- return { exists: false, filepath: tsPath, type: 'ts' };
8
+ for (const type of ['ts', 'js']) {
9
+ const filepath = path.join(cwd, `azure-net.config.${type}`);
10
+ if (fsSync.existsSync(filepath))
11
+ return { exists: true, filepath, type };
12
+ }
13
+ return { exists: false, filepath: path.join(cwd, 'azure-net.config.ts'), type: 'ts' };
14
+ }
15
+ export async function loadUserConfig(cwd = process.cwd()) {
16
+ const { exists, filepath } = resolveConfigFile(cwd);
17
+ if (!exists)
18
+ return {};
19
+ try {
20
+ const source = await fs.readFile(filepath, 'utf8');
21
+ const result = ts.transpileModule(source, {
22
+ fileName: filepath,
23
+ reportDiagnostics: true,
24
+ compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.CommonJS, esModuleInterop: true }
25
+ });
26
+ const errors = result.diagnostics?.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error) ?? [];
27
+ if (errors.length)
28
+ throw new Error(errors.map((error) => ts.flattenDiagnosticMessageText(error.messageText, '\n')).join('\n'));
29
+ const module = { exports: {} };
30
+ new Function('module', 'exports', 'require', '__filename', '__dirname', result.outputText)(module, module.exports, createRequire(filepath), filepath, path.dirname(filepath));
31
+ const config = module.exports.default;
32
+ if (!config || typeof config !== 'object' || Array.isArray(config))
33
+ throw new Error('Expected a default-exported configuration object.');
34
+ const parsed = config;
35
+ if (parsed.presentationWorkspaces !== undefined &&
36
+ (!Array.isArray(parsed.presentationWorkspaces) ||
37
+ parsed.presentationWorkspaces.some((name) => typeof name !== 'string' || !/^[A-Za-z][A-Za-z0-9 _-]*$/.test(name.trim()))))
38
+ throw new Error('presentationWorkspaces must be an array of valid workspace names.');
39
+ if (parsed.runChecksBeforePush !== undefined && typeof parsed.runChecksBeforePush !== 'boolean')
40
+ throw new Error('runChecksBeforePush must be a boolean.');
41
+ return parsed;
42
+ }
43
+ catch (error) {
44
+ throw new Error(`Unable to load ${filepath}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
45
+ }
30
46
  }
31
- export async function loadUserConfig() {
32
- const { exists, filepath } = resolveConfigFile();
33
- if (!exists) {
34
- return { ...DEFAULT_CONFIG };
35
- }
36
- try {
37
- const content = await fs.readFile(filepath, 'utf-8');
38
- const parsed = toObjectFromDefaultExport(content);
39
- if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
40
- return { ...DEFAULT_CONFIG };
41
- }
42
- return { ...DEFAULT_CONFIG, ...parsed };
43
- } catch {
44
- return { ...DEFAULT_CONFIG };
45
- }
47
+ /** Add the default without rewriting or dropping legacy/user configuration. */
48
+ export async function initializeConfigDefaults(cwd = process.cwd()) {
49
+ const existing = resolveConfigFile(cwd);
50
+ if (existing.exists) {
51
+ const original = await fs.readFile(existing.filepath, 'utf8');
52
+ const flattened = flattenConfigLiterals(original);
53
+ if (flattened !== original)
54
+ await fs.writeFile(existing.filepath, flattened);
55
+ }
56
+ const config = await loadUserConfig(cwd);
57
+ if (config.runChecksBeforePush !== undefined)
58
+ return;
59
+ const resolved = resolveConfigFile(cwd);
60
+ if (!resolved.exists) {
61
+ await fs.writeFile(resolved.filepath, 'export default {\n\trunChecksBeforePush: true\n};\n', { flag: 'wx' });
62
+ return;
63
+ }
64
+ const content = await fs.readFile(resolved.filepath, 'utf8');
65
+ const source = ts.createSourceFile(resolved.filepath, content, ts.ScriptTarget.Latest, true);
66
+ const exported = source.statements.find(ts.isExportAssignment);
67
+ if (!exported || exported.isExportEquals)
68
+ throw new Error(`Cannot initialize ${resolved.filepath}: expected a default export.`);
69
+ const expression = exported.expression;
70
+ let nextContent;
71
+ if (ts.isObjectLiteralExpression(expression)) {
72
+ const last = expression.properties.at(-1);
73
+ nextContent = content.slice(0, expression.end - 1) + '\n\trunChecksBeforePush: true\n' + content.slice(expression.end - 1);
74
+ if (last && !expression.properties.hasTrailingComma)
75
+ nextContent = nextContent.slice(0, last.end) + ',' + nextContent.slice(last.end);
76
+ }
77
+ else {
78
+ const replacement = `{ ...(${expression.getText(source)}), runChecksBeforePush: true }`;
79
+ nextContent = content.slice(0, expression.getStart(source)) + replacement + content.slice(expression.end);
80
+ }
81
+ await fs.writeFile(resolved.filepath, nextContent, 'utf8');
46
82
  }
@@ -0,0 +1,63 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { format } from 'prettier';
4
+ export const PACKAGE_IMPORTS = Object.fromEntries(['Contexts', 'Presentation', 'Platform'].flatMap((name) => {
5
+ const key = '#' + name.toLowerCase(), root = './src/app/' + name;
6
+ return [
7
+ [key, root + '/index.ts'],
8
+ [key + '/*', { types: [root + '/*.ts', root + '/*/index.ts', root + '/*'], default: root + '/*' }]
9
+ ];
10
+ }));
11
+ export async function mergePackageImports(content) {
12
+ const json = JSON.parse(content);
13
+ if (!json || typeof json !== 'object' || Array.isArray(json))
14
+ throw new Error('Expected a package.json object');
15
+ if (json.imports !== undefined && (!json.imports || typeof json.imports !== 'object' || Array.isArray(json.imports)))
16
+ throw new Error('Expected package.json imports object');
17
+ const imports = { ...json.imports };
18
+ for (const [key, value] of Object.entries(PACKAGE_IMPORTS)) {
19
+ if (key in imports && JSON.stringify(imports[key]) !== JSON.stringify(value))
20
+ throw new Error(`Conflicting package import ${key}; review its target before initialization.`);
21
+ imports[key] = value;
22
+ }
23
+ return format(JSON.stringify({ ...json, imports }), { parser: 'json', useTabs: true });
24
+ }
25
+ export async function initializePackageImports() {
26
+ const file = path.resolve('package.json');
27
+ let content;
28
+ try {
29
+ content = await fs.readFile(file, 'utf8');
30
+ }
31
+ catch (error) {
32
+ if (error.code !== 'ENOENT')
33
+ throw error;
34
+ content = '{}';
35
+ }
36
+ await fs.writeFile(file, await mergePackageImports(content));
37
+ }
38
+ export function resolvePackageImport(imports, specifier, root) {
39
+ const target = (v) => {
40
+ if (typeof v === 'string')
41
+ return v;
42
+ if (Array.isArray(v))
43
+ return v.map(target).find(Boolean);
44
+ if (v && typeof v === 'object') {
45
+ const obj = v;
46
+ return target(obj.default ?? obj.import ?? obj.types);
47
+ }
48
+ };
49
+ for (const key of Object.keys(imports).sort((a, b) => b.replace('*', '').length - a.replace('*', '').length)) {
50
+ const value = target(imports[key]);
51
+ if (!value?.startsWith('./'))
52
+ continue;
53
+ if (!key.includes('*')) {
54
+ if (key === specifier)
55
+ return path.resolve(root, value);
56
+ continue;
57
+ }
58
+ const [prefix, suffix = ''] = key.split('*');
59
+ if (specifier.startsWith(prefix) && specifier.endsWith(suffix))
60
+ return path.resolve(root, value.replace('*', specifier.slice(prefix.length, suffix ? -suffix.length : undefined)));
61
+ }
62
+ return null;
63
+ }
@@ -1,48 +1,42 @@
1
1
  import path from 'node:path';
2
- import { normalizeContexts } from '../init/initAliases.js';
3
- import { loadUserConfig, resolveConfigFile } from './loadConfig.js';
4
- export const SHARED_ESSENTIALS_DIR_NAME = 'essentials';
5
- const normalizeAlias = (value) => {
6
- const raw = String(value ?? '').trim();
7
- return raw.startsWith('$') ? raw : `$${raw}`;
2
+ import { discoverContexts, getContextPath, getPlatformPath, SHARED_CONTEXT } from './architecture.js';
3
+ import { resolveConfigFile } from './loadConfig.js';
4
+ export const SHARED_ESSENTIALS_DIR_NAME = 'Platform';
5
+ const constructNames = {
6
+ datasource: 'Datasource',
7
+ presenter: 'Presenter',
8
+ provider: 'DI',
9
+ response: 'Response',
10
+ schema: 'Schema'
8
11
  };
9
- const createMissingSharedAliasError = () =>
10
- new Error(
11
- '`sharedAlias` is missing in azure-net.config.ts/js. Add sharedAlias and make sure it points to one of `contexts`, for example: sharedAlias: "$shared-kernel".'
12
- );
13
- export const getSharedState = async () => {
14
- const config = await loadUserConfig();
15
- const contexts = normalizeContexts(config.contexts);
16
- const sharedAliasRaw = String(config.sharedAlias ?? '').trim();
17
- if (!sharedAliasRaw.length) throw createMissingSharedAliasError();
18
- const sharedAlias = normalizeAlias(sharedAliasRaw);
19
- const sharedContext = contexts.find((context) => normalizeAlias(context.alias) === sharedAlias);
20
- if (!sharedContext) {
21
- throw new Error(
22
- `sharedAlias "${sharedAlias}" does not point to any configured context. Add a context with alias "${sharedAlias}" in azure-net.config.ts/js.`
23
- );
24
- }
25
- return {
26
- contexts,
27
- sharedAlias,
28
- sharedContext
29
- };
12
+ export async function getSharedState() {
13
+ const names = await discoverContexts();
14
+ if (!names.includes(SHARED_CONTEXT))
15
+ names.push(SHARED_CONTEXT);
16
+ const contexts = names.sort().map((name) => ({ name, alias: `#contexts/${name}` }));
17
+ return { contexts, sharedAlias: '#platform', sharedContext: contexts.find((context) => context.name === SHARED_CONTEXT) };
18
+ }
19
+ export const hasSharedAliasConfig = async () => true;
20
+ export const getSharedContextRootPath = (name = SHARED_CONTEXT) => getContextPath(name);
21
+ export const getSharedEssentialsPath = (...compatibility) => {
22
+ void compatibility;
23
+ return getPlatformPath();
30
24
  };
31
- export const hasSharedAliasConfig = async () => {
32
- const config = await loadUserConfig();
33
- return String(config.sharedAlias ?? '').trim().length > 0;
25
+ export const getFoundationRootPath = (...compatibility) => {
26
+ void compatibility;
27
+ return path.join(getPlatformPath(), 'Foundation');
28
+ };
29
+ export const getFoundationConstructPath = (name, construct) => path.join(getFoundationRootPath(name), constructNames[construct]);
30
+ export const getFoundationConstructImportPath = (_alias, construct) => `#platform/Foundation/${constructNames[construct]}`;
31
+ export const getLocalizationPath = (...compatibility) => {
32
+ void compatibility;
33
+ return path.join(getPlatformPath(), 'Bootstrap', 'Localization');
34
+ };
35
+ export const getLocalizationImportPath = (...compatibility) => {
36
+ void compatibility;
37
+ return '#platform/Bootstrap/Localization';
34
38
  };
35
- export const getSharedContextRootPath = (sharedContextName) => path.join(process.cwd(), 'src', 'app', sharedContextName);
36
- export const getSharedEssentialsPath = (sharedContextName) =>
37
- path.join(getSharedContextRootPath(sharedContextName), SHARED_ESSENTIALS_DIR_NAME);
38
- export const getFoundationRootPath = (sharedContextName) =>
39
- path.join(getSharedEssentialsPath(sharedContextName), 'foundation', 'constructs');
40
- export const getFoundationConstructPath = (sharedContextName, construct) => path.join(getFoundationRootPath(sharedContextName), construct);
41
- export const getFoundationConstructImportPath = (sharedAlias, construct) =>
42
- `${sharedAlias}/${SHARED_ESSENTIALS_DIR_NAME}/foundation/constructs/${construct}`;
43
- export const getLocalizationPath = (sharedContextName) => path.join(getSharedEssentialsPath(sharedContextName), 'localization');
44
- export const getLocalizationImportPath = (sharedAlias) => `${sharedAlias}/${SHARED_ESSENTIALS_DIR_NAME}/localization`;
45
39
  export const getConfigFileLabel = () => {
46
- const config = resolveConfigFile();
47
- return config.exists ? path.basename(config.filepath) : 'azure-net.config.ts/js';
40
+ const config = resolveConfigFile();
41
+ return config.exists ? path.basename(config.filepath) : 'azure-net.config.ts/js';
48
42
  };