@@ -72,10 +72,11 @@ export async function listTemplates(cwd: string = process.cwd()): Promise<void>
7272 return ;
7373 }
7474
75- const files = await fs . readdir ( templatesDir ) ;
76- const templateFiles = files . filter ( ( f ) => f . endsWith ( '.md' ) ) ;
75+ const entries = await fs . readdir ( templatesDir , { withFileTypes : true } ) ;
76+ const templateFiles = entries . filter ( ( e ) => e . isFile ( ) && e . name . endsWith ( '.md' ) ) ;
77+ const templateDirs = entries . filter ( ( e ) => e . isDirectory ( ) ) ;
7778
78- if ( templateFiles . length === 0 ) {
79+ if ( templateFiles . length === 0 && templateDirs . length === 0 ) {
7980 console . log ( chalk . yellow ( 'No templates found.' ) ) ;
8081 console . log ( '' ) ;
8182 return ;
@@ -87,21 +88,51 @@ export async function listTemplates(cwd: string = process.cwd()): Promise<void>
8788 for ( const [ name , file ] of Object . entries ( config . templates ) ) {
8889 const isDefault = config . template === file ;
8990 const marker = isDefault ? chalk . green ( '✓ (default)' ) : '' ;
90- console . log ( ` ${ chalk . bold ( name ) } : ${ file } ${ marker } ` ) ;
91+
92+ // Check if it's a directory-based template
93+ const templatePath = path . join ( templatesDir , file ) ;
94+ try {
95+ const stat = await fs . stat ( templatePath ) ;
96+ if ( stat . isDirectory ( ) ) {
97+ // List files in the directory
98+ const dirFiles = await fs . readdir ( templatePath ) ;
99+ const mdFiles = dirFiles . filter ( f => f . endsWith ( '.md' ) ) ;
100+ console . log ( ` ${ chalk . bold ( name ) } : ${ file } / ${ marker } ` ) ;
101+ console . log ( chalk . gray ( ` Files: ${ mdFiles . join ( ', ' ) } ` ) ) ;
102+ } else {
103+ console . log ( ` ${ chalk . bold ( name ) } : ${ file } ${ marker } ` ) ;
104+ }
105+ } catch {
106+ console . log ( ` ${ chalk . bold ( name ) } : ${ file } ${ marker } ${ chalk . red ( '(missing)' ) } ` ) ;
107+ }
91108 }
92109 console . log ( '' ) ;
93110 }
94111
95112 // Show all available template files
96- console . log ( chalk . cyan ( 'Available files:' ) ) ;
97- for ( const file of templateFiles ) {
98- const filePath = path . join ( templatesDir , file ) ;
99- const stat = await fs . stat ( filePath ) ;
100- const sizeKB = ( stat . size / 1024 ) . toFixed ( 1 ) ;
101- console . log ( ` ${ file } (${ sizeKB } KB)` ) ;
113+ if ( templateFiles . length > 0 ) {
114+ console . log ( chalk . cyan ( 'Available files:' ) ) ;
115+ for ( const entry of templateFiles ) {
116+ const filePath = path . join ( templatesDir , entry . name ) ;
117+ const stat = await fs . stat ( filePath ) ;
118+ const sizeKB = ( stat . size / 1024 ) . toFixed ( 1 ) ;
119+ console . log ( ` ${ entry . name } (${ sizeKB } KB)` ) ;
120+ }
121+ console . log ( '' ) ;
122+ }
123+
124+ // Show available template directories (multi-file templates)
125+ if ( templateDirs . length > 0 ) {
126+ console . log ( chalk . cyan ( 'Available directories (multi-file templates):' ) ) ;
127+ for ( const entry of templateDirs ) {
128+ const dirPath = path . join ( templatesDir , entry . name ) ;
129+ const dirFiles = await fs . readdir ( dirPath ) ;
130+ const mdFiles = dirFiles . filter ( f => f . endsWith ( '.md' ) ) ;
131+ console . log ( ` ${ entry . name } / (${ mdFiles . length } files: ${ mdFiles . join ( ', ' ) } )` ) ;
132+ }
133+ console . log ( '' ) ;
102134 }
103135
104- console . log ( '' ) ;
105136 console . log ( chalk . gray ( 'Use templates with: lean-spec create <name> --template=<template-name>' ) ) ;
106137 console . log ( '' ) ;
107138}
@@ -123,12 +154,33 @@ export async function showTemplate(
123154 const templatePath = path . join ( templatesDir , templateFile ) ;
124155
125156 try {
126- const content = await fs . readFile ( templatePath , 'utf-8' ) ;
127- console . log ( '' ) ;
128- console . log ( chalk . cyan ( `=== Template: ${ templateName } (${ templateFile } ) ===` ) ) ;
129- console . log ( '' ) ;
130- console . log ( content ) ;
131- console . log ( '' ) ;
157+ const stat = await fs . stat ( templatePath ) ;
158+
159+ if ( stat . isDirectory ( ) ) {
160+ // Directory-based template - show all files
161+ console . log ( '' ) ;
162+ console . log ( chalk . cyan ( `=== Template: ${ templateName } (${ templateFile } /) ===` ) ) ;
163+ console . log ( '' ) ;
164+
165+ const files = await fs . readdir ( templatePath ) ;
166+ const mdFiles = files . filter ( f => f . endsWith ( '.md' ) ) ;
167+
168+ for ( const file of mdFiles ) {
169+ const filePath = path . join ( templatePath , file ) ;
170+ const content = await fs . readFile ( filePath , 'utf-8' ) ;
171+ console . log ( chalk . yellow ( `--- ${ file } ---` ) ) ;
172+ console . log ( content ) ;
173+ console . log ( '' ) ;
174+ }
175+ } else {
176+ // Single file template
177+ const content = await fs . readFile ( templatePath , 'utf-8' ) ;
178+ console . log ( '' ) ;
179+ console . log ( chalk . cyan ( `=== Template: ${ templateName } (${ templateFile } ) ===` ) ) ;
180+ console . log ( '' ) ;
181+ console . log ( content ) ;
182+ console . log ( '' ) ;
183+ }
132184 } catch ( error ) {
133185 console . error ( chalk . red ( `Error reading template: ${ templateFile } ` ) ) ;
134186 console . error ( error ) ;
@@ -145,14 +197,25 @@ export async function addTemplate(
145197 const templatesDir = path . join ( cwd , '.lean-spec' , 'templates' ) ;
146198 const templatePath = path . join ( templatesDir , file ) ;
147199
148- // Check if file exists
200+ // Check if file or directory exists
149201 try {
150- await fs . access ( templatePath ) ;
202+ const stat = await fs . stat ( templatePath ) ;
203+ if ( stat . isDirectory ( ) ) {
204+ // Verify it has a README.md (main template file)
205+ const mainFile = path . join ( templatePath , 'README.md' ) ;
206+ try {
207+ await fs . access ( mainFile ) ;
208+ } catch {
209+ console . error ( chalk . red ( `Directory template must contain README.md: ${ file } /` ) ) ;
210+ console . error ( chalk . gray ( `Expected at: ${ mainFile } ` ) ) ;
211+ process . exit ( 1 ) ;
212+ }
213+ }
151214 } catch {
152- console . error ( chalk . red ( `Template file not found: ${ file } ` ) ) ;
215+ console . error ( chalk . red ( `Template not found: ${ file } ` ) ) ;
153216 console . error ( chalk . gray ( `Expected at: ${ templatePath } ` ) ) ;
154217 console . error (
155- chalk . yellow ( 'Create the file first or use: lean-spec templates copy <source> <target>' ) ,
218+ chalk . yellow ( 'Create the file/directory first or use: lean-spec templates copy <source> <target>' ) ,
156219 ) ;
157220 process . exit ( 1 ) ;
158221 }
0 commit comments