lean-spec 0.2.7-dev.20251127082201 → 0.2.7-dev.20251128011647

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.
@@ -141,13 +141,13 @@ async function loadSubFiles(specDir, options = {}) {
141
141
  if (entry.name === "README.md") continue;
142
142
  if (entry.isDirectory()) continue;
143
143
  const filePath = path17.join(specDir, entry.name);
144
- const stat6 = await fs12.stat(filePath);
144
+ const stat7 = await fs12.stat(filePath);
145
145
  const ext = path17.extname(entry.name).toLowerCase();
146
146
  const isDocument = ext === ".md";
147
147
  const subFile = {
148
148
  name: entry.name,
149
149
  path: filePath,
150
- size: stat6.size,
150
+ size: stat7.size,
151
151
  type: isDocument ? "document" : "asset"
152
152
  };
153
153
  if (isDocument && options.includeContent) {
@@ -3538,6 +3538,7 @@ async function createSpec(name, options = {}) {
3538
3538
  await fs12.mkdir(specDir, { recursive: true });
3539
3539
  const templatesDir = path17.join(cwd, ".lean-spec", "templates");
3540
3540
  let templateName;
3541
+ let templateDir = null;
3541
3542
  if (options.template) {
3542
3543
  if (config.templates?.[options.template]) {
3543
3544
  templateName = config.templates[options.template];
@@ -3550,7 +3551,12 @@ async function createSpec(name, options = {}) {
3550
3551
  }
3551
3552
  let templatePath = path17.join(templatesDir, templateName);
3552
3553
  try {
3553
- await fs12.access(templatePath);
3554
+ const stat7 = await fs12.stat(templatePath);
3555
+ if (stat7.isDirectory()) {
3556
+ templateDir = templatePath;
3557
+ templatePath = path17.join(templateDir, "README.md");
3558
+ await fs12.access(templatePath);
3559
+ }
3554
3560
  } catch {
3555
3561
  const legacyPath = path17.join(templatesDir, "spec-template.md");
3556
3562
  try {
@@ -3617,13 +3623,16 @@ ${options.description}`
3617
3623
  }
3618
3624
  await fs12.writeFile(specFile, content, "utf-8");
3619
3625
  try {
3620
- const templateFiles = await fs12.readdir(templatesDir);
3621
- const additionalFiles = templateFiles.filter(
3622
- (f) => f.endsWith(".md") && f !== templateName && f !== "spec-template.md" && f !== config.structure.defaultFile
3623
- );
3626
+ let additionalFiles = [];
3627
+ if (templateDir) {
3628
+ const templateFiles = await fs12.readdir(templateDir);
3629
+ additionalFiles = templateFiles.filter(
3630
+ (f) => f.endsWith(".md") && f !== "README.md"
3631
+ );
3632
+ }
3624
3633
  if (additionalFiles.length > 0) {
3625
3634
  for (const file of additionalFiles) {
3626
- const srcPath = path17.join(templatesDir, file);
3635
+ const srcPath = path17.join(templateDir, file);
3627
3636
  const destPath = path17.join(specDir, file);
3628
3637
  let fileContent = await fs12.readFile(srcPath, "utf-8");
3629
3638
  fileContent = resolveVariables(fileContent, varContext);
@@ -4362,9 +4371,10 @@ async function listTemplates(cwd = process.cwd()) {
4362
4371
  console.log("");
4363
4372
  return;
4364
4373
  }
4365
- const files = await fs12.readdir(templatesDir);
4366
- const templateFiles = files.filter((f) => f.endsWith(".md"));
4367
- if (templateFiles.length === 0) {
4374
+ const entries = await fs12.readdir(templatesDir, { withFileTypes: true });
4375
+ const templateFiles = entries.filter((e) => e.isFile() && e.name.endsWith(".md"));
4376
+ const templateDirs = entries.filter((e) => e.isDirectory());
4377
+ if (templateFiles.length === 0 && templateDirs.length === 0) {
4368
4378
  console.log(chalk20.yellow("No templates found."));
4369
4379
  console.log("");
4370
4380
  return;
@@ -4374,18 +4384,43 @@ async function listTemplates(cwd = process.cwd()) {
4374
4384
  for (const [name, file] of Object.entries(config.templates)) {
4375
4385
  const isDefault = config.template === file;
4376
4386
  const marker = isDefault ? chalk20.green("\u2713 (default)") : "";
4377
- console.log(` ${chalk20.bold(name)}: ${file} ${marker}`);
4387
+ const templatePath = path17.join(templatesDir, file);
4388
+ try {
4389
+ const stat7 = await fs12.stat(templatePath);
4390
+ if (stat7.isDirectory()) {
4391
+ const dirFiles = await fs12.readdir(templatePath);
4392
+ const mdFiles = dirFiles.filter((f) => f.endsWith(".md"));
4393
+ console.log(` ${chalk20.bold(name)}: ${file}/ ${marker}`);
4394
+ console.log(chalk20.gray(` Files: ${mdFiles.join(", ")}`));
4395
+ } else {
4396
+ console.log(` ${chalk20.bold(name)}: ${file} ${marker}`);
4397
+ }
4398
+ } catch {
4399
+ console.log(` ${chalk20.bold(name)}: ${file} ${marker} ${chalk20.red("(missing)")}`);
4400
+ }
4378
4401
  }
4379
4402
  console.log("");
4380
4403
  }
4381
- console.log(chalk20.cyan("Available files:"));
4382
- for (const file of templateFiles) {
4383
- const filePath = path17.join(templatesDir, file);
4384
- const stat6 = await fs12.stat(filePath);
4385
- const sizeKB = (stat6.size / 1024).toFixed(1);
4386
- console.log(` ${file} (${sizeKB} KB)`);
4404
+ if (templateFiles.length > 0) {
4405
+ console.log(chalk20.cyan("Available files:"));
4406
+ for (const entry of templateFiles) {
4407
+ const filePath = path17.join(templatesDir, entry.name);
4408
+ const stat7 = await fs12.stat(filePath);
4409
+ const sizeKB = (stat7.size / 1024).toFixed(1);
4410
+ console.log(` ${entry.name} (${sizeKB} KB)`);
4411
+ }
4412
+ console.log("");
4413
+ }
4414
+ if (templateDirs.length > 0) {
4415
+ console.log(chalk20.cyan("Available directories (multi-file templates):"));
4416
+ for (const entry of templateDirs) {
4417
+ const dirPath = path17.join(templatesDir, entry.name);
4418
+ const dirFiles = await fs12.readdir(dirPath);
4419
+ const mdFiles = dirFiles.filter((f) => f.endsWith(".md"));
4420
+ console.log(` ${entry.name}/ (${mdFiles.length} files: ${mdFiles.join(", ")})`);
4421
+ }
4422
+ console.log("");
4387
4423
  }
4388
- console.log("");
4389
4424
  console.log(chalk20.gray("Use templates with: lean-spec create <name> --template=<template-name>"));
4390
4425
  console.log("");
4391
4426
  }
@@ -4400,12 +4435,28 @@ async function showTemplate(templateName, cwd = process.cwd()) {
4400
4435
  const templateFile = config.templates[templateName];
4401
4436
  const templatePath = path17.join(templatesDir, templateFile);
4402
4437
  try {
4403
- const content = await fs12.readFile(templatePath, "utf-8");
4404
- console.log("");
4405
- console.log(chalk20.cyan(`=== Template: ${templateName} (${templateFile}) ===`));
4406
- console.log("");
4407
- console.log(content);
4408
- console.log("");
4438
+ const stat7 = await fs12.stat(templatePath);
4439
+ if (stat7.isDirectory()) {
4440
+ console.log("");
4441
+ console.log(chalk20.cyan(`=== Template: ${templateName} (${templateFile}/) ===`));
4442
+ console.log("");
4443
+ const files = await fs12.readdir(templatePath);
4444
+ const mdFiles = files.filter((f) => f.endsWith(".md"));
4445
+ for (const file of mdFiles) {
4446
+ const filePath = path17.join(templatePath, file);
4447
+ const content = await fs12.readFile(filePath, "utf-8");
4448
+ console.log(chalk20.yellow(`--- ${file} ---`));
4449
+ console.log(content);
4450
+ console.log("");
4451
+ }
4452
+ } else {
4453
+ const content = await fs12.readFile(templatePath, "utf-8");
4454
+ console.log("");
4455
+ console.log(chalk20.cyan(`=== Template: ${templateName} (${templateFile}) ===`));
4456
+ console.log("");
4457
+ console.log(content);
4458
+ console.log("");
4459
+ }
4409
4460
  } catch (error) {
4410
4461
  console.error(chalk20.red(`Error reading template: ${templateFile}`));
4411
4462
  console.error(error);
@@ -4417,12 +4468,22 @@ async function addTemplate(name, file, cwd = process.cwd()) {
4417
4468
  const templatesDir = path17.join(cwd, ".lean-spec", "templates");
4418
4469
  const templatePath = path17.join(templatesDir, file);
4419
4470
  try {
4420
- await fs12.access(templatePath);
4471
+ const stat7 = await fs12.stat(templatePath);
4472
+ if (stat7.isDirectory()) {
4473
+ const mainFile = path17.join(templatePath, "README.md");
4474
+ try {
4475
+ await fs12.access(mainFile);
4476
+ } catch {
4477
+ console.error(chalk20.red(`Directory template must contain README.md: ${file}/`));
4478
+ console.error(chalk20.gray(`Expected at: ${mainFile}`));
4479
+ process.exit(1);
4480
+ }
4481
+ }
4421
4482
  } catch {
4422
- console.error(chalk20.red(`Template file not found: ${file}`));
4483
+ console.error(chalk20.red(`Template not found: ${file}`));
4423
4484
  console.error(chalk20.gray(`Expected at: ${templatePath}`));
4424
4485
  console.error(
4425
- chalk20.yellow("Create the file first or use: lean-spec templates copy <source> <target>")
4486
+ chalk20.yellow("Create the file/directory first or use: lean-spec templates copy <source> <target>")
4426
4487
  );
4427
4488
  process.exit(1);
4428
4489
  }
@@ -11384,5 +11445,5 @@ if (import.meta.url === `file://${process.argv[1]}`) {
11384
11445
  }
11385
11446
 
11386
11447
  export { agentCommand, analyzeCommand, archiveCommand, backfillCommand, boardCommand, checkCommand, compactCommand, createCommand, createMcpServer, depsCommand, examplesCommand, filesCommand, ganttCommand, initCommand, linkCommand, listCommand, mcpCommand, migrateCommand, openCommand, searchCommand, splitCommand, statsCommand, templatesCommand, timelineCommand, tokensCommand, uiCommand, unlinkCommand, updateCommand, validateCommand, viewCommand };
11387
- //# sourceMappingURL=chunk-2DAPKDV5.js.map
11388
- //# sourceMappingURL=chunk-2DAPKDV5.js.map
11448
+ //# sourceMappingURL=chunk-KKBRTXTX.js.map
11449
+ //# sourceMappingURL=chunk-KKBRTXTX.js.map