(preferredFramework?: string)
| 211 | } |
| 212 | |
| 213 | export async function listTemplateChoices(preferredFramework?: string): Promise< |
| 214 | Array<{ |
| 215 | id: string |
| 216 | name: string |
| 217 | description?: string |
| 218 | framework: string |
| 219 | }> |
| 220 | > { |
| 221 | const frameworkFilter = preferredFramework?.toLowerCase() |
| 222 | const deduped = new Map< |
| 223 | string, |
| 224 | { id: string; name: string; description?: string; framework: string } |
| 225 | >() |
| 226 | |
| 227 | const registry = await getRawRegistry() |
| 228 | for (const starter of registry?.starters || []) { |
| 229 | const framework = starter.framework.toLowerCase() |
| 230 | if (frameworkFilter && framework !== frameworkFilter) { |
| 231 | continue |
| 232 | } |
| 233 | |
| 234 | const ids = Array.from(getStarterIdsFromUrl(starter.url)) |
| 235 | const id = ids[0] || slugifyStarterName(starter.name) |
| 236 | if (!id) { |
| 237 | continue |
| 238 | } |
| 239 | |
| 240 | const key = `${framework}:${id}` |
| 241 | if (!deduped.has(key)) { |
| 242 | deduped.set(key, { |
| 243 | id, |
| 244 | name: starter.name, |
| 245 | description: starter.description, |
| 246 | framework, |
| 247 | }) |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | const cwd = process.cwd() |
| 252 | const rootCandidates = [ |
| 253 | cwd, |
| 254 | resolve(cwd, '..'), |
| 255 | resolve(cwd, '../..'), |
| 256 | resolve(cwd, '../../..'), |
| 257 | ] |
| 258 | |
| 259 | const frameworks = frameworkFilter ? [frameworkFilter] : ['react', 'solid'] |
| 260 | |
| 261 | for (const root of rootCandidates) { |
| 262 | for (const framework of frameworks) { |
| 263 | const frameworkDir = resolve(root, 'examples', framework) |
| 264 | if (!fs.existsSync(frameworkDir) || !fs.statSync(frameworkDir).isDirectory()) { |
| 265 | continue |
| 266 | } |
| 267 | |
| 268 | for (const entry of fs.readdirSync(frameworkDir, { withFileTypes: true })) { |
| 269 | if (!entry.isDirectory()) { |
| 270 | continue |
no test coverage detected