@azure-net/cli 5.1.0 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-net/cli",
3
- "version": "5.1.0",
3
+ "version": "5.1.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "azure-net": "bin/azure-net.js"
@@ -11,207 +11,201 @@ const SERVER_FILE_PATTERN = /^\+server\.(?:ts|js)$/;
11
11
  const isRouteGroup = (segment) => /^\(.+\)$/.test(segment);
12
12
  const getRouteGroupName = (segment) => segment.slice(1, -1).trim();
13
13
  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);
14
+ const withoutRest = rawParam.startsWith('...') ? rawParam.slice(3) : rawParam;
15
+ const matcherIndex = withoutRest.indexOf('=');
16
+ return matcherIndex === -1 ? withoutRest : withoutRest.slice(0, matcherIndex);
17
17
  };
18
18
  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 };
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)
28
+ params.push(paramName);
29
+ return `{${paramName}}`;
30
+ });
31
+ return { variants: [converted], params };
31
32
  };
32
33
  const normalizeUrl = (segments) => {
33
- const filtered = segments.filter(Boolean);
34
- return filtered.length ? `/${filtered.join('/')}` : '/';
34
+ const filtered = segments.filter(Boolean);
35
+ return filtered.length ? `/${filtered.join('/')}` : '/';
35
36
  };
36
37
  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
- };
38
+ let variants = [[]];
39
+ const dynamicParams = new Set();
40
+ for (const segment of segments) {
41
+ if (isRouteGroup(segment))
42
+ continue;
43
+ const converted = convertDynamicSegments(segment);
44
+ for (const param of converted.params) {
45
+ dynamicParams.add(param);
46
+ }
47
+ const nextVariants = [];
48
+ for (const variant of variants) {
49
+ for (const nextSegment of converted.variants) {
50
+ nextVariants.push(nextSegment ? [...variant, nextSegment] : [...variant]);
51
+ }
52
+ }
53
+ variants = nextVariants;
54
+ }
55
+ return {
56
+ urls: [...new Set(variants.map(normalizeUrl))],
57
+ dynamicParams: [...dynamicParams]
58
+ };
57
59
  };
58
60
  const hasRouteFile = (files) => files.some((file) => ROUTE_FILE_PATTERN.test(file));
59
61
  const hasPageFile = (files) => files.some((file) => PAGE_FILE_PATTERN.test(file));
60
62
  const hasServerFile = (files) => files.some((file) => SERVER_FILE_PATTERN.test(file));
61
63
  const readDirSafe = async (dir) => {
62
- try {
63
- return await fs.readdir(dir, { withFileTypes: true });
64
- } catch {
65
- return [];
66
- }
64
+ try {
65
+ return await fs.readdir(dir, { withFileTypes: true });
66
+ }
67
+ catch {
68
+ return [];
69
+ }
67
70
  };
68
71
  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;
72
+ const entries = (await readDirSafe(dir)).sort((a, b) => a.name.localeCompare(b.name));
73
+ const files = entries.filter((entry) => entry.isFile()).map((entry) => entry.name);
74
+ const dirs = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'));
75
+ const routes = [];
76
+ const routeVariants = createRouteVariants(segments);
77
+ if (hasRouteFile(files)) {
78
+ for (const url of routeVariants.urls) {
79
+ routes.push({
80
+ url,
81
+ routeDir: dir,
82
+ relativeDir: path.relative(ROUTES_DIR, dir) || '.',
83
+ segments,
84
+ dynamicParams: routeVariants.dynamicParams,
85
+ rootGroup,
86
+ groupStack,
87
+ depth: segments.length,
88
+ hasChildren: dirs.length > 0,
89
+ hasPage: hasPageFile(files),
90
+ hasServer: hasServerFile(files)
91
+ });
92
+ }
93
+ }
94
+ for (const child of dirs) {
95
+ const childGroupName = isRouteGroup(child.name) ? getRouteGroupName(child.name) : undefined;
96
+ const nextGroupStack = childGroupName ? [...groupStack, childGroupName] : groupStack;
97
+ const nextRootGroup = rootGroup ?? (segments.length === 0 ? childGroupName : undefined);
98
+ const childRoutes = await collectRoutes(path.join(dir, child.name), [...segments, child.name], nextGroupStack, nextRootGroup);
99
+ routes.push(...childRoutes);
100
+ }
101
+ return routes;
99
102
  };
100
103
  const sanitizeGroupName = (value) => {
101
- const trimmed = value.trim();
102
- return trimmed.length ? trimmed : 'routes';
104
+ const trimmed = value.trim();
105
+ return trimmed.length ? trimmed : 'routes';
103
106
  };
104
107
  const toRouteVariableName = (groupName) => {
105
- const base = toCamelCase(sanitizeGroupName(groupName).replace(/[^\p{L}\p{N}_-]+/gu, '-'));
106
- return `${base || 'routes'}Routes`;
108
+ const base = toCamelCase(sanitizeGroupName(groupName).replace(/[^\p{L}\p{N}_-]+/gu, '-'));
109
+ return `${base || 'routes'}Routes`;
107
110
  };
108
111
  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;
112
+ if (!used.has(name)) {
113
+ used.add(name);
114
+ return name;
115
+ }
116
+ let index = 2;
117
+ let nextName = `${name}${index}`;
118
+ while (used.has(nextName)) {
119
+ index += 1;
120
+ nextName = `${name}${index}`;
121
+ }
122
+ used.add(nextName);
123
+ return nextName;
121
124
  };
122
125
  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;
126
+ const groups = new Map();
127
+ for (const route of routes) {
128
+ const groupName = mode === 'none'
129
+ ? 'routes'
130
+ : mode === 'root-groups'
131
+ ? (route.rootGroup ?? 'routes')
132
+ : (sanitizeGroupName(String(resolver?.(route) ?? 'routes')) ?? 'routes');
133
+ const list = groups.get(groupName) ?? [];
134
+ list.push(route);
135
+ groups.set(groupName, list);
136
+ }
137
+ return groups;
136
138
  };
137
139
  const createStringArray = (items, indent = '\t') => {
138
- if (!items.length) return '[]';
139
- return `[\n${items.map((item) => `${indent}'${item}'`).join(',\n')}\n]`;
140
+ if (!items.length)
141
+ return '[]';
142
+ return `[\n${items.map((item) => `${indent}'${item}'`).join(',\n')}\n]`;
140
143
  };
141
144
  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`;
145
+ const usedVariables = new Set();
146
+ const groupEntries = [...groups.entries()].map(([groupName, routes]) => ({
147
+ groupName,
148
+ variableName: ensureUniqueVariableName(groupName === 'routes' ? (groups.size === 1 ? 'routes' : 'ungroupedRoutes') : toRouteVariableName(groupName), usedVariables),
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 type Route = (typeof routes)[number];');
161
+ lines.push('');
162
+ return `${lines.join('\n')}\n`;
170
163
  };
171
164
  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;
165
+ const { mode } = await prompts({
166
+ type: 'select',
167
+ name: 'mode',
168
+ message: 'How should routes be grouped?',
169
+ choices: [
170
+ { title: 'By root route groups: (account), (landing), ...', value: 'root-groups' },
171
+ { title: 'By azure-net.config.ts groupRoutesFunc', value: 'config-function' },
172
+ { title: 'Do not group, generate one routes array', value: 'none' }
173
+ ]
174
+ });
175
+ return mode ? mode : null;
183
176
  };
184
177
  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;
178
+ const config = await loadUserConfig();
179
+ if (typeof config.groupRoutesFunc !== 'function') {
180
+ console.error('❌ `groupRoutesFunc` is missing in azure-net.config.ts/js or is not a function.');
181
+ console.error('Example:');
182
+ console.error('export default {');
183
+ console.error("\tgroupRoutesFunc: (route) => route.rootGroup ?? 'app'");
184
+ console.error('};');
185
+ return null;
186
+ }
187
+ return config.groupRoutesFunc;
195
188
  };
196
189
  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}`);
190
+ const mode = await selectGroupingMode();
191
+ if (!mode)
192
+ return;
193
+ const { sharedContext } = await getSharedState();
194
+ const resolver = mode === 'config-function' ? await getConfigRouteGroupResolver() : undefined;
195
+ if (mode === 'config-function' && !resolver) {
196
+ process.exitCode = 1;
197
+ return;
198
+ }
199
+ const routes = await collectRoutes(ROUTES_DIR);
200
+ if (!routes.length) {
201
+ console.warn('⚠️ No SvelteKit routes found in src/routes');
202
+ return;
203
+ }
204
+ const groups = createGroupMap(routes, mode, resolver ?? undefined);
205
+ const outputDir = path.join(getSharedContextRootPath(sharedContext.name), 'runtime', 'routes');
206
+ const outputFile = path.join(outputDir, 'index.ts');
207
+ await fs.mkdir(outputDir, { recursive: true });
208
+ await fs.writeFile(outputFile, createGeneratedFile(groups), 'utf-8');
209
+ console.log(`✅ Routes generated: ${outputFile}`);
216
210
  }
217
- //# sourceMappingURL=generateRoutes.js.map
211
+ //# sourceMappingURL=generateRoutes.js.map
@@ -212,14 +212,7 @@ const createGeneratedFile = (groups: Map<string, RouteRecord[]>): string => {
212
212
  lines.push('');
213
213
  }
214
214
 
215
- lines.push('export const routeGroups = {');
216
- lines.push(
217
- ...groupEntries.map((group, index) => `\t'${group.groupName}': ${group.variableName}${index === groupEntries.length - 1 ? '' : ','}`)
218
- );
219
- lines.push('} as const;');
220
- lines.push('');
221
215
  lines.push('export type Route = (typeof routes)[number];');
222
- lines.push('export type RouteGroupName = keyof typeof routeGroups;');
223
216
  lines.push('');
224
217
 
225
218
  return `${lines.join('\n')}\n`;