@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
@@ -2,216 +2,207 @@ import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import prompts from 'prompts';
4
4
  import { loadUserConfig } from '../../utils/loadConfig.js';
5
- import { getSharedContextRootPath, getSharedState } from '../../utils/sharedFoundation.js';
6
5
  import { toCamelCase } from '../../utils/contextUtils.js';
7
- const ROUTES_DIR = path.join(process.cwd(), 'src', 'routes');
6
+ const getRoutesDir = () => path.join(process.cwd(), 'src', 'routes');
8
7
  const ROUTE_FILE_PATTERN = /^\+(page|server)(?:\.server)?\.(?:svelte|ts|js)$/;
9
8
  const PAGE_FILE_PATTERN = /^\+page(?:\.server)?\.(?:svelte|ts|js)$/;
10
9
  const SERVER_FILE_PATTERN = /^\+server\.(?:ts|js)$/;
11
10
  const isRouteGroup = (segment) => /^\(.+\)$/.test(segment);
12
11
  const getRouteGroupName = (segment) => segment.slice(1, -1).trim();
13
12
  const extractParamName = (rawParam) => {
14
- const withoutRest = rawParam.startsWith('...') ? rawParam.slice(3) : rawParam;
15
- const matcherIndex = withoutRest.indexOf('=');
16
- return matcherIndex === -1 ? withoutRest : withoutRest.slice(0, matcherIndex);
13
+ const withoutRest = rawParam.startsWith('...') ? rawParam.slice(3) : rawParam;
14
+ const matcherIndex = withoutRest.indexOf('=');
15
+ return matcherIndex === -1 ? withoutRest : withoutRest.slice(0, matcherIndex);
17
16
  };
18
17
  const convertDynamicSegments = (segment) => {
19
- const optionalMatch = segment.match(/^\[\[(.+)\]\]$/);
20
- if (optionalMatch?.[1]) {
21
- const paramName = extractParamName(optionalMatch[1]);
22
- return { variants: ['', `{${paramName}}`], params: [paramName] };
23
- }
24
- const params = [];
25
- const converted = segment.replace(/\[(.+?)\]/g, (_match, rawParam) => {
26
- const paramName = extractParamName(rawParam);
27
- if (paramName.length) params.push(paramName);
28
- return `{${paramName}}`;
29
- });
30
- return { variants: [converted], params };
18
+ const optionalMatch = segment.match(/^\[\[(.+)\]\]$/);
19
+ if (optionalMatch?.[1]) {
20
+ const paramName = extractParamName(optionalMatch[1]);
21
+ return { variants: ['', `{${paramName}}`], params: [paramName] };
22
+ }
23
+ const params = [];
24
+ const converted = segment.replace(/\[(.+?)\]/g, (_match, rawParam) => {
25
+ const paramName = extractParamName(rawParam);
26
+ if (paramName.length)
27
+ params.push(paramName);
28
+ return `{${paramName}}`;
29
+ });
30
+ return { variants: [converted], params };
31
31
  };
32
32
  const normalizeUrl = (segments) => {
33
- const filtered = segments.filter(Boolean);
34
- return filtered.length ? `/${filtered.join('/')}` : '/';
33
+ const filtered = segments.filter(Boolean);
34
+ return filtered.length ? `/${filtered.join('/')}` : '/';
35
35
  };
36
36
  const createRouteVariants = (segments) => {
37
- let variants = [[]];
38
- const dynamicParams = new Set();
39
- for (const segment of segments) {
40
- if (isRouteGroup(segment)) continue;
41
- const converted = convertDynamicSegments(segment);
42
- for (const param of converted.params) {
43
- dynamicParams.add(param);
44
- }
45
- const nextVariants = [];
46
- for (const variant of variants) {
47
- for (const nextSegment of converted.variants) {
48
- nextVariants.push(nextSegment ? [...variant, nextSegment] : [...variant]);
49
- }
50
- }
51
- variants = nextVariants;
52
- }
53
- return {
54
- urls: [...new Set(variants.map(normalizeUrl))],
55
- dynamicParams: [...dynamicParams]
56
- };
37
+ let variants = [[]];
38
+ const dynamicParams = new Set();
39
+ for (const segment of segments) {
40
+ if (isRouteGroup(segment))
41
+ continue;
42
+ const converted = convertDynamicSegments(segment);
43
+ for (const param of converted.params) {
44
+ dynamicParams.add(param);
45
+ }
46
+ const nextVariants = [];
47
+ for (const variant of variants) {
48
+ for (const nextSegment of converted.variants) {
49
+ nextVariants.push(nextSegment ? [...variant, nextSegment] : [...variant]);
50
+ }
51
+ }
52
+ variants = nextVariants;
53
+ }
54
+ return {
55
+ urls: [...new Set(variants.map(normalizeUrl))],
56
+ dynamicParams: [...dynamicParams]
57
+ };
57
58
  };
58
59
  const hasRouteFile = (files) => files.some((file) => ROUTE_FILE_PATTERN.test(file));
59
60
  const hasPageFile = (files) => files.some((file) => PAGE_FILE_PATTERN.test(file));
60
61
  const hasServerFile = (files) => files.some((file) => SERVER_FILE_PATTERN.test(file));
61
62
  const readDirSafe = async (dir) => {
62
- try {
63
- return await fs.readdir(dir, { withFileTypes: true });
64
- } catch {
65
- return [];
66
- }
63
+ try {
64
+ return await fs.readdir(dir, { withFileTypes: true });
65
+ }
66
+ catch {
67
+ return [];
68
+ }
67
69
  };
68
70
  const collectRoutes = async (dir, segments = [], groupStack = [], rootGroup) => {
69
- const entries = (await readDirSafe(dir)).sort((a, b) => a.name.localeCompare(b.name));
70
- const files = entries.filter((entry) => entry.isFile()).map((entry) => entry.name);
71
- const dirs = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'));
72
- const routes = [];
73
- const routeVariants = createRouteVariants(segments);
74
- if (hasRouteFile(files)) {
75
- for (const url of routeVariants.urls) {
76
- routes.push({
77
- url,
78
- routeDir: dir,
79
- relativeDir: path.relative(ROUTES_DIR, dir) || '.',
80
- segments,
81
- dynamicParams: routeVariants.dynamicParams,
82
- rootGroup,
83
- groupStack,
84
- depth: segments.length,
85
- hasChildren: dirs.length > 0,
86
- hasPage: hasPageFile(files),
87
- hasServer: hasServerFile(files)
88
- });
89
- }
90
- }
91
- for (const child of dirs) {
92
- const childGroupName = isRouteGroup(child.name) ? getRouteGroupName(child.name) : undefined;
93
- const nextGroupStack = childGroupName ? [...groupStack, childGroupName] : groupStack;
94
- const nextRootGroup = rootGroup ?? (segments.length === 0 ? childGroupName : undefined);
95
- const childRoutes = await collectRoutes(path.join(dir, child.name), [...segments, child.name], nextGroupStack, nextRootGroup);
96
- routes.push(...childRoutes);
97
- }
98
- return routes;
71
+ const entries = (await readDirSafe(dir)).sort((a, b) => a.name.localeCompare(b.name));
72
+ const files = entries.filter((entry) => entry.isFile()).map((entry) => entry.name);
73
+ const dirs = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'));
74
+ const routes = [];
75
+ const routeVariants = createRouteVariants(segments);
76
+ if (hasRouteFile(files)) {
77
+ for (const url of routeVariants.urls) {
78
+ routes.push({
79
+ url,
80
+ routeDir: dir,
81
+ relativeDir: path.relative(getRoutesDir(), dir) || '.',
82
+ segments,
83
+ dynamicParams: routeVariants.dynamicParams,
84
+ rootGroup,
85
+ groupStack,
86
+ depth: segments.length,
87
+ hasChildren: dirs.length > 0,
88
+ hasPage: hasPageFile(files),
89
+ hasServer: hasServerFile(files)
90
+ });
91
+ }
92
+ }
93
+ for (const child of dirs) {
94
+ const childGroupName = isRouteGroup(child.name) ? getRouteGroupName(child.name) : undefined;
95
+ const nextGroupStack = childGroupName ? [...groupStack, childGroupName] : groupStack;
96
+ const nextRootGroup = rootGroup ?? (segments.length === 0 ? childGroupName : undefined);
97
+ const childRoutes = await collectRoutes(path.join(dir, child.name), [...segments, child.name], nextGroupStack, nextRootGroup);
98
+ routes.push(...childRoutes);
99
+ }
100
+ return routes;
99
101
  };
100
102
  const sanitizeGroupName = (value) => {
101
- const trimmed = value.trim();
102
- return trimmed.length ? trimmed : 'routes';
103
+ const trimmed = value.trim();
104
+ return trimmed.length ? trimmed : 'routes';
103
105
  };
104
106
  const toRouteVariableName = (groupName) => {
105
- const base = toCamelCase(sanitizeGroupName(groupName).replace(/[^\p{L}\p{N}_-]+/gu, '-'));
106
- return `${base || 'routes'}Routes`;
107
+ const base = toCamelCase(sanitizeGroupName(groupName).replace(/[^\p{L}\p{N}_-]+/gu, '-'));
108
+ return `${base || 'routes'}Routes`;
107
109
  };
108
110
  const ensureUniqueVariableName = (name, used) => {
109
- if (!used.has(name)) {
110
- used.add(name);
111
- return name;
112
- }
113
- let index = 2;
114
- let nextName = `${name}${index}`;
115
- while (used.has(nextName)) {
116
- index += 1;
117
- nextName = `${name}${index}`;
118
- }
119
- used.add(nextName);
120
- return nextName;
111
+ if (!used.has(name)) {
112
+ used.add(name);
113
+ return name;
114
+ }
115
+ let index = 2;
116
+ let nextName = `${name}${index}`;
117
+ while (used.has(nextName)) {
118
+ index += 1;
119
+ nextName = `${name}${index}`;
120
+ }
121
+ used.add(nextName);
122
+ return nextName;
121
123
  };
122
124
  const createGroupMap = (routes, mode, resolver) => {
123
- const groups = new Map();
124
- for (const route of routes) {
125
- const groupName =
126
- mode === 'none'
127
- ? 'routes'
128
- : mode === 'root-groups'
129
- ? (route.rootGroup ?? 'routes')
130
- : (sanitizeGroupName(String(resolver?.(route) ?? 'routes')) ?? 'routes');
131
- const list = groups.get(groupName) ?? [];
132
- list.push(route);
133
- groups.set(groupName, list);
134
- }
135
- return groups;
125
+ const groups = new Map();
126
+ for (const route of routes) {
127
+ const groupName = mode === 'none'
128
+ ? 'routes'
129
+ : mode === 'root-groups'
130
+ ? (route.rootGroup ?? 'routes')
131
+ : (sanitizeGroupName(String(resolver?.(route) ?? 'routes')) ?? 'routes');
132
+ const list = groups.get(groupName) ?? [];
133
+ list.push(route);
134
+ groups.set(groupName, list);
135
+ }
136
+ return groups;
136
137
  };
137
138
  const createStringArray = (items, indent = '\t') => {
138
- if (!items.length) return '[]';
139
- return `[\n${items.map((item) => `${indent}'${item}'`).join(',\n')}\n]`;
139
+ if (!items.length)
140
+ return '[]';
141
+ return `[\n${items.map((item) => `${indent}'${item}'`).join(',\n')}\n]`;
140
142
  };
141
143
  const createGeneratedFile = (groups) => {
142
- const usedVariables = new Set();
143
- const groupEntries = [...groups.entries()].map(([groupName, routes]) => ({
144
- groupName,
145
- variableName: ensureUniqueVariableName(
146
- groupName === 'routes' ? (groups.size === 1 ? 'routes' : 'ungroupedRoutes') : toRouteVariableName(groupName),
147
- usedVariables
148
- ),
149
- routes: [...new Set(routes.map((route) => route.url))].sort((a, b) => a.localeCompare(b))
150
- }));
151
- const lines = ['// This file is generated by `azure-net generate routes`.', '// Do not edit it manually.', ''];
152
- for (const group of groupEntries) {
153
- lines.push(`export const ${group.variableName} = ${createStringArray(group.routes)} as const;`);
154
- lines.push('');
155
- }
156
- if (groupEntries.length !== 1 || groupEntries[0]?.variableName !== 'routes') {
157
- lines.push(`export const routes = [${groupEntries.map((group) => `...${group.variableName}`).join(', ')}] as const;`);
158
- lines.push('');
159
- }
160
- lines.push('export const routeGroups = {');
161
- lines.push(
162
- ...groupEntries.map((group, index) => `\t'${group.groupName}': ${group.variableName}${index === groupEntries.length - 1 ? '' : ','}`)
163
- );
164
- lines.push('} as const;');
165
- lines.push('');
166
- lines.push('export type Route = (typeof routes)[number];');
167
- lines.push('export type RouteGroupName = keyof typeof routeGroups;');
168
- lines.push('');
169
- return `${lines.join('\n')}\n`;
144
+ const usedVariables = new Set();
145
+ const groupEntries = [...groups.entries()].map(([groupName, routes]) => ({
146
+ groupName,
147
+ variableName: ensureUniqueVariableName(groupName === 'routes' ? (groups.size === 1 ? 'routes' : 'ungroupedRoutes') : toRouteVariableName(groupName), usedVariables),
148
+ routes: [...new Set(routes.map((route) => route.url))].sort((a, b) => a.localeCompare(b))
149
+ }));
150
+ const lines = ['// This file is generated by `azure-net generate routes`.', '// Do not edit it manually.', ''];
151
+ for (const group of groupEntries) {
152
+ lines.push(`export const ${group.variableName} = ${createStringArray(group.routes)} as const;`);
153
+ lines.push('');
154
+ }
155
+ if (groupEntries.length !== 1 || groupEntries[0]?.variableName !== 'routes') {
156
+ lines.push(`export const routes = [${groupEntries.map((group) => `...${group.variableName}`).join(', ')}] as const;`);
157
+ lines.push('');
158
+ }
159
+ lines.push('export type Route = (typeof routes)[number];');
160
+ lines.push('');
161
+ return `${lines.join('\n')}\n`;
170
162
  };
171
163
  const selectGroupingMode = async () => {
172
- const { mode } = await prompts({
173
- type: 'select',
174
- name: 'mode',
175
- message: 'How should routes be grouped?',
176
- choices: [
177
- { title: 'By root route groups: (account), (landing), ...', value: 'root-groups' },
178
- { title: 'By azure-net.config.ts groupRoutesFunc', value: 'config-function' },
179
- { title: 'Do not group, generate one routes array', value: 'none' }
180
- ]
181
- });
182
- return mode ? mode : null;
164
+ const { mode } = await prompts({
165
+ type: 'select',
166
+ name: 'mode',
167
+ message: 'How should routes be grouped?',
168
+ choices: [
169
+ { title: 'By root route groups: (account), (landing), ...', value: 'root-groups' },
170
+ { title: 'By azure-net.config.ts groupRoutesFunc', value: 'config-function' },
171
+ { title: 'Do not group, generate one routes array', value: 'none' }
172
+ ]
173
+ });
174
+ return mode ? mode : null;
183
175
  };
184
176
  const getConfigRouteGroupResolver = async () => {
185
- const config = await loadUserConfig();
186
- if (typeof config.groupRoutesFunc !== 'function') {
187
- console.error('❌ `groupRoutesFunc` is missing in azure-net.config.ts/js or is not a function.');
188
- console.error('Example:');
189
- console.error('export default {');
190
- console.error("\tgroupRoutesFunc: (route) => route.rootGroup ?? 'app'");
191
- console.error('};');
192
- return null;
193
- }
194
- return config.groupRoutesFunc;
177
+ const config = await loadUserConfig();
178
+ if (typeof config.groupRoutesFunc !== 'function') {
179
+ console.error('❌ `groupRoutesFunc` is missing in azure-net.config.ts/js or is not a function.');
180
+ console.error('Example:');
181
+ console.error('export default {');
182
+ console.error("\tgroupRoutesFunc: (route) => route.rootGroup ?? 'app'");
183
+ console.error('};');
184
+ return null;
185
+ }
186
+ return config.groupRoutesFunc;
195
187
  };
196
188
  export default async function generateRoutes() {
197
- const mode = await selectGroupingMode();
198
- if (!mode) return;
199
- const { sharedContext } = await getSharedState();
200
- const resolver = mode === 'config-function' ? await getConfigRouteGroupResolver() : undefined;
201
- if (mode === 'config-function' && !resolver) {
202
- process.exitCode = 1;
203
- return;
204
- }
205
- const routes = await collectRoutes(ROUTES_DIR);
206
- if (!routes.length) {
207
- console.warn('⚠️ No SvelteKit routes found in src/routes');
208
- return;
209
- }
210
- const groups = createGroupMap(routes, mode, resolver ?? undefined);
211
- const outputDir = path.join(getSharedContextRootPath(sharedContext.name), 'runtime', 'routes');
212
- const outputFile = path.join(outputDir, 'index.ts');
213
- await fs.mkdir(outputDir, { recursive: true });
214
- await fs.writeFile(outputFile, createGeneratedFile(groups), 'utf-8');
215
- console.log(`✅ Routes generated: ${outputFile}`);
189
+ const mode = await selectGroupingMode();
190
+ if (!mode)
191
+ return;
192
+ const resolver = mode === 'config-function' ? await getConfigRouteGroupResolver() : undefined;
193
+ if (mode === 'config-function' && !resolver) {
194
+ process.exitCode = 1;
195
+ return;
196
+ }
197
+ const routes = await collectRoutes(getRoutesDir());
198
+ if (!routes.length) {
199
+ console.warn('⚠️ No SvelteKit routes found in src/routes');
200
+ return;
201
+ }
202
+ const groups = createGroupMap(routes, mode, resolver ?? undefined);
203
+ const outputDir = path.join(process.cwd(), 'src', 'app', 'Platform', 'Bootstrap', 'Routes');
204
+ const outputFile = path.join(outputDir, 'index.ts');
205
+ await fs.mkdir(outputDir, { recursive: true });
206
+ await fs.writeFile(outputFile, createGeneratedFile(groups), 'utf-8');
207
+ console.log(`✅ Routes generated: ${outputFile}`);
216
208
  }
217
- //# sourceMappingURL=generateRoutes.js.map
@@ -2,81 +2,61 @@ import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import prompts from 'prompts';
4
4
  import { toPascalCase } from '../../utils/contextUtils.js';
5
- import { normalizeContexts } from '../../init/initAliases.js';
6
- import { loadUserConfig } from '../../utils/loadConfig.js';
5
+ import { selectWorkspace } from '../../utils/architecture.js';
7
6
  import { writeIfNotExists } from '../../utils/fileUtils.js';
8
7
  const createComponentContent = (propsName) => `<script lang="ts">
9
- import type { ${propsName} } from './types';
8
+ import type { ${propsName} } from './Types';
10
9
  const {}: ${propsName} = $props();
11
10
  </script>
12
11
  <!--Your HTML here-->
13
12
  <style lang="scss">
14
- \t@use './style';
13
+ \t@use './Style';
15
14
  </style>
16
15
  `;
17
16
  const createTypesContent = (propsName) => `export interface ${propsName} {}
18
17
  `;
19
18
  const createIndexContent = (name) => `export { default as ${name} } from './Component.svelte';
20
19
  `;
21
- const printContextsError = () => {
22
- console.error('❌ Cannot generate UI artifact: `contexts` is missing or empty in azure-net.config.ts/js');
23
- };
24
- const selectContext = async () => {
25
- const config = await loadUserConfig();
26
- const contexts = normalizeContexts(config.contexts);
27
- if (!contexts.length) return null;
28
- const { context } = await prompts({
29
- type: 'select',
30
- name: 'context',
31
- message: 'Select context:',
32
- choices: contexts.map((item) => ({ title: item.name, value: item.name })),
33
- initial: 0
34
- });
35
- return context ? String(context) : null;
36
- };
37
20
  export default async function generateComponent() {
38
- const context = await selectContext();
39
- if (!context) {
40
- printContextsError();
41
- process.exitCode = 1;
42
- return;
43
- }
44
- const { rawName } = await prompts({
45
- type: 'text',
46
- name: 'rawName',
47
- message: 'Component name:',
48
- validate: (value) => (String(value).trim().length > 0 ? true : 'Name is required')
49
- });
50
- const { componentKind } = await prompts({
51
- type: 'select',
52
- name: 'componentKind',
53
- message: 'Component kind:',
54
- choices: [
55
- { title: 'shared', value: 'shared' },
56
- { title: 'layout', value: 'layout' },
57
- { title: 'page', value: 'page' }
58
- ],
59
- initial: 0
60
- });
61
- const name = toPascalCase(String(rawName ?? 'Component')) || 'Component';
62
- const propsName = `IComponent${name}Props`;
63
- const kind = componentKind ?? 'shared';
64
- let targetDir = path.join(process.cwd(), 'src', 'app', context, 'ui', 'components', kind);
65
- if (kind === 'page') {
66
- const { pageFolderRaw } = await prompts({
67
- type: 'text',
68
- name: 'pageFolderRaw',
69
- message: 'Page folder name:',
70
- validate: (value) => (String(value).trim().length > 0 ? true : 'Page folder name is required')
71
- });
72
- const pageFolder = String(pageFolderRaw ?? '').trim();
73
- targetDir = path.join(targetDir, pageFolder);
74
- }
75
- targetDir = path.join(targetDir, name);
76
- await fs.mkdir(targetDir, { recursive: true });
77
- await writeIfNotExists(path.join(targetDir, 'Component.svelte'), createComponentContent(propsName));
78
- await writeIfNotExists(path.join(targetDir, 'style.scss'), '');
79
- await writeIfNotExists(path.join(targetDir, 'types.ts'), createTypesContent(propsName));
80
- await writeIfNotExists(path.join(targetDir, 'index.ts'), createIndexContent(name));
81
- console.log(`✅ Component generated: ${targetDir}`);
21
+ const workspace = await selectWorkspace();
22
+ if (!workspace)
23
+ return;
24
+ const { rawName } = await prompts({
25
+ type: 'text',
26
+ name: 'rawName',
27
+ message: 'Component name:',
28
+ validate: (value) => (String(value).trim().length > 0 ? true : 'Name is required')
29
+ });
30
+ const { componentKind } = await prompts({
31
+ type: 'select',
32
+ name: 'componentKind',
33
+ message: 'Component kind:',
34
+ choices: [
35
+ { title: 'shared', value: 'shared' },
36
+ { title: 'layout', value: 'layout' },
37
+ { title: 'page', value: 'page' }
38
+ ],
39
+ initial: 0
40
+ });
41
+ const name = toPascalCase(String(rawName ?? 'Component')) || 'Component';
42
+ const propsName = `IComponent${name}Props`;
43
+ const kind = componentKind ?? 'shared';
44
+ let targetDir = path.join(workspace.path, 'Ui', 'Components', toPascalCase(kind));
45
+ if (kind === 'page') {
46
+ const { pageFolderRaw } = await prompts({
47
+ type: 'text',
48
+ name: 'pageFolderRaw',
49
+ message: 'Page folder name:',
50
+ validate: (value) => (String(value).trim().length > 0 ? true : 'Page folder name is required')
51
+ });
52
+ const pageFolder = toPascalCase(String(pageFolderRaw ?? 'Page')) || 'Page';
53
+ targetDir = path.join(targetDir, pageFolder);
54
+ }
55
+ targetDir = path.join(targetDir, name);
56
+ await fs.mkdir(targetDir, { recursive: true });
57
+ await writeIfNotExists(path.join(targetDir, 'Component.svelte'), createComponentContent(propsName));
58
+ await writeIfNotExists(path.join(targetDir, 'Style.scss'), '');
59
+ await writeIfNotExists(path.join(targetDir, 'Types.ts'), createTypesContent(propsName));
60
+ await writeIfNotExists(path.join(targetDir, 'index.ts'), createIndexContent(name));
61
+ console.log(`✅ Component generated: ${targetDir}`);
82
62
  }
@@ -2,58 +2,38 @@ import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import prompts from 'prompts';
4
4
  import { toPascalCase } from '../../utils/contextUtils.js';
5
- import { normalizeContexts } from '../../init/initAliases.js';
6
- import { loadUserConfig } from '../../utils/loadConfig.js';
5
+ import { selectWorkspace } from '../../utils/architecture.js';
7
6
  import { writeIfNotExists } from '../../utils/fileUtils.js';
8
7
  const createComponentContent = (propsName) => `<script lang="ts">
9
- import type { ${propsName} } from './types';
8
+ import type { ${propsName} } from './Types';
10
9
  const {}: ${propsName} = $props();
11
10
  </script>
12
11
  <!--Your HTML here-->
13
12
  <style lang="scss">
14
- \t@use './style';
13
+ \t@use './Style';
15
14
  </style>
16
15
  `;
17
16
  const createTypesContent = (propsName) => `export interface ${propsName} {}
18
17
  `;
19
18
  const createIndexContent = (name) => `export { default as ${name} } from './Component.svelte';
20
19
  `;
21
- const printContextsError = () => {
22
- console.error('❌ Cannot generate UI artifact: `contexts` is missing or empty in azure-net.config.ts/js');
23
- };
24
- const selectContext = async () => {
25
- const config = await loadUserConfig();
26
- const contexts = normalizeContexts(config.contexts);
27
- if (!contexts.length) return null;
28
- const { context } = await prompts({
29
- type: 'select',
30
- name: 'context',
31
- message: 'Select context:',
32
- choices: contexts.map((item) => ({ title: item.name, value: item.name })),
33
- initial: 0
34
- });
35
- return context ? String(context) : null;
36
- };
37
20
  export default async function generateDesignComponent() {
38
- const context = await selectContext();
39
- if (!context) {
40
- printContextsError();
41
- process.exitCode = 1;
42
- return;
43
- }
44
- const { rawName } = await prompts({
45
- type: 'text',
46
- name: 'rawName',
47
- message: 'Design component name:',
48
- validate: (value) => (String(value).trim().length > 0 ? true : 'Name is required')
49
- });
50
- const name = toPascalCase(String(rawName ?? 'DesignComponent')) || 'DesignComponent';
51
- const propsName = `IDesignComponent${name}Props`;
52
- const targetDir = path.join(process.cwd(), 'src', 'app', context, 'ui', 'design', name);
53
- await fs.mkdir(targetDir, { recursive: true });
54
- await writeIfNotExists(path.join(targetDir, 'Component.svelte'), createComponentContent(propsName));
55
- await writeIfNotExists(path.join(targetDir, 'style.scss'), '');
56
- await writeIfNotExists(path.join(targetDir, 'types.ts'), createTypesContent(propsName));
57
- await writeIfNotExists(path.join(targetDir, 'index.ts'), createIndexContent(name));
58
- console.log(`✅ Design component generated: ${targetDir}`);
21
+ const workspace = await selectWorkspace();
22
+ if (!workspace)
23
+ return;
24
+ const { rawName } = await prompts({
25
+ type: 'text',
26
+ name: 'rawName',
27
+ message: 'Design component name:',
28
+ validate: (value) => (String(value).trim().length > 0 ? true : 'Name is required')
29
+ });
30
+ const name = toPascalCase(String(rawName ?? 'DesignComponent')) || 'DesignComponent';
31
+ const propsName = `IDesignComponent${name}Props`;
32
+ const targetDir = path.join(workspace.path, 'Ui', 'Design', name);
33
+ await fs.mkdir(targetDir, { recursive: true });
34
+ await writeIfNotExists(path.join(targetDir, 'Component.svelte'), createComponentContent(propsName));
35
+ await writeIfNotExists(path.join(targetDir, 'Style.scss'), '');
36
+ await writeIfNotExists(path.join(targetDir, 'Types.ts'), createTypesContent(propsName));
37
+ await writeIfNotExists(path.join(targetDir, 'index.ts'), createIndexContent(name));
38
+ console.log(`✅ Design component generated: ${targetDir}`);
59
39
  }