specweave 0.23.2 → 0.23.5

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 (106) hide show
  1. package/CLAUDE.md +367 -0
  2. package/dist/plugins/specweave/lib/utils/fs-native.d.ts +133 -0
  3. package/dist/plugins/specweave/lib/utils/fs-native.d.ts.map +1 -0
  4. package/dist/plugins/specweave/lib/utils/fs-native.js +224 -0
  5. package/dist/plugins/specweave/lib/utils/fs-native.js.map +1 -0
  6. package/dist/plugins/specweave-github/lib/github-client-v2.js +1 -1
  7. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  8. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
  9. package/dist/plugins/specweave-github/lib/github-feature-sync.js +52 -20
  10. package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
  11. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -1
  12. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +24 -0
  13. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -1
  14. package/dist/src/cli/helpers/init/initial-increment-generator.d.ts.map +1 -1
  15. package/dist/src/cli/helpers/init/initial-increment-generator.js +2 -1
  16. package/dist/src/cli/helpers/init/initial-increment-generator.js.map +1 -1
  17. package/dist/src/core/ac-test-validator-cli.d.ts +16 -0
  18. package/dist/src/core/ac-test-validator-cli.d.ts.map +1 -0
  19. package/dist/src/core/ac-test-validator-cli.js +118 -0
  20. package/dist/src/core/ac-test-validator-cli.js.map +1 -0
  21. package/dist/src/core/ac-test-validator.d.ts +111 -0
  22. package/dist/src/core/ac-test-validator.d.ts.map +1 -0
  23. package/dist/src/core/ac-test-validator.js +292 -0
  24. package/dist/src/core/ac-test-validator.js.map +1 -0
  25. package/dist/src/core/increment/desync-detector.d.ts +142 -0
  26. package/dist/src/core/increment/desync-detector.d.ts.map +1 -0
  27. package/dist/src/core/increment/desync-detector.js +270 -0
  28. package/dist/src/core/increment/desync-detector.js.map +1 -0
  29. package/dist/src/core/increment/metadata-manager.d.ts +8 -4
  30. package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
  31. package/dist/src/core/increment/metadata-manager.js +45 -21
  32. package/dist/src/core/increment/metadata-manager.js.map +1 -1
  33. package/dist/src/core/qa/qa-runner.js +9 -2
  34. package/dist/src/core/qa/qa-runner.js.map +1 -1
  35. package/dist/src/sync/sync-coordinator.d.ts +1 -1
  36. package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
  37. package/dist/src/sync/sync-coordinator.js +40 -2
  38. package/dist/src/sync/sync-coordinator.js.map +1 -1
  39. package/dist/src/utils/fs-native.d.ts +133 -0
  40. package/dist/src/utils/fs-native.d.ts.map +1 -0
  41. package/dist/src/utils/fs-native.js +224 -0
  42. package/dist/src/utils/fs-native.js.map +1 -0
  43. package/package.json +1 -1
  44. package/plugins/specweave/.claude-plugin/plugin.json +12 -0
  45. package/plugins/specweave/agents/AGENTS-INDEX.md +216 -0
  46. package/plugins/specweave/agents/architect/AGENT.md +17 -0
  47. package/plugins/specweave/agents/code-standards-detective/AGENT.md +16 -0
  48. package/plugins/specweave/agents/docs-writer/AGENT.md +16 -0
  49. package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +704 -0
  50. package/plugins/specweave/agents/infrastructure/AGENT.md +16 -0
  51. package/plugins/specweave/agents/performance/AGENT.md +16 -0
  52. package/plugins/specweave/agents/pm/AGENT.md +17 -0
  53. package/plugins/specweave/agents/qa-lead/AGENT.md +15 -0
  54. package/plugins/specweave/agents/reflective-reviewer/AGENT.md +16 -0
  55. package/plugins/specweave/agents/security/AGENT.md +16 -0
  56. package/plugins/specweave/agents/tdd-orchestrator/AGENT.md +16 -0
  57. package/plugins/specweave/agents/tech-lead/AGENT.md +16 -0
  58. package/plugins/specweave/agents/test-aware-planner/AGENT.md +16 -0
  59. package/plugins/specweave/agents/translator/AGENT.md +13 -0
  60. package/plugins/specweave/commands/specweave-done.md +14 -0
  61. package/plugins/specweave/commands/specweave-qa.md +11 -1
  62. package/plugins/specweave/commands/specweave-sync-status.md +356 -0
  63. package/plugins/specweave/commands/specweave-validate.md +10 -1
  64. package/plugins/specweave/hooks/pre-task-completion.sh +196 -0
  65. package/plugins/specweave/lib/hooks/git-diff-analyzer.js +3 -3
  66. package/plugins/specweave/lib/hooks/git-diff-analyzer.ts +3 -3
  67. package/plugins/specweave/lib/hooks/invoke-translator-skill.js +3 -2
  68. package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +3 -2
  69. package/plugins/specweave/lib/hooks/prepare-reflection-context.js +3 -3
  70. package/plugins/specweave/lib/hooks/prepare-reflection-context.ts +3 -3
  71. package/plugins/specweave/lib/hooks/reflection-config-loader.js +4 -4
  72. package/plugins/specweave/lib/hooks/reflection-config-loader.ts +4 -4
  73. package/plugins/specweave/lib/hooks/reflection-storage.js +9 -9
  74. package/plugins/specweave/lib/hooks/reflection-storage.ts +9 -9
  75. package/plugins/specweave/lib/hooks/sync-cache.js +9 -8
  76. package/plugins/specweave/lib/hooks/sync-living-docs.js +57 -6
  77. package/plugins/specweave/lib/hooks/sync-us-tasks.js +6 -6
  78. package/plugins/specweave/lib/hooks/translate-file.js +3 -2
  79. package/plugins/specweave/lib/hooks/translate-file.ts +3 -2
  80. package/plugins/specweave/lib/hooks/translate-living-docs.js +4 -3
  81. package/plugins/specweave/lib/hooks/translate-living-docs.ts +4 -3
  82. package/plugins/specweave/lib/hooks/update-tasks-md.js +3 -3
  83. package/plugins/specweave/lib/hooks/update-tasks-md.ts +3 -3
  84. package/plugins/specweave/lib/utils/fs-native.js +182 -0
  85. package/plugins/specweave/lib/utils/fs-native.ts +283 -0
  86. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +8 -4
  87. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +45 -21
  88. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
  89. package/plugins/specweave/skills/SKILLS-INDEX.md +26 -2
  90. package/plugins/specweave/skills/increment-planner/SKILL.md +2 -2
  91. package/plugins/specweave-ado/commands/specweave-ado-close-workitem.md +1 -1
  92. package/plugins/specweave-ado/commands/specweave-ado-create-workitem.md +1 -1
  93. package/plugins/specweave-ado/commands/specweave-ado-status.md +1 -1
  94. package/plugins/specweave-ado/commands/specweave-ado-sync.md +1 -1
  95. package/plugins/specweave-diagrams/agents/diagrams-architect/AGENT.md +1 -1
  96. package/plugins/specweave-diagrams/skills/diagrams-generator/SKILL.md +4 -4
  97. package/plugins/specweave-github/lib/github-client-v2.js +2 -1
  98. package/plugins/specweave-github/lib/github-client-v2.ts +1 -1
  99. package/plugins/specweave-github/lib/github-feature-sync.js +30 -17
  100. package/plugins/specweave-github/lib/github-feature-sync.ts +54 -24
  101. package/plugins/specweave-github/lib/user-story-issue-builder.js +24 -0
  102. package/plugins/specweave-github/lib/user-story-issue-builder.ts +33 -0
  103. package/plugins/specweave-mobile/README.md +1 -1
  104. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +72 -0
  105. package/src/templates/CLAUDE.md.template +13 -0
  106. package/plugins/specweave/skills/task-builder/README.md +0 -84
@@ -1,15 +1,31 @@
1
1
  #!/usr/bin/env node
2
- import fs from "fs-extra";
2
+ import { promises as fs, existsSync } from "fs";
3
3
  import path from "path";
4
4
  import { execSync } from "child_process";
5
+ import { mkdirpSync } from "../utils/fs-native.js";
5
6
  async function syncLivingDocs(incrementId) {
6
7
  try {
7
8
  console.log(`
8
9
  \u{1F4DA} Checking living docs sync for increment: ${incrementId}`);
10
+ // Load and validate config with error handling
9
11
  const configPath = path.join(process.cwd(), ".specweave", "config.json");
10
12
  let config = {};
11
- if (fs.existsSync(configPath)) {
12
- config = JSON.parse(await fs.readFile(configPath, "utf-8"));
13
+
14
+ try {
15
+ if (existsSync(configPath)) {
16
+ const rawContent = await fs.readFile(configPath, "utf-8");
17
+ config = JSON.parse(rawContent);
18
+ } else {
19
+ console.log("\u26A0\uFE0F No config.json found, using safe defaults (all permissions disabled)");
20
+ console.log(" To configure: Run 'specweave init' or create .specweave/config.json");
21
+ config = { sync: { settings: {} } };
22
+ }
23
+ } catch (error) {
24
+ console.error("\u274C Failed to load config.json:", error.message);
25
+ console.error(" File may be corrupted or contain invalid JSON");
26
+ console.error(" Using safe defaults (all permissions denied)");
27
+ console.error(" To fix: Check .specweave/config.json for syntax errors");
28
+ config = { sync: { settings: {} } };
13
29
  }
14
30
  const syncEnabled = config.hooks?.post_task_completion?.sync_living_docs ?? false;
15
31
  if (!syncEnabled) {
@@ -18,6 +34,22 @@ async function syncLivingDocs(incrementId) {
18
34
  return;
19
35
  }
20
36
  console.log("\u2705 Living docs sync enabled");
37
+
38
+ // ========================================================================
39
+ // GATE 1: canUpsertInternalItems (v0.24.0+ - Internal Docs Permission)
40
+ // ========================================================================
41
+ // This permission controls whether SpecWeave can CREATE/UPDATE internal docs.
42
+ // If false, ALL living docs sync is blocked (both local and external).
43
+ const canUpsertInternal = config.sync?.settings?.canUpsertInternalItems ?? false;
44
+
45
+ if (!canUpsertInternal) {
46
+ console.log("\u26D4 Living docs sync BLOCKED (canUpsertInternalItems = false)");
47
+ console.log(" To enable: Set sync.settings.canUpsertInternalItems = true in config.json");
48
+ console.log(" No internal docs or external tools will be updated");
49
+ return;
50
+ }
51
+
52
+ console.log("\u2705 Internal docs sync permitted (canUpsertInternalItems = true)");
21
53
  const intelligentEnabled = config.livingDocs?.intelligent?.enabled ?? false;
22
54
  let specCopied = false;
23
55
  let changedDocs = [];
@@ -54,6 +86,25 @@ async function syncLivingDocs(incrementId) {
54
86
  return;
55
87
  }
56
88
 
89
+ // ========================================================================
90
+ // GATE 3: autoSyncOnCompletion (v0.24.0+ - Automatic vs Manual Sync)
91
+ // ========================================================================
92
+ // This setting controls whether sync to external tools happens automatically
93
+ // on increment completion or requires manual /specweave:sync-* commands.
94
+ // DEFAULT: true (automatic sync enabled for better UX)
95
+ const autoSync = config.sync?.settings?.autoSyncOnCompletion ?? true;
96
+
97
+ if (!autoSync) {
98
+ console.log("\u26A0\uFE0F Automatic external sync DISABLED (autoSyncOnCompletion = false)");
99
+ console.log(" Living docs updated locally, but external tools NOT synced");
100
+ console.log(" To sync manually: Run /specweave-github:sync or /specweave-jira:sync");
101
+ console.log(" To enable auto-sync: Set sync.settings.autoSyncOnCompletion = true");
102
+ console.log("\u2705 Living docs sync complete (manual external sync required)\n");
103
+ return;
104
+ }
105
+
106
+ console.log("\u2705 Automatic external sync permitted (autoSyncOnCompletion = true)");
107
+
57
108
  // T-034E: Use FormatPreservationSyncService for origin-aware sync
58
109
  await syncWithFormatPreservation(incrementId);
59
110
 
@@ -184,7 +235,7 @@ async function extractAndMergeLivingDocs(incrementId) {
184
235
  } = await import("../../../../dist/src/utils/spec-parser.js");
185
236
  const projectRoot = process.cwd();
186
237
  const incrementSpecPath = path.join(projectRoot, ".specweave", "increments", incrementId, "spec.md");
187
- if (!fs.existsSync(incrementSpecPath)) {
238
+ if (!existsSync(incrementSpecPath)) {
188
239
  console.log(`\u26A0\uFE0F Increment spec not found: ${incrementSpecPath}`);
189
240
  return false;
190
241
  }
@@ -198,7 +249,7 @@ async function extractAndMergeLivingDocs(incrementId) {
198
249
  const specId = incrementSpec.implementsSpec || extractSpecId(incrementId);
199
250
  const livingDocsDir = path.join(projectRoot, ".specweave", "docs", "internal", "specs", "default");
200
251
  const livingDocsPath = path.join(livingDocsDir, `${specId}-${incrementId.replace(/^\d+-/, "")}.md`);
201
- const livingDocsExists = fs.existsSync(livingDocsPath);
252
+ const livingDocsExists = existsSync(livingDocsPath);
202
253
  if (livingDocsExists) {
203
254
  console.log(` \u{1F4DA} Living docs spec exists, merging user stories...`);
204
255
  const livingSpec = await parseLivingDocsSpec(livingDocsPath);
@@ -253,7 +304,7 @@ async function extractAndMergeLivingDocs(incrementId) {
253
304
  created: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
254
305
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
255
306
  };
256
- await fs.ensureDir(livingDocsDir);
307
+ mkdirpSync(livingDocsDir);
257
308
  await writeLivingDocsSpec(livingDocsPath, livingSpec);
258
309
  console.log(` \u2705 Created new living docs spec: ${specId}`);
259
310
  console.log(` \u2705 Added ${incrementSpec.userStories.length} user stories`);
@@ -10,7 +10,7 @@
10
10
  * Part of increment 0047-us-task-linkage implementation.
11
11
  */
12
12
 
13
- import fs from 'fs-extra';
13
+ import { readFileSync, existsSync, promises as fs } from 'fs';
14
14
  import path from 'path';
15
15
  import { parseTasksWithUSLinks, getAllTasks } from '../vendor/generators/spec/task-parser.js';
16
16
  import { glob } from 'glob';
@@ -32,7 +32,7 @@ export async function syncUSTasksToLivingDocs(incrementId, projectRoot, featureI
32
32
  const tasksPath = path.join(projectRoot, '.specweave', 'increments', incrementId, 'tasks.md');
33
33
 
34
34
  // Check if tasks.md exists
35
- if (!fs.existsSync(tasksPath)) {
35
+ if (!existsSync(tasksPath)) {
36
36
  console.log(` ⚠️ tasks.md not found, skipping task sync`);
37
37
  return { success: true, updatedFiles: [], errors: [] };
38
38
  }
@@ -451,8 +451,8 @@ function getProjectId(projectRoot, incrementId) {
451
451
  try {
452
452
  // Try to get from metadata.json
453
453
  const metadataPath = path.join(projectRoot, '.specweave', 'increments', incrementId, 'metadata.json');
454
- if (fs.existsSync(metadataPath)) {
455
- const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf-8'));
454
+ if (existsSync(metadataPath)) {
455
+ const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
456
456
  if (metadata.project) {
457
457
  return metadata.project;
458
458
  }
@@ -460,8 +460,8 @@ function getProjectId(projectRoot, incrementId) {
460
460
 
461
461
  // Try to get from config.json
462
462
  const configPath = path.join(projectRoot, '.specweave', 'config.json');
463
- if (fs.existsSync(configPath)) {
464
- const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
463
+ if (existsSync(configPath)) {
464
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
465
465
  if (config.defaultProject) {
466
466
  return config.defaultProject;
467
467
  }
@@ -1,4 +1,5 @@
1
- import fs from "fs-extra";
1
+ import { existsSync } from "fs";
2
+ import { promises as fs } from "fs";
2
3
  import {
3
4
  detectLanguage,
4
5
  prepareTranslation,
@@ -9,7 +10,7 @@ import {
9
10
  } from "../vendor/utils/translation.js";
10
11
  async function translateFile(options) {
11
12
  const { filePath, targetLang, preview, verbose } = options;
12
- if (!await fs.pathExists(filePath)) {
13
+ if (!existsSync(filePath)) {
13
14
  throw new Error(`File not found: ${filePath}`);
14
15
  }
15
16
  if (verbose) {
@@ -16,7 +16,8 @@
16
16
  * @see .specweave/increments/0006-llm-native-i18n/reports/DESIGN-POST-GENERATION-TRANSLATION.md
17
17
  */
18
18
 
19
- import fs from 'fs-extra';
19
+ import { existsSync } from 'fs';
20
+ import { promises as fs } from 'fs';
20
21
  import path from 'path';
21
22
  import {
22
23
  detectLanguage,
@@ -62,7 +63,7 @@ export async function translateFile(options: CLIOptions): Promise<FileTranslatio
62
63
  const { filePath, targetLang, preview, verbose } = options;
63
64
 
64
65
  // 1. Validate file exists
65
- if (!await fs.pathExists(filePath)) {
66
+ if (!existsSync(filePath)) {
66
67
  throw new Error(`File not found: ${filePath}`);
67
68
  }
68
69
 
@@ -1,13 +1,14 @@
1
1
  import { execSync } from "child_process";
2
- import fs from "fs-extra";
2
+ import { existsSync } from "fs";
3
+ import { promises as fs } from "fs";
3
4
  async function translateLivingDocs(incrementId) {
4
5
  try {
5
6
  const configPath = ".specweave/config.json";
6
- if (!fs.existsSync(configPath)) {
7
+ if (!existsSync(configPath)) {
7
8
  console.log("[translate-living-docs] No config found, skipping translation");
8
9
  return;
9
10
  }
10
- const config = await fs.readJson(configPath);
11
+ const config = JSON.parse(await fs.readFile(configPath, "utf-8"));
11
12
  if (!config.language || config.language === "en") {
12
13
  console.log("[translate-living-docs] Project language is English, skipping translation");
13
14
  return;
@@ -8,7 +8,8 @@
8
8
  */
9
9
 
10
10
  import { execSync } from 'child_process';
11
- import fs from 'fs-extra';
11
+ import { existsSync } from 'fs';
12
+ import { promises as fs } from 'fs';
12
13
  import path from 'path';
13
14
 
14
15
  interface Config {
@@ -27,12 +28,12 @@ export async function translateLivingDocs(incrementId: string): Promise<void> {
27
28
  try {
28
29
  // 1. Load config
29
30
  const configPath = '.specweave/config.json';
30
- if (!fs.existsSync(configPath)) {
31
+ if (!existsSync(configPath)) {
31
32
  console.log('[translate-living-docs] No config found, skipping translation');
32
33
  return;
33
34
  }
34
35
 
35
- const config: Config = await fs.readJson(configPath);
36
+ const config: Config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
36
37
 
37
38
  // 2. Check if translation is enabled
38
39
  if (!config.language || config.language === 'en') {
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
- import fs from "fs-extra";
2
+ import { existsSync, promises as fs } from "fs";
3
3
  import path from "path";
4
4
  async function updateTasksMd(incrementId) {
5
5
  try {
6
6
  console.log(`
7
7
  \u{1F504} Updating tasks.md for increment: ${incrementId}`);
8
8
  const incrementDir = path.join(process.cwd(), ".specweave", "increments", incrementId);
9
- if (!fs.existsSync(incrementDir)) {
9
+ if (!existsSync(incrementDir)) {
10
10
  console.error(`\u274C Increment directory not found: ${incrementDir}`);
11
11
  process.exit(1);
12
12
  }
13
13
  const tasksPath = path.join(incrementDir, "tasks.md");
14
- if (!fs.existsSync(tasksPath)) {
14
+ if (!existsSync(tasksPath)) {
15
15
  console.error(`\u274C tasks.md not found: ${tasksPath}`);
16
16
  process.exit(1);
17
17
  }
@@ -23,7 +23,7 @@
23
23
  * @version 1.0.0
24
24
  */
25
25
 
26
- import fs from 'fs-extra';
26
+ import { existsSync, promises as fs } from 'fs';
27
27
  import path from 'path';
28
28
 
29
29
  interface TaskMatch {
@@ -48,13 +48,13 @@ async function updateTasksMd(incrementId: string): Promise<void> {
48
48
 
49
49
  // 1. Validate increment exists
50
50
  const incrementDir = path.join(process.cwd(), '.specweave', 'increments', incrementId);
51
- if (!fs.existsSync(incrementDir)) {
51
+ if (!existsSync(incrementDir)) {
52
52
  console.error(`❌ Increment directory not found: ${incrementDir}`);
53
53
  process.exit(1);
54
54
  }
55
55
 
56
56
  const tasksPath = path.join(incrementDir, 'tasks.md');
57
- if (!fs.existsSync(tasksPath)) {
57
+ if (!existsSync(tasksPath)) {
58
58
  console.error(`❌ tasks.md not found: ${tasksPath}`);
59
59
  process.exit(1);
60
60
  }
@@ -0,0 +1,182 @@
1
+ import { promises as fsPromises, existsSync, mkdirSync, readFileSync, writeFileSync, statSync, readdirSync, rmSync, unlinkSync, copyFileSync } from "fs";
2
+ import path from "path";
3
+ async function ensureDir(dirPath) {
4
+ if (!existsSync(dirPath)) {
5
+ await fsPromises.mkdir(dirPath, { recursive: true });
6
+ }
7
+ }
8
+ function ensureDirSync(dirPath) {
9
+ if (!existsSync(dirPath)) {
10
+ mkdirSync(dirPath, { recursive: true });
11
+ }
12
+ }
13
+ function mkdirpSync(dirPath) {
14
+ ensureDirSync(dirPath);
15
+ }
16
+ async function pathExists(filePath) {
17
+ return existsSync(filePath);
18
+ }
19
+ async function readJson(filePath) {
20
+ const content = await fsPromises.readFile(filePath, "utf-8");
21
+ return JSON.parse(content);
22
+ }
23
+ function readJsonSync(filePath) {
24
+ const content = readFileSync(filePath, "utf-8");
25
+ return JSON.parse(content);
26
+ }
27
+ async function writeJson(filePath, data, options) {
28
+ const spaces = options?.spaces ?? 2;
29
+ const content = JSON.stringify(data, null, spaces);
30
+ await fsPromises.writeFile(filePath, content, "utf-8");
31
+ }
32
+ function writeJsonSync(filePath, data, options) {
33
+ const spaces = options?.spaces ?? 2;
34
+ const content = JSON.stringify(data, null, spaces);
35
+ writeFileSync(filePath, content, "utf-8");
36
+ }
37
+ async function remove(targetPath) {
38
+ if (existsSync(targetPath)) {
39
+ await fsPromises.rm(targetPath, { recursive: true, force: true });
40
+ }
41
+ }
42
+ function removeSync(targetPath) {
43
+ if (existsSync(targetPath)) {
44
+ rmSync(targetPath, { recursive: true, force: true });
45
+ }
46
+ }
47
+ async function copy(src, dest, options) {
48
+ const srcStat = await fsPromises.stat(src);
49
+ if (srcStat.isFile()) {
50
+ await fsPromises.mkdir(path.dirname(dest), { recursive: true });
51
+ await fsPromises.copyFile(src, dest);
52
+ } else if (srcStat.isDirectory()) {
53
+ await fsPromises.mkdir(dest, { recursive: true });
54
+ const entries = await fsPromises.readdir(src, { withFileTypes: true });
55
+ for (const entry of entries) {
56
+ const srcPath = path.join(src, entry.name);
57
+ const destPath = path.join(dest, entry.name);
58
+ if (options?.filter && !options.filter(srcPath)) {
59
+ continue;
60
+ }
61
+ if (entry.isDirectory()) {
62
+ await copy(srcPath, destPath, options);
63
+ } else {
64
+ await fsPromises.copyFile(srcPath, destPath);
65
+ }
66
+ }
67
+ }
68
+ }
69
+ function copySync(src, dest, options) {
70
+ const srcStat = statSync(src);
71
+ if (srcStat.isFile()) {
72
+ mkdirSync(path.dirname(dest), { recursive: true });
73
+ copyFileSync(src, dest);
74
+ } else if (srcStat.isDirectory()) {
75
+ mkdirSync(dest, { recursive: true });
76
+ const entries = readdirSync(src, { withFileTypes: true });
77
+ for (const entry of entries) {
78
+ const srcPath = path.join(src, entry.name);
79
+ const destPath = path.join(dest, entry.name);
80
+ if (options?.filter && !options.filter(srcPath)) {
81
+ continue;
82
+ }
83
+ if (entry.isDirectory()) {
84
+ copySync(srcPath, destPath, options);
85
+ } else {
86
+ copyFileSync(srcPath, destPath);
87
+ }
88
+ }
89
+ }
90
+ }
91
+ async function ensureFile(filePath) {
92
+ if (!existsSync(filePath)) {
93
+ await fsPromises.mkdir(path.dirname(filePath), { recursive: true });
94
+ await fsPromises.writeFile(filePath, "", "utf-8");
95
+ }
96
+ }
97
+ function ensureFileSync(filePath) {
98
+ if (!existsSync(filePath)) {
99
+ mkdirSync(path.dirname(filePath), { recursive: true });
100
+ writeFileSync(filePath, "", "utf-8");
101
+ }
102
+ }
103
+ const {
104
+ readFile,
105
+ writeFile,
106
+ appendFile,
107
+ stat,
108
+ readdir,
109
+ access,
110
+ unlink,
111
+ rmdir,
112
+ rename,
113
+ chmod
114
+ } = fsPromises;
115
+ var fs_native_default = {
116
+ // Async methods
117
+ ensureDir,
118
+ pathExists,
119
+ readJson,
120
+ writeJson,
121
+ remove,
122
+ copy,
123
+ ensureFile,
124
+ readFile,
125
+ writeFile,
126
+ appendFile,
127
+ stat,
128
+ readdir,
129
+ access,
130
+ unlink,
131
+ // Sync methods
132
+ ensureDirSync,
133
+ mkdirpSync,
134
+ existsSync,
135
+ readJsonSync,
136
+ writeJsonSync,
137
+ removeSync,
138
+ copySync,
139
+ ensureFileSync,
140
+ readFileSync,
141
+ writeFileSync,
142
+ statSync,
143
+ readdirSync,
144
+ unlinkSync,
145
+ mkdirSync,
146
+ rmSync
147
+ };
148
+ export {
149
+ access,
150
+ appendFile,
151
+ chmod,
152
+ copy,
153
+ copySync,
154
+ fs_native_default as default,
155
+ ensureDir,
156
+ ensureDirSync,
157
+ ensureFile,
158
+ ensureFileSync,
159
+ existsSync,
160
+ mkdirSync,
161
+ mkdirpSync,
162
+ pathExists,
163
+ readFile,
164
+ readFileSync,
165
+ readJson,
166
+ readJsonSync,
167
+ readdir,
168
+ readdirSync,
169
+ remove,
170
+ removeSync,
171
+ rename,
172
+ rmSync,
173
+ rmdir,
174
+ stat,
175
+ statSync,
176
+ unlink,
177
+ unlinkSync,
178
+ writeFile,
179
+ writeFileSync,
180
+ writeJson,
181
+ writeJsonSync
182
+ };