@pixpilot/scaffoldfy 0.13.0 → 0.16.0
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/README.md +19 -0
- package/dist/cli.cjs +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +1 -1
- package/dist/src-BFNl4oPQ.js +17 -0
- package/dist/src-DERXEoos.cjs +17 -0
- package/package.json +2 -2
- package/schema/tasks.schema.json +17 -0
- package/dist/src-1wb6PUAF.js +0 -17
- package/dist/src-BP7X1T83.cjs +0 -17
package/README.md
CHANGED
|
@@ -44,6 +44,25 @@ scaffoldfy --dry-run
|
|
|
44
44
|
scaffoldfy --force
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
Or run without installing using npx:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
# Basic usage with default task file
|
|
51
|
+
npx @pixpilot/scaffoldfy
|
|
52
|
+
|
|
53
|
+
# With custom tasks file
|
|
54
|
+
npx @pixpilot/scaffoldfy --tasks-file ./my-tasks.json
|
|
55
|
+
|
|
56
|
+
# TypeScript tasks file
|
|
57
|
+
npx @pixpilot/scaffoldfy --tasks-ts ./my-tasks.ts
|
|
58
|
+
|
|
59
|
+
# Preview changes (dry run)
|
|
60
|
+
npx @pixpilot/scaffoldfy --dry-run
|
|
61
|
+
|
|
62
|
+
# Force re-initialization
|
|
63
|
+
npx @pixpilot/scaffoldfy --force
|
|
64
|
+
```
|
|
65
|
+
|
|
47
66
|
### CLI Options
|
|
48
67
|
|
|
49
68
|
| Option | Description |
|
package/dist/cli.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const e=require(`./src-
|
|
2
|
+
const e=require(`./src-DERXEoos.cjs`);let t=require(`node:fs`);t=e.X(t);let n=require(`node:path`);n=e.X(n);let r=require(`node:process`);r=e.X(r);let i=require(`commander`);i=e.X(i);const a=1,o=new i.Command,s=n.default.join(__dirname,`..`,`package.json`);let c=`0.0.0`;try{c=JSON.parse(t.default.readFileSync(s,`utf-8`)).version??`0.0.0`}catch{}o.name(`scaffoldfy`).description(`Automate project setup and configuration with customizable tasks`).version(c),o.option(`--dry-run`,`Run in dry mode without making any changes`).option(`--force`,`Force execution even if checks fail`).option(`--tasks-file <path>`,`Path to JSON file containing task definitions`,`./template-tasks.json`).option(`--tasks-ts <path>`,`Path to TypeScript file exporting tasks`,`./template-tasks.ts`).action(async i=>{try{let a=[],o,s,c;if(i.tasksTs!=null&&i.tasksTs!==``){let o=n.default.resolve(r.default.cwd(),i.tasksTs);if(t.default.existsSync(o)){e.K(`Loading tasks from TypeScript file: ${i.tasksTs}`,`info`),c=o;try{let t=await import(o);a=t.default??t.tasks??[],(!Array.isArray(a)||a.length===0)&&(e.K(`⚠️ No tasks found in TypeScript file or invalid format`,`warn`),e.K(`Expected default export or named export "tasks" with TaskDefinition[]`,`info`))}catch(t){e.K(`Failed to load TypeScript tasks file: ${i.tasksTs}`,`error`),t instanceof Error&&e.K(` Error: ${t.message}`,`error`),r.default.exit(1)}}}if(a.length===0&&i.tasksFile!=null&&i.tasksFile!==``){let l=n.default.resolve(r.default.cwd(),i.tasksFile);if(t.default.existsSync(l)){c=l;try{let t=await e.p(l);a=t.tasks,o=t.variables,s=t.prompts,Array.isArray(a)||(e.K(`❌ Invalid tasks file format`,`error`),e.K(`Expected JSON with { "tasks": [...] } structure`,`info`),r.default.exit(1))}catch(t){e.K(`Failed to load JSON tasks file: ${i.tasksFile}`,`error`),t instanceof Error&&e.K(` Error: ${t.message}`,`error`),r.default.exit(1)}}else e.K(`Tasks file not found: ${i.tasksFile}`,`warn`)}let l=s!=null&&s.length>0||o!=null&&o.length>0;a.length===0&&!l&&(e.K(`❌ No tasks defined`,`error`),e.K(`Please provide tasks using one of these methods:`,`info`),e.K(` 1. Create a template-tasks.json file in the current directory`,`info`),e.K(` 2. Create a template-tasks.ts file in the current directory`,`info`),e.K(` 3. Use --tasks-file option to specify a different JSON file`,`info`),e.K(` 4. Use --tasks-ts option to specify a different TypeScript file`,`info`),e.K(`Example JSON structure:`,`info`),console.log(JSON.stringify({tasks:[{id:`update-package`,name:`Update package.json`,description:`Update package.json with repository information`,required:!0,enabled:!0,type:`update-json`,prompts:[{id:`projectName`,type:`input`,message:`What is your project name?`,default:`my-project`,required:!0},{id:`includeTests`,type:`confirm`,message:`Include test files?`,default:!0}],config:{file:`package.json`,updates:{name:`{{projectName}}`,author:`{{author}}`}}}]},null,2)),r.default.exit(1)),a.length===0?e.K(`Loaded template with 0 tasks (template may only provide prompts/variables for extending)`,`info`):e.K(`Loaded ${a.length} task(s)`,`success`),await e.n(a,{dryRun:i.dryRun,force:i.force,tasksFilePath:c,globalVariables:o,globalPrompts:s})}catch(t){if(e.K(`❌ CLI execution failed`,`error`),t instanceof Error){e.K(`Error: ${t.message}`,`error`);let n=r.default.env.DEBUG;n!=null&&n!==``&&console.error(t.stack)}else console.error(t);r.default.exit(1)}}),o.parse(r.default.argv);
|
package/dist/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{K as e,n as t,p as n}from"./src-BFNl4oPQ.js";import r from"node:path";import{fileURLToPath as i}from"node:url";import a from"node:fs";import o from"node:process";import{Command as s}from"commander";const c=()=>i(import.meta.url),l=(()=>r.dirname(c()))(),u=new s,d=r.join(l,`..`,`package.json`);let f=`0.0.0`;try{f=JSON.parse(a.readFileSync(d,`utf-8`)).version??`0.0.0`}catch{}u.name(`scaffoldfy`).description(`Automate project setup and configuration with customizable tasks`).version(f),u.option(`--dry-run`,`Run in dry mode without making any changes`).option(`--force`,`Force execution even if checks fail`).option(`--tasks-file <path>`,`Path to JSON file containing task definitions`,`./template-tasks.json`).option(`--tasks-ts <path>`,`Path to TypeScript file exporting tasks`,`./template-tasks.ts`).action(async i=>{try{let s=[],c,l,u;if(i.tasksTs!=null&&i.tasksTs!==``){let t=r.resolve(o.cwd(),i.tasksTs);if(a.existsSync(t)){e(`Loading tasks from TypeScript file: ${i.tasksTs}`,`info`),u=t;try{let n=await import(t);s=n.default??n.tasks??[],(!Array.isArray(s)||s.length===0)&&(e(`⚠️ No tasks found in TypeScript file or invalid format`,`warn`),e(`Expected default export or named export "tasks" with TaskDefinition[]`,`info`))}catch(t){e(`Failed to load TypeScript tasks file: ${i.tasksTs}`,`error`),t instanceof Error&&e(` Error: ${t.message}`,`error`),o.exit(1)}}}if(s.length===0&&i.tasksFile!=null&&i.tasksFile!==``){let t=r.resolve(o.cwd(),i.tasksFile);if(a.existsSync(t)){u=t;try{let r=await n(t);s=r.tasks,c=r.variables,l=r.prompts,Array.isArray(s)||(e(`❌ Invalid tasks file format`,`error`),e(`Expected JSON with { "tasks": [...] } structure`,`info`),o.exit(1))}catch(t){e(`Failed to load JSON tasks file: ${i.tasksFile}`,`error`),t instanceof Error&&e(` Error: ${t.message}`,`error`),o.exit(1)}}else e(`Tasks file not found: ${i.tasksFile}`,`warn`)}let d=l!=null&&l.length>0||c!=null&&c.length>0;s.length===0&&!d&&(e(`❌ No tasks defined`,`error`),e(`Please provide tasks using one of these methods:`,`info`),e(` 1. Create a template-tasks.json file in the current directory`,`info`),e(` 2. Create a template-tasks.ts file in the current directory`,`info`),e(` 3. Use --tasks-file option to specify a different JSON file`,`info`),e(` 4. Use --tasks-ts option to specify a different TypeScript file`,`info`),e(`Example JSON structure:`,`info`),console.log(JSON.stringify({tasks:[{id:`update-package`,name:`Update package.json`,description:`Update package.json with repository information`,required:!0,enabled:!0,type:`update-json`,prompts:[{id:`projectName`,type:`input`,message:`What is your project name?`,default:`my-project`,required:!0},{id:`includeTests`,type:`confirm`,message:`Include test files?`,default:!0}],config:{file:`package.json`,updates:{name:`{{projectName}}`,author:`{{author}}`}}}]},null,2)),o.exit(1)),s.length===0?e(`Loaded template with 0 tasks (template may only provide prompts/variables for extending)`,`info`):e(`Loaded ${s.length} task(s)`,`success`),await t(s,{dryRun:i.dryRun,force:i.force,tasksFilePath:u,globalVariables:c,globalPrompts:l})}catch(t){if(e(`❌ CLI execution failed`,`error`),t instanceof Error){e(`Error: ${t.message}`,`error`);let n=o.env.DEBUG;n!=null&&n!==``&&console.error(t.stack)}else console.error(t);o.exit(1)}}),u.parse(o.argv);export{};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`./src-
|
|
1
|
+
const e=require(`./src-DERXEoos.cjs`);exports.callHook=e.b,exports.clearPlugins=e.x,exports.clearTemplateCache=e.d,exports.collectPrompts=e.y,exports.collectVariables=e.o,exports.createPlugin=e.S,exports.displayTasksDiff=e.N,exports.evaluateCondition=e.U,exports.executePluginTask=e.C,exports.executeTask=e.c,exports.getDeleteDiff=e.P,exports.getExecDiff=e.F,exports.getGitInitDiff=e.I,exports.getGitRepoInfo=e.W,exports.getPlugin=e.w,exports.getPluginForTaskType=e.T,exports.getPluginTaskDiff=e.E,exports.getRegexReplaceDiff=e.L,exports.getRenameDiff=e.R,exports.getReplaceInFileDiff=e.z,exports.getTaskDiff=e.B,exports.getTemplateDiff=e.V,exports.getUpdateJsonDiff=e.H,exports.interpolateTemplate=e.G,exports.isPluginTaskType=e.D,exports.listPlugins=e.O,exports.loadAndMergeTemplate=e.f,exports.loadTasksWithInheritance=e.p,exports.loadTemplate=e.m,exports.log=e.K,exports.main=e.t,exports.mergeTemplates=e.h,exports.prompt=e.q,exports.promptYesNo=e.J,exports.registerBuiltInPlugins=e.l,exports.registerHooks=e.k,exports.registerPlugin=e.A,exports.resolveAllDefaultValues=e._,exports.resolveAllVariableValues=e.i,exports.resolveDefaultValue=e.v,exports.resolveVariableValue=e.a,exports.runTask=e.u,exports.runWithTasks=e.n,exports.setNestedProperty=e.Y,exports.topologicalSort=e.s,exports.unregisterPlugin=e.j,exports.validatePluginTask=e.M,exports.validatePrompts=e.g,exports.validateVariables=e.r;
|
package/dist/index.d.cts
CHANGED
|
@@ -190,6 +190,9 @@ interface TaskDefinition {
|
|
|
190
190
|
* Configuration file structure for template tasks
|
|
191
191
|
*/
|
|
192
192
|
interface TasksConfiguration {
|
|
193
|
+
name: string;
|
|
194
|
+
description?: string;
|
|
195
|
+
dependencies?: string[];
|
|
193
196
|
extends?: string | string[];
|
|
194
197
|
variables?: VariableDefinition[];
|
|
195
198
|
prompts?: PromptDefinition[];
|
|
@@ -404,6 +407,7 @@ declare function resolveDefaultValue<T = string | number | boolean>(defaultValue
|
|
|
404
407
|
declare function validatePrompts(prompts: PromptDefinition[]): string[];
|
|
405
408
|
//#endregion
|
|
406
409
|
//#region src/task-executors.d.ts
|
|
410
|
+
declare function registerBuiltInPlugins(): void;
|
|
407
411
|
/**
|
|
408
412
|
* Execute a task based on its type
|
|
409
413
|
*/
|
|
@@ -552,4 +556,4 @@ declare function runWithTasks(customTasks: TaskDefinition[], options?: {
|
|
|
552
556
|
globalPrompts?: PromptDefinition[] | undefined;
|
|
553
557
|
}): Promise<void>;
|
|
554
558
|
//#endregion
|
|
555
|
-
export { BasePrompt, ConditionExpression, ConditionalEnabled, ConfirmPrompt, type CreateConfig, DefaultValue, DefaultValueConfig, DefaultValueType, type DeleteConfig, EnabledValue, type ExecConfig, type GitInitConfig, InitConfig, InputPrompt, MergeStrategy, NumberPrompt, PluginHooks, PromptDefinition, PromptType, type RegexReplaceConfig, type RenameConfig, type ReplaceInFileConfig, RollbackConfig, SelectPrompt, TaskDefinition, TaskPlugin, TaskType, TasksConfiguration, type TemplateConfig, type UpdateJsonConfig, VariableDefinition, callHook, clearPlugins, clearTemplateCache, collectPrompts, collectVariables, createPlugin, displayTasksDiff, evaluateCondition, executePluginTask, executeTask, getDeleteDiff, getExecDiff, getGitInitDiff, getGitRepoInfo, getPlugin, getPluginForTaskType, getPluginTaskDiff, getRegexReplaceDiff, getRenameDiff, getReplaceInFileDiff, getTaskDiff, getTemplateDiff, getUpdateJsonDiff, interpolateTemplate, isPluginTaskType, listPlugins, loadAndMergeTemplate, loadTasksWithInheritance, loadTemplate, log, main, mergeTemplates, prompt, promptYesNo, registerHooks, registerPlugin, resolveAllDefaultValues, resolveAllVariableValues, resolveDefaultValue, resolveVariableValue, runTask, runWithTasks, setNestedProperty, topologicalSort, unregisterPlugin, validatePluginTask, validatePrompts, validateVariables };
|
|
559
|
+
export { BasePrompt, ConditionExpression, ConditionalEnabled, ConfirmPrompt, type CreateConfig, DefaultValue, DefaultValueConfig, DefaultValueType, type DeleteConfig, EnabledValue, type ExecConfig, type GitInitConfig, InitConfig, InputPrompt, MergeStrategy, NumberPrompt, PluginHooks, PromptDefinition, PromptType, type RegexReplaceConfig, type RenameConfig, type ReplaceInFileConfig, RollbackConfig, SelectPrompt, TaskDefinition, TaskPlugin, TaskType, TasksConfiguration, type TemplateConfig, type UpdateJsonConfig, VariableDefinition, callHook, clearPlugins, clearTemplateCache, collectPrompts, collectVariables, createPlugin, displayTasksDiff, evaluateCondition, executePluginTask, executeTask, getDeleteDiff, getExecDiff, getGitInitDiff, getGitRepoInfo, getPlugin, getPluginForTaskType, getPluginTaskDiff, getRegexReplaceDiff, getRenameDiff, getReplaceInFileDiff, getTaskDiff, getTemplateDiff, getUpdateJsonDiff, interpolateTemplate, isPluginTaskType, listPlugins, loadAndMergeTemplate, loadTasksWithInheritance, loadTemplate, log, main, mergeTemplates, prompt, promptYesNo, registerBuiltInPlugins, registerHooks, registerPlugin, resolveAllDefaultValues, resolveAllVariableValues, resolveDefaultValue, resolveVariableValue, runTask, runWithTasks, setNestedProperty, topologicalSort, unregisterPlugin, validatePluginTask, validatePrompts, validateVariables };
|
package/dist/index.d.ts
CHANGED
|
@@ -190,6 +190,9 @@ interface TaskDefinition {
|
|
|
190
190
|
* Configuration file structure for template tasks
|
|
191
191
|
*/
|
|
192
192
|
interface TasksConfiguration {
|
|
193
|
+
name: string;
|
|
194
|
+
description?: string;
|
|
195
|
+
dependencies?: string[];
|
|
193
196
|
extends?: string | string[];
|
|
194
197
|
variables?: VariableDefinition[];
|
|
195
198
|
prompts?: PromptDefinition[];
|
|
@@ -404,6 +407,7 @@ declare function resolveDefaultValue<T = string | number | boolean>(defaultValue
|
|
|
404
407
|
declare function validatePrompts(prompts: PromptDefinition[]): string[];
|
|
405
408
|
//#endregion
|
|
406
409
|
//#region src/task-executors.d.ts
|
|
410
|
+
declare function registerBuiltInPlugins(): void;
|
|
407
411
|
/**
|
|
408
412
|
* Execute a task based on its type
|
|
409
413
|
*/
|
|
@@ -552,4 +556,4 @@ declare function runWithTasks(customTasks: TaskDefinition[], options?: {
|
|
|
552
556
|
globalPrompts?: PromptDefinition[] | undefined;
|
|
553
557
|
}): Promise<void>;
|
|
554
558
|
//#endregion
|
|
555
|
-
export { BasePrompt, ConditionExpression, ConditionalEnabled, ConfirmPrompt, type CreateConfig, DefaultValue, DefaultValueConfig, DefaultValueType, type DeleteConfig, EnabledValue, type ExecConfig, type GitInitConfig, InitConfig, InputPrompt, MergeStrategy, NumberPrompt, PluginHooks, PromptDefinition, PromptType, type RegexReplaceConfig, type RenameConfig, type ReplaceInFileConfig, RollbackConfig, SelectPrompt, TaskDefinition, TaskPlugin, TaskType, TasksConfiguration, type TemplateConfig, type UpdateJsonConfig, VariableDefinition, callHook, clearPlugins, clearTemplateCache, collectPrompts, collectVariables, createPlugin, displayTasksDiff, evaluateCondition, executePluginTask, executeTask, getDeleteDiff, getExecDiff, getGitInitDiff, getGitRepoInfo, getPlugin, getPluginForTaskType, getPluginTaskDiff, getRegexReplaceDiff, getRenameDiff, getReplaceInFileDiff, getTaskDiff, getTemplateDiff, getUpdateJsonDiff, interpolateTemplate, isPluginTaskType, listPlugins, loadAndMergeTemplate, loadTasksWithInheritance, loadTemplate, log, main, mergeTemplates, prompt, promptYesNo, registerHooks, registerPlugin, resolveAllDefaultValues, resolveAllVariableValues, resolveDefaultValue, resolveVariableValue, runTask, runWithTasks, setNestedProperty, topologicalSort, unregisterPlugin, validatePluginTask, validatePrompts, validateVariables };
|
|
559
|
+
export { BasePrompt, ConditionExpression, ConditionalEnabled, ConfirmPrompt, type CreateConfig, DefaultValue, DefaultValueConfig, DefaultValueType, type DeleteConfig, EnabledValue, type ExecConfig, type GitInitConfig, InitConfig, InputPrompt, MergeStrategy, NumberPrompt, PluginHooks, PromptDefinition, PromptType, type RegexReplaceConfig, type RenameConfig, type ReplaceInFileConfig, RollbackConfig, SelectPrompt, TaskDefinition, TaskPlugin, TaskType, TasksConfiguration, type TemplateConfig, type UpdateJsonConfig, VariableDefinition, callHook, clearPlugins, clearTemplateCache, collectPrompts, collectVariables, createPlugin, displayTasksDiff, evaluateCondition, executePluginTask, executeTask, getDeleteDiff, getExecDiff, getGitInitDiff, getGitRepoInfo, getPlugin, getPluginForTaskType, getPluginTaskDiff, getRegexReplaceDiff, getRenameDiff, getReplaceInFileDiff, getTaskDiff, getTemplateDiff, getUpdateJsonDiff, interpolateTemplate, isPluginTaskType, listPlugins, loadAndMergeTemplate, loadTasksWithInheritance, loadTemplate, log, main, mergeTemplates, prompt, promptYesNo, registerBuiltInPlugins, registerHooks, registerPlugin, resolveAllDefaultValues, resolveAllVariableValues, resolveDefaultValue, resolveVariableValue, runTask, runWithTasks, setNestedProperty, topologicalSort, unregisterPlugin, validatePluginTask, validatePrompts, validateVariables };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as e,B as t,C as n,D as r,E as i,F as a,G as o,H as s,I as c,J as l,K as u,L as d,M as f,N as p,O as m,P as h,R as g,S as _,T as v,U as y,V as b,W as x,
|
|
1
|
+
import{A as e,B as t,C as n,D as r,E as i,F as a,G as o,H as s,I as c,J as l,K as u,L as d,M as f,N as p,O as m,P as h,R as g,S as _,T as v,U as y,V as b,W as x,Y as S,_ as C,a as w,b as T,c as E,d as D,f as O,g as k,h as A,i as j,j as M,k as N,l as P,m as F,n as I,o as L,p as R,q as z,r as B,s as V,t as H,u as U,v as W,w as G,x as K,y as q,z as J}from"./src-BFNl4oPQ.js";export{T as callHook,K as clearPlugins,D as clearTemplateCache,q as collectPrompts,L as collectVariables,_ as createPlugin,p as displayTasksDiff,y as evaluateCondition,n as executePluginTask,E as executeTask,h as getDeleteDiff,a as getExecDiff,c as getGitInitDiff,x as getGitRepoInfo,G as getPlugin,v as getPluginForTaskType,i as getPluginTaskDiff,d as getRegexReplaceDiff,g as getRenameDiff,J as getReplaceInFileDiff,t as getTaskDiff,b as getTemplateDiff,s as getUpdateJsonDiff,o as interpolateTemplate,r as isPluginTaskType,m as listPlugins,O as loadAndMergeTemplate,R as loadTasksWithInheritance,F as loadTemplate,u as log,H as main,A as mergeTemplates,z as prompt,l as promptYesNo,P as registerBuiltInPlugins,N as registerHooks,e as registerPlugin,C as resolveAllDefaultValues,j as resolveAllVariableValues,W as resolveDefaultValue,w as resolveVariableValue,U as runTask,I as runWithTasks,S as setNestedProperty,V as topologicalSort,M as unregisterPlugin,f as validatePluginTask,k as validatePrompts,B as validateVariables};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import e from"node:path";import t from"node:fs";import n from"node:process";import{promisify as r}from"node:util";import{execSync as i}from"node:child_process";import a from"node:readline";import o from"handlebars";import{confirm as s,input as c,number as l,password as u,select as d}from"@inquirer/prompts";function ee(){return{}}var f=class extends Error{constructor(e,t){super(e),this.code=t,this.name=this.constructor.name}},p=class e extends f{constructor(e,t,n){super(e,`CIRCULAR_DEPENDENCY`),this.dependencyChain=t,this.resolvedPath=n,this.name=`CircularDependencyError`}static forTemplateInheritance(t,n){let r=Array.from(t);return new e(`Circular dependency detected: ${r.join(` -> `)} -> ${n}`,r,n)}static forTaskDependency(t){return new e(`Circular dependency detected involving task: ${t}`,[t])}},m=class e extends f{constructor(e,t){super(e,`TEMPLATE_FILE_NOT_FOUND`),this.filePath=t,this.name=`TemplateFileNotFoundError`}static forPath(t){return new e(`Template file not found: ${t}`,t)}},h=class e extends f{constructor(e,t,n){super(e,`TEMPLATE_RESOLUTION_ERROR`),this.templateFilePath=t,this.sourceUrl=n,this.name=`TemplateResolutionError`}static forRemoteTemplate(t,n){return new e(`Failed to resolve templateFile "${t}" relative to remote template "${n}"`,t,n)}},g=class e extends f{constructor(e,t,n){super(e,`TEMPLATE_FETCH_ERROR`),this.url=t,this.originalError=n,this.name=`TemplateFetchError`}static forUrl(t,n,r){return typeof n==`number`?new e(`Failed to fetch template from ${t}: ${n} ${r??``}`.trim(),t):new e(`Failed to fetch template from ${t}: ${n?.message??String(n??`Unknown error`)}`,t,n)}},te=class e extends f{constructor(e,t,n){super(e,`TEMPLATE_PARSE_ERROR`),this.filePath=t,this.originalError=n,this.name=`TemplateParseError`}static forFile(t,n){return new e(`Failed to parse template file ${t}: ${n.message}`,t,n)}},_=class e extends f{constructor(e,t){super(e,`INVALID_TEMPLATE`),this.filePath=t,this.name=`InvalidTemplateError`}static forFile(t,n){return new e(`Invalid template file ${t}: ${n}`,t)}static tasksNotArray(t){return new e(`Invalid template file ${t}: 'tasks' must be an array if provided`,t)}static missingName(t){return new e(`Invalid template file ${t}: 'name' field is required`,t)}static invalidNameFormat(t,n){return new e(`Invalid template file ${t}: 'name' field "${n}" must contain only lowercase letters, digits, and hyphens. It cannot start or end with a hyphen, and cannot contain consecutive hyphens.`,t)}};function v(e,t){return e===void 0?!0:typeof e==`boolean`?e:typeof e==`object`&&`condition`in e?S(e.condition,t):!1}function ne(){try{let e=i(`git remote get-url origin`,{encoding:`utf-8`}).trim(),t=e.match(/github\.com[:/](?<owner>[^/]+)\/(?<name>[^/]+)$/u);if(t?.groups){let{owner:n,name:r}=t.groups,i=r;return i.endsWith(`.git`)&&(i=i.slice(0,-4)),{owner:n,name:i,url:e}}return null}catch{return null}}async function re(e,t){let r=a.createInterface({input:n.stdin,output:n.stdout});return new Promise(n=>{let i;i=t==null?`${e}: `:`${e} (${t}): `,r.question(i,e=>{r.close(),n(e.trim()||(t??``))})})}async function ie(e,t=!1){return re(`${e} (${t?`Y/n`:`y/N`})`,t?`y`:`n`).then(e=>e.toLowerCase()===`y`||e.toLowerCase()===`yes`)}function y(e,t=`info`){console.log(`${{info:`\x1B[36m`,success:`\x1B[32m`,error:`\x1B[31m`,warn:`\x1B[33m`}[t]}${{info:`ℹ`,success:`✓`,error:`✗`,warn:`⚠`}[t]} ${e}[0m`)}function b(e,t){return e.replace(/\{\{(?<key>\w+)\}\}/gu,(e,n)=>t[n]?.toString()??``)}function x(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++){let t=r[e];t!=null&&t!==``&&((!(t in i)||typeof i[t]!=`object`||i[t]===null)&&(i[t]={}),i=i[t])}let a=r[r.length-1];a!=null&&a!==``&&(i[a]=n)}function S(e,t){try{let n={...t};return Function(...Object.keys(n),`'use strict'; return (${e})`)(...Object.values(n))}catch(t){return y(`Failed to evaluate condition: ${e}`,`warn`),t instanceof Error&&y(` Error: ${t.message}`,`warn`),!1}}function ae(r,i){try{let a=e.isAbsolute(r)?r:e.join(n.cwd(),r);if(!t.existsSync(a))throw m.forPath(r);return oe(t.readFileSync(a,`utf-8`),i)}catch(e){throw y(`Failed to read template file: ${r}`,`error`),e instanceof Error&&y(` Error: ${e.message}`,`error`),e}}function oe(e,t){try{return o.compile(e)(t)}catch(e){throw y(`Failed to compile Handlebars template`,`error`),e instanceof Error&&y(` Error: ${e.message}`,`error`),e}}const C=r(t.readFile),w={reset:`\x1B[0m`,red:`\x1B[31m`,green:`\x1B[32m`,yellow:`\x1B[33m`,blue:`\x1B[34m`,cyan:`\x1B[36m`,gray:`\x1B[90m`};function T(e,t){switch(t){case`add`:return`${w.green}+ ${e}${w.reset}`;case`remove`:return`${w.red}- ${e}${w.reset}`;case`context`:return`${w.gray} ${e}${w.reset}`;default:return e}}function E(e,t){let n=e.split(`
|
|
2
|
+
`),r=t.split(`
|
|
3
|
+
`),i=[],a=Math.max(n.length,r.length);for(let e=0;e<a;e++){let t=n[e],a=r[e];t===a?t!==void 0&&i.push(T(t,`context`)):(t!==void 0&&i.push(T(t,`remove`)),a!==void 0&&i.push(T(a,`add`)))}return i}async function D(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let a=e.join(n.cwd(),r.file);if(!t.existsSync(a))return`${w.red}✗ File not found: ${r.file}${w.reset}`;try{let e=await C(a,`utf-8`),t=JSON.parse(e),n={...t};function o(e){if(typeof e==`string`)return b(e,i);if(Array.isArray(e))return e.map(e=>o(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=o(r);return t}return e}for(let[e,n]of Object.entries(r.updates)){let r=o(n);e.includes(`.`)?x(t,e,r):t[e]=r}let s=JSON.stringify(n,null,2),c=JSON.stringify(t,null,2);if(s===c)return`${w.cyan}→ No changes${w.reset}`;let l=E(s,c);return`${w.blue}File: ${r.file}${w.reset}\n${l.join(`
|
|
4
|
+
`)}`}catch(e){return`${w.red}✗ Error: ${e instanceof Error?e.message:String(e)}${w.reset}`}}async function se(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;if(r.template==null||r.template===``)return`${w.red}✗ No template content provided for file: ${r.file}${w.reset}`;let a=e.join(n.cwd(),r.file),o=b(r.template,i);if(!t.existsSync(a)){let e=o.split(`
|
|
5
|
+
`).slice(0,10).join(`
|
|
6
|
+
`),t=o.split(`
|
|
7
|
+
`).length>10;return`${w.blue}File: ${r.file}${w.reset}\n${w.green}+ New file would be created${w.reset}\n${w.gray}Content preview:${w.reset}\n${e}${t?`
|
|
8
|
+
...`:``}`}try{let e=await C(a,`utf-8`);if(e===o)return`${w.cyan}→ No changes${w.reset}`;let t=E(e,o);return`${w.blue}File: ${r.file}${w.reset}\n${t.join(`
|
|
9
|
+
`)}`}catch(e){return`${w.red}✗ Error: ${e instanceof Error?e.message:String(e)}${w.reset}`}}async function ce(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let a=e.join(n.cwd(),r.file);if(t.existsSync(a))return`${w.cyan}→ File already exists, would be skipped: ${r.file}${w.reset}`;let o=r.template!=null&&r.template!==``,s=r.templateFile!=null&&r.templateFile!==``;if(!o&&!s)return`${w.red}✗ No template content provided for file: ${r.file}${w.reset}`;try{let e;if(o)e=b(r.template,i);else return`${w.blue}File: ${r.file}${w.reset}\n${w.green}+ New file would be created from template: ${r.templateFile}${w.reset}`;let t=e.split(`
|
|
10
|
+
`).slice(0,10).join(`
|
|
11
|
+
`),n=e.split(`
|
|
12
|
+
`).length>10;return`${w.blue}File: ${r.file}${w.reset}\n${w.green}+ New file would be created${w.reset}\n${w.gray}Content preview:${w.reset}\n${t}${n?`
|
|
13
|
+
...`:``}`}catch(e){return`${w.red}✗ Error: ${e instanceof Error?e.message:String(e)}${w.reset}`}}async function le(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let a=e.join(n.cwd(),r.file);if(!t.existsSync(a))return`${w.red}✗ File not found: ${r.file}${w.reset}`;try{let e=await C(a,`utf-8`),t=new RegExp(r.pattern,r.flags??`g`),n=b(r.replacement,i),o=e.replace(t,n);if(e===o)return`${w.cyan}→ No matches found${w.reset}`;let s=E(e,o);return`${w.blue}File: ${r.file}${w.reset}\n${s.join(`
|
|
14
|
+
`)}`}catch(e){return`${w.red}✗ Error: ${e instanceof Error?e.message:String(e)}${w.reset}`}}async function ue(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let a=e.join(n.cwd(),r.file);if(!t.existsSync(a))return`${w.red}✗ File not found: ${r.file}${w.reset}`;try{let e=await C(a,`utf-8`),t=e;for(let{find:t,replace:n}of r.replacements){let r=b(t,i),a=b(n,i);e=e.replace(r,a)}if(t===e)return`${w.cyan}→ No changes${w.reset}`;let n=E(t,e);return`${w.blue}File: ${r.file}${w.reset}\n${n.join(`
|
|
15
|
+
`)}`}catch(e){return`${w.red}✗ Error: ${e instanceof Error?e.message:String(e)}${w.reset}`}}function de(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let a=r.paths.map(e=>b(e,i)).filter(r=>t.existsSync(e.join(n.cwd(),r)));return a.length===0?`${w.cyan}→ No files/directories to delete${w.reset}`:`${w.red}Would delete:${w.reset}\n${a.map(e=>`${w.red} - ${e}${w.reset}`).join(`
|
|
16
|
+
`)}`}function fe(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let a=b(r.from,i),o=b(r.to,i),s=e.join(n.cwd(),a),c=e.join(n.cwd(),o);return t.existsSync(s)?t.existsSync(c)?`${w.yellow}⚠ Destination already exists: ${o}${w.reset}\n${w.cyan}Would rename: ${a} → ${o}${w.reset}`:`${w.cyan}Would rename: ${a} → ${o}${w.reset}`:`${w.red}✗ Source not found: ${a}${w.reset}`}function O(r){if(r.condition!=null&&r.condition!==``)return`${w.yellow}⊘ Condition check skipped in dry-run${w.reset}`;let i=e.join(n.cwd(),`.git`),a=t.existsSync(i),o=[];if(r.removeExisting&&a&&o.push(`${w.red}Would remove existing .git directory${w.reset}`),o.push(`${w.green}Would initialize git repository${w.reset}`),r.initialCommit){let e=r.message??`Initial commit`;o.push(`${w.green}Would create initial commit: "${e}"${w.reset}`)}return o.join(`
|
|
17
|
+
`)}function k(e,t){if(e.condition!=null&&e.condition!==``&&!S(e.condition,t))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let r=b(e.command,t),i=e.cwd==null?n.cwd():b(e.cwd,t);return`${w.yellow}Would execute:${w.reset}\n${w.cyan} Command: ${r}${w.reset}\n${w.cyan} Working directory: ${i}${w.reset}`}async function A(e,t){try{switch(e.type){case`update-json`:return await D(e.config,t);case`template`:return await se(e.config,t);case`create`:return await ce(e.config,t);case`regex-replace`:return await le(e.config,t);case`replace-in-file`:return await ue(e.config,t);case`delete`:return de(e.config,t);case`rename`:return fe(e.config,t);case`git-init`:return O(e.config);case`exec`:return k(e.config,t);default:{let t=e.type;return`${w.yellow}⚠ Diff not available for task type: ${t}${w.reset}`}}}catch(e){return`${w.red}✗ Error generating diff: ${e instanceof Error?e.message:String(e)}${w.reset}`}}async function j(e,t){console.log(`${w.blue}═══════════════════════════════════════════════════════${w.reset}`),console.log(`${w.blue} DRY RUN - Preview of changes${w.reset}`),console.log(`${w.blue}═══════════════════════════════════════════════════════${w.reset}`);for(let n of e){console.log(`${w.cyan}▶ Task: ${n.name}${w.reset}`),console.log(`${w.gray} ${n.description}${w.reset}`);let e=await A(n,t);console.log(e),console.log(`${w.gray}${`─`.repeat(55)}${w.reset}`)}console.log(`${w.blue}═══════════════════════════════════════════════════════${w.reset}`),console.log(`${w.yellow} No changes were applied (dry-run mode)${w.reset}`),console.log(`${w.blue}═══════════════════════════════════════════════════════${w.reset}`)}const M=new Map,N={},P=new Map;function F(e){if(e.name==null||e.name===``)throw TypeError(`Plugin name is required`);if(!Array.isArray(e.taskTypes)||e.taskTypes.length===0)throw TypeError(`Plugin ${e.name} must define at least one task type`);if(typeof e.execute!=`function`)throw TypeError(`Plugin ${e.name} must provide an execute function`);if(M.has(e.name))throw TypeError(`Plugin ${e.name} is already registered`);for(let t of e.taskTypes)if(P.has(t)){let e=P.get(t);throw TypeError(`Task type "${t}" is already registered by plugin "${e}"`)}M.set(e.name,e);for(let t of e.taskTypes)P.set(t,e.name);y(`✓ Registered plugin: ${e.name}${e.version==null?``:` v${e.version}`}`,`info`)}function pe(e){let t=M.get(e);if(t!=null){for(let e of t.taskTypes)P.delete(e);M.delete(e)}}function me(e){return M.get(e)}function I(e){let t=P.get(e);if(t!=null)return M.get(t)}function L(e){return P.has(e)}function he(){return Array.from(M.keys())}function ge(){M.clear(),P.clear()}function _e(e){e.beforeAll!=null&&(N.beforeAll=e.beforeAll),e.afterAll!=null&&(N.afterAll=e.afterAll),e.beforeTask!=null&&(N.beforeTask=e.beforeTask),e.afterTask!=null&&(N.afterTask=e.afterTask),e.onError!=null&&(N.onError=e.onError)}async function R(e,...t){let n=N[e];if(n!=null)try{e===`beforeAll`||e===`afterAll`?await n(t[0]):(e===`beforeTask`||e===`afterTask`||e===`onError`)&&await n(t[0],t[1])}catch(t){y(`Error in ${e} hook: ${t instanceof Error?t.message:String(t)}`,`error`)}}async function z(e,t,n){let r=I(e.type);if(r==null)throw TypeError(`No plugin found for task type: ${e.type}`);await r.execute(e,t,n)}async function ve(e,t){let n=I(e.type);if(!(n==null||n.getDiff==null))return n.getDiff(e,t)}function ye(e){let t=I(e.type);return t==null?[`No plugin found for task type: ${e.type}`]:t.validate==null?[]:t.validate(e)}function be(e,t,n,r){return{name:e,...r?.version!=null&&{version:r.version},taskTypes:[t],execute:n,...r?.getDiff!=null&&{getDiff:r.getDiff},...r?.validate!=null&&{validate:r.validate}}}var xe=class e extends f{constructor(e,t){super(e,`TASK_NOT_FOUND`),this.taskId=t,this.name=`TaskNotFoundError`}static forId(t){return new e(`Task not found: ${t}`,t)}},B=class e extends f{constructor(e,t,n){super(e,`PROMPT_VALIDATION_ERROR`),this.promptId=t,this.reason=n,this.name=`PromptValidationError`}static required(t){return new e(`Prompt "${t}" is required`,t,`required`)}static unknownType(t){return new e(`Unknown prompt type: ${t}`,t,`unknown_type`)}},V=class e extends f{constructor(e,t,n){super(e,`PLUGIN_CONFIGURATION_ERROR`),this.pluginType=t,this.configIssue=n,this.name=`PluginConfigurationError`}static templateMissingTemplateOrFile(){return new e(`Template task requires either "template" (inline) or "templateFile" (file path) to be specified`,`template`,`missing_template_or_file`)}static templateHasBothTemplateAndFile(){return new e(`Template task cannot have both "template" and "templateFile" specified. Use one or the other.`,`template`,`both_template_and_file`)}static createMissingTemplateOrFile(){return new e(`Create task requires either "template" (inline) or "templateFile" (file path) to be specified`,`create`,`missing_template_or_file`)}static createHasBothTemplateAndFile(){return new e(`Create task cannot have both "template" and "templateFile" specified. Use one or the other.`,`create`,`both_template_and_file`)}};async function H(e,t=new Map,n={}){let r={};if(e.length===0)return r;for(let i of e){let e={...n,...r};if(v(i.enabled,e))try{let e,n=t.get(i.id);switch(i.type){case`input`:{let t={message:i.message};if(n!==void 0&&(t.default=String(n)),i.required!==void 0&&(t.required=i.required),e=await c(t),i.required&&(e==null||typeof e==`string`&&e.trim()===``))throw y(`${i.message} is required`,`error`),B.required(i.id);break}case`password`:if(e=await u({message:i.message,mask:`*`}),i.required&&(e==null||typeof e==`string`&&e.trim()===``))throw y(`${i.message} is required`,`error`),B.required(i.id);break;case`number`:{let t={message:i.message};if(n!==void 0&&(t.default=Number(n)),i.required!==void 0&&(t.required=i.required),i.min!==void 0&&(t.min=i.min),i.max!==void 0&&(t.max=i.max),e=await l(t),i.required&&e==null)throw y(`${i.message} is required`,`error`),B.required(i.id);break}case`select`:{let t={message:i.message,choices:i.choices.map(e=>({name:e.name,value:e.value}))};n!==void 0&&(t.default=n),e=await d(t);break}case`confirm`:{let t=n===void 0?!1:!!n;e=await s({message:i.message,default:t});break}default:throw y(`Unknown prompt type: ${i.type}`,`error`),B.unknownType(i.type)}r[i.id]=e}catch(e){throw e instanceof Error&&y(`Failed to collect prompt "${i.id}": ${e.message}`,`error`),e}}return r}async function U(e,t){if(e===void 0)return;if(typeof e!=`object`||!e||Array.isArray(e))return e;let n=e;if(n.type===`exec`){let e=n.value;if(typeof e!=`string`){y(`Prompt "${t}": exec default value must have a string command`,`error`);return}try{let t=i(e,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:1e4}).trim();if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return t}if(/^-?\d+(?:\.\d+)?$/u.test(t)){let e=Number.parseFloat(t);if(!Number.isNaN(e))return e}return t===`true`||t===`false`?t===`true`:t}catch(e){y(`Prompt "${t}": failed to execute default value command: ${e instanceof Error?e.message:`Unknown error`}`,`warn`);return}}else if(n.type===`static`)return n.value;return e}async function W(e){let t=new Map,n=e.map(async e=>{if(e.default!==void 0){let n=await U(e.default,e.id);n!==void 0&&t.set(e.id,n)}});return await Promise.all(n),t}function G(e){let t=[],n=new Set;for(let r of e){if(n.has(r.id)&&t.push(`Duplicate prompt ID: ${r.id}`),n.add(r.id),/^[\w-]+$/u.test(r.id)||t.push(`Invalid prompt ID "${r.id}": must contain only alphanumeric characters, underscores, and hyphens`),(!r.message||r.message.trim()===``)&&t.push(`Prompt "${r.id}" must have a non-empty message`),r.type===`select`){r.choices.length===0&&t.push(`Select prompt "${r.id}" must have at least one choice`);for(let e of r.choices)(!e.name||e.name.trim()===``)&&t.push(`Select prompt "${r.id}" has a choice with empty name`),e.value===void 0&&t.push(`Select prompt "${r.id}" has a choice with undefined value`)}r.type===`number`&&r.min!==void 0&&r.max!==void 0&&r.min>r.max&&t.push(`Number prompt "${r.id}" has min greater than max`)}return t}const Se=r(t.writeFile);async function Ce(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i)){y(`Condition not met, skipping create task`,`info`);return}let a=e.join(n.cwd(),r.file);if(t.existsSync(a)){y(`File already exists, skipping: ${r.file}`,`info`);return}let o=r.template!=null&&r.template!==``,s=r.templateFile!=null&&r.templateFile!==``;if(!o&&!s)throw V.createMissingTemplateOrFile();if(o&&s)throw V.createHasBothTemplateAndFile();let c;if(s&&r.templateFile.endsWith(`.hbs`))c=ae(r.templateFile,i);else if(s){let a=r.templateFile,o=e.isAbsolute(a)?a:e.join(n.cwd(),a);if(!t.existsSync(o))throw m.forPath(a);c=b(t.readFileSync(o,`utf-8`),i)}else c=b(r.template,i);let l=e.dirname(a);t.existsSync(l)||t.mkdirSync(l,{recursive:!0}),await Se(a,c),y(`Created file: ${r.file}`,`success`)}const we={name:`create`,version:`1.0.0`,taskTypes:[`create`],execute:async(e,t,n)=>{n.dryRun||await Ce(e.config,t)}};async function Te(r,i){let{paths:a,condition:o}=r;if(o!=null&&o!==``){if(!i){y(`Condition specified but no config provided, skipping deletion`,`warn`);return}if(!S(o,i)){y(`Condition not met, skipping deletion`,`info`);return}}for(let r of a){let i=e.join(n.cwd(),r);t.existsSync(i)&&t.rmSync(i,{recursive:!0,force:!0})}}const Ee={name:`delete`,version:`1.0.0`,taskTypes:[`delete`],execute:async(e,t,n)=>{n.dryRun||await Te(e.config,t)}};async function De(t,r){if(t.condition!=null&&t.condition!==``){if(!r){y(`Condition specified but no config provided, skipping exec`,`warn`);return}if(!S(t.condition,r)){y(`Condition not met, skipping exec task`,`info`);return}}let a=t.cwd==null?n.cwd():e.join(n.cwd(),t.cwd);i(t.command,{cwd:a,stdio:`inherit`})}const Oe={name:`exec`,version:`1.0.0`,taskTypes:[`exec`],execute:async(e,t,n)=>{n.dryRun||await De(e.config,t)}};async function ke(r,a){if(r.condition!=null&&r.condition!==``){if(!a){y(`Condition specified but no config provided, skipping git-init`,`warn`);return}if(!S(r.condition,a)){y(`Condition not met, skipping git-init task`,`info`);return}}if(r.removeExisting){let r=e.join(n.cwd(),`.git`);t.existsSync(r)&&t.rmSync(r,{recursive:!0,force:!0})}if(i(`git init`,{stdio:`inherit`}),r.initialCommit){let e=r.message??`Initial commit`;i(`git add .`,{stdio:`inherit`}),i(`git commit -m "${e}"`,{stdio:`inherit`})}}const Ae={name:`git-init`,version:`1.0.0`,taskTypes:[`git-init`],execute:async(e,t,n)=>{n.dryRun||await ke(e.config,t)}},je=r(t.readFile),Me=r(t.writeFile);async function Ne(t,r){if(t.condition!=null&&t.condition!==``&&!S(t.condition,r)){y(`Condition not met, skipping regex-replace task`,`info`);return}let i=e.join(n.cwd(),t.file),{pattern:a}=t,o=t.flags??``,s=t.replacement||``,c=await je(i,`utf-8`),l=new RegExp(a,o);c=c.replace(l,b(s,r)),await Me(i,c)}const Pe={name:`regex-replace`,version:`1.0.0`,taskTypes:[`regex-replace`],execute:async(e,t,n)=>{n.dryRun||await Ne(e.config,t)}},Fe=r(t.rename);async function Ie(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i)){y(`Condition not met, skipping rename task`,`info`);return}let a=e.join(n.cwd(),b(r.from,i)),o=e.join(n.cwd(),b(r.to,i));if(!t.existsSync(a)){y(`Source path does not exist: ${a}`,`warn`);return}await Fe(a,o)}const Le={name:`rename`,version:`1.0.0`,taskTypes:[`rename`],execute:async(e,t,n)=>{n.dryRun||await Ie(e.config,t)}},Re=r(t.readFile),ze=r(t.writeFile);async function Be(r,i){if(r.condition!=null&&r.condition!==``&&!S(r.condition,i)){y(`Condition not met, skipping replace-in-file task`,`info`);return}let a=e.join(n.cwd(),r.file),{replacements:o}=r;if(!t.existsSync(a)){y(`File not found: ${a}, skipping`,`warn`);return}let s=await Re(a,`utf-8`);for(let{find:e,replace:t}of o){let n=b(t,i);s=s.replace(new RegExp(e,`gu`),n)}await ze(a,s)}const Ve={name:`replace-in-file`,version:`1.0.0`,taskTypes:[`replace-in-file`],execute:async(e,t,n)=>{n.dryRun||await Be(e.config,t)}};var K=class e extends f{constructor(e,t,n,r){super(e,`DUPLICATE_ID`),this.id=t,this.type=n,this.existingType=r,this.name=`DuplicateIdError`}static forId(t,n,r){return new e(`Duplicate ID "${t}" found in ${n}. This ID is already used in ${r??`unknown`}`,t,n,r)}},q=class e extends f{constructor(e,t,n,r,i){super(e,`ID_CONFLICT`),this.id=t,this.type=n,this.baseSource=r,this.overrideSource=i,this.name=`IdConflictError`}static forTask(t,n,r){return new e(`Task ID conflict: "${t}" is defined in multiple templates.\n Base task from: ${n??`unknown`}\n Override task from: ${r??`unknown`}\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the task.\n Task is being extended/overridden but no override strategy was specified.`,t,`task`,n,r)}static forVariable(t){return new e(`Variable ID conflict: "${t}" is defined in multiple templates.\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the variable.\n Variable is being extended/overridden but no override strategy was specified.`,t,`variable`)}static forPrompt(t){return new e(`Prompt ID conflict: "${t}" is defined in multiple templates.\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the prompt.\n Prompt is being extended/overridden but no override strategy was specified.`,t,`prompt`)}};const He=r(t.readFile),Ue={template:[[`template`,`templateFile`]]};function J(t){if(t==null||t===``)return`current template`;if(Y(t))return t;let r=n.cwd();return t.startsWith(r)?e.relative(r,t):t}function Y(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}function We(t,r){if(Y(t))return t;if(r==null||r===``)return e.isAbsolute(t)?t:e.resolve(n.cwd(),t);if(Y(r))try{let e=new URL(`.`,r);return new URL(t,e).href}catch{throw h.forRemoteTemplate(t,r)}let i=e.dirname(r);return e.isAbsolute(t)?t:e.resolve(i,t)}async function Ge(e){if(Y(e))return Ke(e);if(!t.existsSync(e))throw m.forPath(e);return He(e,`utf-8`)}async function Ke(e){try{let t=await fetch(e);if(!t.ok)throw g.forUrl(e,t.status,t.statusText);return await t.text()}catch(t){throw t instanceof Error&&t.message.includes(`Failed to fetch`)?t:g.forUrl(e,t instanceof Error?t:void 0)}}const X=new Map;async function qe(r,i=new Set){let a=Y(r),o;if(o=a||e.isAbsolute(r)?r:e.resolve(n.cwd(),r),X.has(o))return X.get(o);if(i.has(o))throw p.forTemplateInheritance(i,o);i.add(o);let s;if(a)s=await Ke(o);else{if(!t.existsSync(o))throw m.forPath(o);s=await He(o,`utf-8`)}let c;try{c=JSON.parse(s)}catch(e){throw te.forFile(o,e instanceof Error?e:Error(String(e)))}if(c.name==null||c.name.trim()===``)throw _.missingName(o);if(!/^[a-z\d]+(?:-[a-z\d]+)*$/u.test(c.name))throw _.invalidNameFormat(o,c.name);if(c.tasks!==void 0&&!Array.isArray(c.tasks))throw _.tasksNotArray(o);c.tasks===void 0&&(c.tasks=[]);for(let e of c.tasks)e.$sourceUrl=o;return X.set(o,c),c}async function Z(t,r,i=new Set){let a=Y(t),o;if(o=a||e.isAbsolute(t)?t:r==null?e.resolve(n.cwd(),t):Y(r)?new URL(t,r).href:e.resolve(r,t),i.has(o))throw p.forTemplateInheritance(i,o);i.add(o);let s=await qe(o);if(s.extends==null||s.extends===``)return s;let c=Y(o)?new URL(`.`,o).href:e.dirname(o),l=Array.isArray(s.extends)?s.extends:[s.extends],u=[];for(let e of l){let t=await Z(e,c,i);u.push(t)}return Ze([...u,s])}function Je(e,t,n){let r=new Map;for(let t of e){if(r.has(t.id))throw K.forId(t.id,`task`,r.get(t.id));r.set(t.id,`task`)}if(t!=null)for(let e of t){if(r.has(e.id))throw K.forId(e.id,`variable`,r.get(e.id));r.set(e.id,`variable`)}if(n!=null)for(let e of n){if(r.has(e.id))throw K.forId(e.id,`prompt`,r.get(e.id));r.set(e.id,`prompt`)}}function Ye(e,t){if((t.override??`merge`)===`replace`){y(` → Variable "${t.id}" using 'replace' strategy`,`info`);let{override:e,...n}=t;return n}y(` → Variable "${t.id}" merged (value replaced)`,`info`);let n={...e,...t};return delete n.override,n}function Xe(e,t){if((t.override??`merge`)===`replace`){y(` → Prompt "${t.id}" using 'replace' strategy`,`info`);let{override:e,...n}=t;return n}y(` → Prompt "${t.id}" merged`,`info`);let n={...e,...t};return delete n.override,n}function Ze(e){if(e.length===0)return{name:`Empty Template`,tasks:[]};if(e.length===1){let t=e[0];return Je(t.tasks??[],t.variables,t.prompts),t}let t=new Map,n=new Map,r=new Map;for(let i of e){if(i.prompts!=null)for(let e of i.prompts)if(r.has(e.id)){if(e.override==null)throw q.forPrompt(e.id);let t=r.get(e.id);r.set(e.id,Xe(t,e))}else r.set(e.id,{...e});if(i.variables!=null)for(let e of i.variables)if(n.has(e.id)){if(e.override==null)throw q.forVariable(e.id);let t=n.get(e.id);n.set(e.id,Ye(t,e))}else n.set(e.id,{...e});for(let e of i.tasks??[])if(t.has(e.id)){if(e.override==null){let n=t.get(e.id);throw q.forTask(e.id,J(n.$sourceUrl),J(e.$sourceUrl))}let n=t.get(e.id);t.set(e.id,et(n,e))}else t.set(e.id,{...e})}let i=Array.from(t.values()),a=r.size>0?Array.from(r.values()):void 0,o=n.size>0?Array.from(n.values()):void 0;Je(i,o,a);let s=e[e.length-1],c={name:s.name,tasks:i};return s.description!=null&&(c.description=s.description),s.dependencies!=null&&(c.dependencies=s.dependencies),a!=null&&(c.prompts=a),o!=null&&(c.variables=o),c}function Qe(e,t){let n=Ue[e];if(!n)return null;for(let e of n){let n=e.filter(e=>e in t&&t[e]!=null);if(n.length>1)return n}return null}function $e(e,t,n){let r={...e},i=Ue[n]??[];for(let[e,n]of Object.entries(t)){for(let t of i)if(t.includes(e)){for(let n of t)n!==e&&delete r[n];break}r[e]=n}return r}function et(e,t){if((t.override??`merge`)===`replace`){y(` → Task "${t.id}" using 'replace' strategy - completely replacing base task`,`info`),y(` Base: ${J(e.$sourceUrl)}`,`info`),y(` Override: ${J(t.$sourceUrl)}`,`info`);let{override:n,...r}=t;return r}y(` → Merging task "${t.id}"`,`info`),y(` Base: ${J(e.$sourceUrl)}`,`info`),y(` Override: ${J(t.$sourceUrl)}`,`info`);let n;if(typeof e.config==`object`&&e.config!==null&&typeof t.config==`object`&&t.config!==null){n=$e(e.config,t.config,t.type);let r=Qe(t.type,n);r!==null&&r.length>0&&(y(` ⚠️ Warning: Conflicting config fields detected: ${r.join(`, `)}`,`warn`),y(` Please use override: "replace" or specify only one of these fields`,`warn`))}else n=t.config??e.config;let r=e.prompts?[...e.prompts]:void 0;if(t.prompts&&t.prompts.length>0)if(!r)r=[...t.prompts];else{let e=new Map(r.map(e=>[e.id,e]));for(let n of t.prompts)e.set(n.id,n);r=Array.from(e.values())}let i=e.variables?[...e.variables]:void 0;if(t.variables&&t.variables.length>0)if(!i)i=[...t.variables];else{let e=new Map(i.map(e=>[e.id,e]));for(let n of t.variables)e.set(n.id,n);i=Array.from(e.values())}let a=[...e.dependencies??[],...t.dependencies??[]],o=a.length>0?[...new Set(a)]:void 0,s=t.$sourceUrl??e.$sourceUrl,c={...e,...t,config:n,...r!=null&&{prompts:r},...i!=null&&{variables:i},...o!=null&&{dependencies:o},...s!=null&&{$sourceUrl:s}};return delete c.override,c}function tt(){X.clear()}async function nt(e){y(`Loading tasks from ${e}...`,`info`);let t=await Z(e);y(`Loaded ${t.tasks?.length??0} task(s)`,`info`),t.extends!=null&&t.extends!==``&&y(`Extended from: ${(Array.isArray(t.extends)?t.extends:[t.extends]).join(`, `)}`,`info`),t.prompts!=null&&t.prompts.length>0&&y(`Found ${t.prompts.length} top-level prompt(s)`,`info`),t.variables!=null&&t.variables.length>0&&y(`Found ${t.variables.length} top-level variable(s)`,`info`);let n={tasks:t.tasks??[]};return t.prompts!=null&&(n.prompts=t.prompts),t.variables!=null&&(n.variables=t.variables),n}const rt=r(t.writeFile);async function it(t,r,i){if(t.condition!=null&&t.condition!==``&&!S(t.condition,r)){y(`Condition not met, skipping template task`,`info`);return}let a=e.join(n.cwd(),t.file),o=t.template!=null&&t.template!==``,s=t.templateFile!=null&&t.templateFile!==``;if(!o&&!s)throw V.templateMissingTemplateOrFile();if(o&&s)throw V.templateHasBothTemplateAndFile();let c;if(s&&t.templateFile.endsWith(`.hbs`)){let e=await Ge(We(t.templateFile,i?.$sourceUrl));c=(await import(`handlebars`)).default.compile(e)(r)}else c=b(s?await Ge(We(t.templateFile,i?.$sourceUrl)):t.template,r);await rt(a,c)}const at={name:`template`,version:`1.0.0`,taskTypes:[`template`],execute:async(e,t,n)=>{n.dryRun||await it(e.config,t,e)}},ot=r(t.readFile),st=r(t.writeFile);async function ct(t,r){if(t.condition!=null&&t.condition!==``&&!S(t.condition,r)){y(`Condition not met, skipping update-json task`,`info`);return}let i=e.join(n.cwd(),t.file),{updates:a}=t,o=await ot(i,`utf-8`),s=JSON.parse(o);function c(e){if(typeof e==`string`)return b(e,r);if(Array.isArray(e))return e.map(e=>c(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=c(r);return t}return e}for(let[e,t]of Object.entries(a)){let n=c(t);e.includes(`.`)?x(s,e,n):s[e]=n}await st(i,`${JSON.stringify(s,null,2)}\n`)}const lt={name:`update-json`,version:`1.0.0`,taskTypes:[`update-json`],execute:async(e,t,n)=>{n.dryRun||await ct(e.config,t)}};function Q(){L(`update-json`)||(F(lt),F(at),F(we),F(Pe),F(Ve),F(Ee),F(Le),F(Ae),F(Oe))}async function ut(e,t,n=!1){if(Q(),n){y(`[DRY RUN] Would execute: ${e.name}`,`info`);return}if(L(e.type)){await z(e,t,{dryRun:n});return}throw TypeError(`Unknown task type: ${e.type}`)}async function $(e,t,r,i,a=!1){try{return y(`[${r}/${i}] Running: ${e.name}...`,`info`),await ut(e,t,a),y(`✓ ${e.name}`,`success`),!0}catch(t){return y(`✗ Failed: ${e.name}`,`error`),t instanceof Error&&(y(` Reason: ${t.message}`,`error`),t.stack!=null&&n.env.DEBUG!=null&&console.error(t.stack)),e.required&&y(` This is a required task. Initialization cannot continue.`,`error`),!1}}function dt(e){let t=[],n=new Set,r=new Set,i=new Map(e.map(e=>[e.id,e]));function a(e){if(n.has(e))return;if(r.has(e))throw p.forTaskDependency(e);r.add(e);let o=i.get(e);if(!o)throw xe.forId(e);if(o.dependencies)for(let e of o.dependencies)a(e);r.delete(e),n.add(e),t.push(o)}for(let t of e)n.has(t.id)||a(t.id);return t}function ft(e){let t=[];for(let n of e)if(!L(n.type))t.push(`Task "${n.id}" (${n.name}): Unknown task type "${n.type}"`);else if(n.type===`template`){let e=pt(n);t.push(...e)}return t}function pt(e){let t=[],n=e.config,r=n.template!=null&&n.template!==``,i=n.templateFile!=null&&n.templateFile!==``;return!r&&!i&&t.push(`Task "${e.id}" (${e.name}): Template task requires either "template" (inline) or "templateFile" (file path) to be specified`),r&&i&&t.push(`Task "${e.id}" (${e.name}): Template task cannot have both "template" and "templateFile" specified. Use one or the other.`),(n.file==null||n.file===``)&&t.push(`Task "${e.id}" (${e.name}): Template task requires "file" property to specify the output file path`),t}function mt(e){y(`❌ Template validation failed:`,`error`),y(``,`error`);for(let t of e)y(` • ${t}`,`error`);y(``,`error`),y(`Please fix these errors before continuing.`,`error`)}function ht(e,t=new Map){let n={};for(let r of e){let e=t.get(r.id);e!==void 0&&(n[r.id]=e)}return n}async function gt(e,t){if(e==null)return;if(typeof e!=`object`||!e||Array.isArray(e))return e;let n=e;if(n.type===`exec`){let e=n.value;if(typeof e!=`string`){y(`Variable "${t}": exec value must have a string command`,`error`);return}try{let t=i(e,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:1e4}).trim();if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return t}if(/^-?\d+(?:\.\d+)?$/u.test(t)){let e=Number.parseFloat(t);if(!Number.isNaN(e))return e}return t===`true`||t===`false`?t===`true`:t}catch(e){y(`Variable "${t}": failed to execute command: ${e instanceof Error?e.message:`Unknown error`}`,`warn`);return}}else if(n.type===`static`)return n.value;return e}async function _t(e){let t=new Map,n=e.map(async e=>{let t=await gt(e.value,e.id);return{id:e.id,value:t}}),r=await Promise.all(n);for(let e of r)e.value!==void 0&&t.set(e.id,e.value);return t}function vt(e){let t=[],n=new Set;for(let r of e)if(n.has(r.id)&&t.push(`Duplicate variable ID: "${r.id}"`),n.add(r.id),/^[\w$]+$/u.test(r.id)||t.push(`Variable ID "${r.id}" is invalid. Must contain only letters, numbers, underscore, or dollar sign.`),r.value===void 0||r.value===null)t.push(`Variable "${r.id}" must have a value`);else if(typeof r.value==`object`&&!Array.isArray(r.value)&&r.value!==null){let e=r.value;e.type==null||e.type===``?t.push(`Variable "${r.id}": value object must have a "type" field ("static" or "exec")`):e.type!==`static`&&e.type!==`exec`&&t.push(`Variable "${r.id}": type must be "static" or "exec", got "${e.type}"`),(e.value===void 0||e.value===null)&&t.push(`Variable "${r.id}": value config must have a "value" field`),e.type===`exec`&&typeof e.value!=`string`&&t.push(`Variable "${r.id}": exec type must have a string command as value`)}return t}async function yt(e,t){Q(),y(`Validating task configurations...`,`info`);let r=ft(e);r.length>0&&(mt(r),n.exit(1)),y(`✓ All tasks validated successfully`,`success`);let i=e.filter(e=>v(e.enabled,ee()));y(`Resolving task dependencies...`,`info`);let a=dt(i);y(`Welcome! Let's execute your tasks.`,`info`),t.dryRun&&y(`🔍 DRY RUN MODE - No changes will be made`,`warn`),y(`This will execute your project tasks based on the defined configuration.`,`info`);let o=ee(),s=t.globalVariables??[],c=[],l=[...s];for(let e of a)if(e.variables&&e.variables.length>0)for(let t of e.variables)c.push(t),l.push(t);if(l.length>0){let e=vt(l);e.length>0&&(y(`❌ Variable validation errors:`,`error`),e.forEach(e=>y(` - ${e}`,`error`)),n.exit(1)),y(`Resolving variable values...`,`info`);let t=ht(l,await _t(l));Object.assign(o,t),Object.keys(t).length>0&&y(`✓ Resolved ${Object.keys(t).length} variable(s)`,`success`)}let u=t.globalPrompts??[],d=[],f=[...u];for(let e of a)if(e.prompts&&e.prompts.length>0)for(let t of e.prompts)d.push(t),f.push(t);if(f.length>0){let e=G(f);e.length>0&&(y(`❌ Prompt validation errors:`,`error`),e.forEach(e=>y(` - ${e}`,`error`)),n.exit(1)),y(`Resolving prompt default values...`,`info`);let t=await W(f),r={};if(u.length>0&&(y(`📋 Top-level prompts (available to all tasks):`,`info`),r=await H(u,t,o),Object.assign(o,r)),d.length>0){u.length>0&&y(`📋 Task-specific prompts:`,`info`);let e=await H(d,t,o);Object.assign(o,e)}}let p=a.filter(e=>v(e.enabled,o));if(y(`${p.length} of ${a.length} task(s) enabled for execution`,`info`),t.dryRun){await j(p,o),y(`🔍 Dry run completed - no changes were made`,`info`),y(`Run without --dry-run to apply changes`,`info`);return}y(`Starting task execution...`,`info`),await R(`beforeAll`,o);let m=p.length,h=0,g=0,te=[];for(let e=0;e<p.length;e++){let n=p[e];if(n!=null)if(await R(`beforeTask`,n,o),await $(n,o,e+1,m,t.dryRun))h++,te.push(n.id),await R(`afterTask`,n,o);else if(n.required){g++,await R(`onError`,Error(`Task ${n.name} failed`),n);break}else y(`⚠️ Non-critical task failed, continuing...`,`warn`),await R(`onError`,Error(`Task ${n.name} failed`),n)}g>0&&(y(`❌ Task execution failed with ${g} critical error(s)`,`error`),y(`✓ Completed: ${h}/${m} tasks`,`info`),n.exit(1)),await R(`afterAll`,o),y(`✅ All tasks completed successfully!`,`success`),y(`✓ Completed: ${h}/${m} tasks`,`success`),t.dryRun||(y(`Next steps:`,`info`),y(`1. Review the changes made to your project`,`info`),y(`2. Commit the changes to git`,`info`))}const bt=n.argv.includes(`--dry-run`),xt=n.argv.includes(`--force`);async function St(e){try{let t=e||[];t.length===0&&(y(`⚠️ No tasks defined. Use --tasks-file to specify tasks or call runWithTasks() programmatically.`,`warn`),y(`Example: scaffoldfy --tasks-file ./tasks.json`,`info`),n.exit(1)),await yt(t,{dryRun:bt,force:xt,tasksFilePath:void 0})}catch(e){y(`❌ Task execution failed`,`error`),e instanceof Error?(y(`Error: ${e.message}`,`error`),n.env.DEBUG!=null&&console.error(e.stack)):console.error(e),n.exit(1)}}async function Ct(e,t){try{await yt(e,{dryRun:t?.dryRun??bt,force:t?.force??xt,tasksFilePath:t?.tasksFilePath??void 0,...t?.globalVariables!=null&&{globalVariables:t.globalVariables},...t?.globalPrompts!=null&&{globalPrompts:t.globalPrompts}})}catch(e){y(`❌ Task execution failed`,`error`),e instanceof Error?(y(`Error: ${e.message}`,`error`),n.env.DEBUG!=null&&console.error(e.stack)):console.error(e),n.exit(1)}}export{F as A,A as B,z as C,L as D,ve as E,k as F,b as G,D as H,O as I,ie as J,y as K,le as L,ye as M,j as N,he as O,de as P,fe as R,be as S,I as T,S as U,se as V,ne as W,x as Y,W as _,gt as a,R as b,ut as c,tt as d,Z as f,G as g,Ze as h,_t as i,pe as j,_e as k,Q as l,qe as m,Ct as n,ht as o,nt as p,re as q,vt as r,dt as s,St as t,$ as u,U as v,me as w,ge as x,H as y,ue as z};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`node:fs`);c=s(c);let l=require(`node:path`);l=s(l);let u=require(`node:process`);u=s(u);let d=require(`node:util`);d=s(d);let f=require(`node:child_process`);f=s(f);let p=require(`node:readline`);p=s(p);let m=require(`handlebars`);m=s(m);let h=require(`@inquirer/prompts`);h=s(h);function g(){return{}}var _=class extends Error{constructor(e,t){super(e),this.code=t,this.name=this.constructor.name}},v=class e extends _{constructor(e,t,n){super(e,`CIRCULAR_DEPENDENCY`),this.dependencyChain=t,this.resolvedPath=n,this.name=`CircularDependencyError`}static forTemplateInheritance(t,n){let r=Array.from(t);return new e(`Circular dependency detected: ${r.join(` -> `)} -> ${n}`,r,n)}static forTaskDependency(t){return new e(`Circular dependency detected involving task: ${t}`,[t])}},y=class e extends _{constructor(e,t){super(e,`TEMPLATE_FILE_NOT_FOUND`),this.filePath=t,this.name=`TemplateFileNotFoundError`}static forPath(t){return new e(`Template file not found: ${t}`,t)}},ee=class e extends _{constructor(e,t,n){super(e,`TEMPLATE_RESOLUTION_ERROR`),this.templateFilePath=t,this.sourceUrl=n,this.name=`TemplateResolutionError`}static forRemoteTemplate(t,n){return new e(`Failed to resolve templateFile "${t}" relative to remote template "${n}"`,t,n)}},te=class e extends _{constructor(e,t,n){super(e,`TEMPLATE_FETCH_ERROR`),this.url=t,this.originalError=n,this.name=`TemplateFetchError`}static forUrl(t,n,r){return typeof n==`number`?new e(`Failed to fetch template from ${t}: ${n} ${r??``}`.trim(),t):new e(`Failed to fetch template from ${t}: ${n?.message??String(n??`Unknown error`)}`,t,n)}},ne=class e extends _{constructor(e,t,n){super(e,`TEMPLATE_PARSE_ERROR`),this.filePath=t,this.originalError=n,this.name=`TemplateParseError`}static forFile(t,n){return new e(`Failed to parse template file ${t}: ${n.message}`,t,n)}},b=class e extends _{constructor(e,t){super(e,`INVALID_TEMPLATE`),this.filePath=t,this.name=`InvalidTemplateError`}static forFile(t,n){return new e(`Invalid template file ${t}: ${n}`,t)}static tasksNotArray(t){return new e(`Invalid template file ${t}: 'tasks' must be an array if provided`,t)}static missingName(t){return new e(`Invalid template file ${t}: 'name' field is required`,t)}static invalidNameFormat(t,n){return new e(`Invalid template file ${t}: 'name' field "${n}" must contain only lowercase letters, digits, and hyphens. It cannot start or end with a hyphen, and cannot contain consecutive hyphens.`,t)}};function x(e,t){return e===void 0?!0:typeof e==`boolean`?e:typeof e==`object`&&`condition`in e?E(e.condition,t):!1}function re(){try{let e=(0,f.execSync)(`git remote get-url origin`,{encoding:`utf-8`}).trim(),t=e.match(/github\.com[:/](?<owner>[^/]+)\/(?<name>[^/]+)$/u);if(t?.groups){let{owner:n,name:r}=t.groups,i=r;return i.endsWith(`.git`)&&(i=i.slice(0,-4)),{owner:n,name:i,url:e}}return null}catch{return null}}async function S(e,t){let n=p.default.createInterface({input:u.default.stdin,output:u.default.stdout});return new Promise(r=>{let i;i=t==null?`${e}: `:`${e} (${t}): `,n.question(i,e=>{n.close(),r(e.trim()||(t??``))})})}async function ie(e,t=!1){return S(`${e} (${t?`Y/n`:`y/N`})`,t?`y`:`n`).then(e=>e.toLowerCase()===`y`||e.toLowerCase()===`yes`)}function C(e,t=`info`){console.log(`${{info:`\x1B[36m`,success:`\x1B[32m`,error:`\x1B[31m`,warn:`\x1B[33m`}[t]}${{info:`ℹ`,success:`✓`,error:`✗`,warn:`⚠`}[t]} ${e}[0m`)}function w(e,t){return e.replace(/\{\{(?<key>\w+)\}\}/gu,(e,n)=>t[n]?.toString()??``)}function T(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++){let t=r[e];t!=null&&t!==``&&((!(t in i)||typeof i[t]!=`object`||i[t]===null)&&(i[t]={}),i=i[t])}let a=r[r.length-1];a!=null&&a!==``&&(i[a]=n)}function E(e,t){try{let n={...t};return Function(...Object.keys(n),`'use strict'; return (${e})`)(...Object.values(n))}catch(t){return C(`Failed to evaluate condition: ${e}`,`warn`),t instanceof Error&&C(` Error: ${t.message}`,`warn`),!1}}function ae(e,t){try{let n=l.default.isAbsolute(e)?e:l.default.join(u.default.cwd(),e);if(!c.default.existsSync(n))throw y.forPath(e);return oe(c.default.readFileSync(n,`utf-8`),t)}catch(t){throw C(`Failed to read template file: ${e}`,`error`),t instanceof Error&&C(` Error: ${t.message}`,`error`),t}}function oe(e,t){try{return m.default.compile(e)(t)}catch(e){throw C(`Failed to compile Handlebars template`,`error`),e instanceof Error&&C(` Error: ${e.message}`,`error`),e}}const D=(0,d.promisify)(c.default.readFile),se=2,ce=10,le=55,O={reset:`\x1B[0m`,red:`\x1B[31m`,green:`\x1B[32m`,yellow:`\x1B[33m`,blue:`\x1B[34m`,cyan:`\x1B[36m`,gray:`\x1B[90m`};function k(e,t){switch(t){case`add`:return`${O.green}+ ${e}${O.reset}`;case`remove`:return`${O.red}- ${e}${O.reset}`;case`context`:return`${O.gray} ${e}${O.reset}`;default:return e}}function A(e,t){let n=e.split(`
|
|
2
|
+
`),r=t.split(`
|
|
3
|
+
`),i=[],a=Math.max(n.length,r.length);for(let e=0;e<a;e++){let t=n[e],a=r[e];t===a?t!==void 0&&i.push(k(t,`context`)):(t!==void 0&&i.push(k(t,`remove`)),a!==void 0&&i.push(k(a,`add`)))}return i}async function ue(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t))return`${O.yellow}⊘ Condition not met - task would be skipped${O.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${O.red}✗ File not found: ${e.file}${O.reset}`;try{let r=await D(n,`utf-8`),i=JSON.parse(r),a={...i};function o(e){if(typeof e==`string`)return w(e,t);if(Array.isArray(e))return e.map(e=>o(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=o(r);return t}return e}for(let[t,n]of Object.entries(e.updates)){let e=o(n);t.includes(`.`)?T(i,t,e):i[t]=e}let s=JSON.stringify(a,null,2),c=JSON.stringify(i,null,2);if(s===c)return`${O.cyan}→ No changes${O.reset}`;let l=A(s,c);return`${O.blue}File: ${e.file}${O.reset}\n${l.join(`
|
|
4
|
+
`)}`}catch(e){return`${O.red}✗ Error: ${e instanceof Error?e.message:String(e)}${O.reset}`}}async function de(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t))return`${O.yellow}⊘ Condition not met - task would be skipped${O.reset}`;if(e.template==null||e.template===``)return`${O.red}✗ No template content provided for file: ${e.file}${O.reset}`;let n=l.default.join(u.default.cwd(),e.file),r=w(e.template,t);if(!c.default.existsSync(n)){let t=r.split(`
|
|
5
|
+
`).slice(0,10).join(`
|
|
6
|
+
`),n=r.split(`
|
|
7
|
+
`).length>10;return`${O.blue}File: ${e.file}${O.reset}\n${O.green}+ New file would be created${O.reset}\n${O.gray}Content preview:${O.reset}\n${t}${n?`
|
|
8
|
+
...`:``}`}try{let t=await D(n,`utf-8`);if(t===r)return`${O.cyan}→ No changes${O.reset}`;let i=A(t,r);return`${O.blue}File: ${e.file}${O.reset}\n${i.join(`
|
|
9
|
+
`)}`}catch(e){return`${O.red}✗ Error: ${e instanceof Error?e.message:String(e)}${O.reset}`}}async function fe(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t))return`${O.yellow}⊘ Condition not met - task would be skipped${O.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(c.default.existsSync(n))return`${O.cyan}→ File already exists, would be skipped: ${e.file}${O.reset}`;let r=e.template!=null&&e.template!==``,i=e.templateFile!=null&&e.templateFile!==``;if(!r&&!i)return`${O.red}✗ No template content provided for file: ${e.file}${O.reset}`;try{let n;if(r)n=w(e.template,t);else return`${O.blue}File: ${e.file}${O.reset}\n${O.green}+ New file would be created from template: ${e.templateFile}${O.reset}`;let i=n.split(`
|
|
10
|
+
`).slice(0,10).join(`
|
|
11
|
+
`),a=n.split(`
|
|
12
|
+
`).length>10;return`${O.blue}File: ${e.file}${O.reset}\n${O.green}+ New file would be created${O.reset}\n${O.gray}Content preview:${O.reset}\n${i}${a?`
|
|
13
|
+
...`:``}`}catch(e){return`${O.red}✗ Error: ${e instanceof Error?e.message:String(e)}${O.reset}`}}async function pe(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t))return`${O.yellow}⊘ Condition not met - task would be skipped${O.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${O.red}✗ File not found: ${e.file}${O.reset}`;try{let r=await D(n,`utf-8`),i=new RegExp(e.pattern,e.flags??`g`),a=w(e.replacement,t),o=r.replace(i,a);if(r===o)return`${O.cyan}→ No matches found${O.reset}`;let s=A(r,o);return`${O.blue}File: ${e.file}${O.reset}\n${s.join(`
|
|
14
|
+
`)}`}catch(e){return`${O.red}✗ Error: ${e instanceof Error?e.message:String(e)}${O.reset}`}}async function me(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t))return`${O.yellow}⊘ Condition not met - task would be skipped${O.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${O.red}✗ File not found: ${e.file}${O.reset}`;try{let r=await D(n,`utf-8`),i=r;for(let{find:n,replace:i}of e.replacements){let e=w(n,t),a=w(i,t);r=r.replace(e,a)}if(i===r)return`${O.cyan}→ No changes${O.reset}`;let a=A(i,r);return`${O.blue}File: ${e.file}${O.reset}\n${a.join(`
|
|
15
|
+
`)}`}catch(e){return`${O.red}✗ Error: ${e instanceof Error?e.message:String(e)}${O.reset}`}}function he(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t))return`${O.yellow}⊘ Condition not met - task would be skipped${O.reset}`;let n=e.paths.map(e=>w(e,t)).filter(e=>c.default.existsSync(l.default.join(u.default.cwd(),e)));return n.length===0?`${O.cyan}→ No files/directories to delete${O.reset}`:`${O.red}Would delete:${O.reset}\n${n.map(e=>`${O.red} - ${e}${O.reset}`).join(`
|
|
16
|
+
`)}`}function ge(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t))return`${O.yellow}⊘ Condition not met - task would be skipped${O.reset}`;let n=w(e.from,t),r=w(e.to,t),i=l.default.join(u.default.cwd(),n),a=l.default.join(u.default.cwd(),r);return c.default.existsSync(i)?c.default.existsSync(a)?`${O.yellow}⚠ Destination already exists: ${r}${O.reset}\n${O.cyan}Would rename: ${n} → ${r}${O.reset}`:`${O.cyan}Would rename: ${n} → ${r}${O.reset}`:`${O.red}✗ Source not found: ${n}${O.reset}`}function j(e){if(e.condition!=null&&e.condition!==``)return`${O.yellow}⊘ Condition check skipped in dry-run${O.reset}`;let t=l.default.join(u.default.cwd(),`.git`),n=c.default.existsSync(t),r=[];if(e.removeExisting&&n&&r.push(`${O.red}Would remove existing .git directory${O.reset}`),r.push(`${O.green}Would initialize git repository${O.reset}`),e.initialCommit){let t=e.message??`Initial commit`;r.push(`${O.green}Would create initial commit: "${t}"${O.reset}`)}return r.join(`
|
|
17
|
+
`)}function M(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t))return`${O.yellow}⊘ Condition not met - task would be skipped${O.reset}`;let n=w(e.command,t),r=e.cwd==null?u.default.cwd():w(e.cwd,t);return`${O.yellow}Would execute:${O.reset}\n${O.cyan} Command: ${n}${O.reset}\n${O.cyan} Working directory: ${r}${O.reset}`}async function N(e,t){try{switch(e.type){case`update-json`:return await ue(e.config,t);case`template`:return await de(e.config,t);case`create`:return await fe(e.config,t);case`regex-replace`:return await pe(e.config,t);case`replace-in-file`:return await me(e.config,t);case`delete`:return he(e.config,t);case`rename`:return ge(e.config,t);case`git-init`:return j(e.config);case`exec`:return M(e.config,t);default:{let t=e.type;return`${O.yellow}⚠ Diff not available for task type: ${t}${O.reset}`}}}catch(e){return`${O.red}✗ Error generating diff: ${e instanceof Error?e.message:String(e)}${O.reset}`}}async function P(e,t){console.log(`${O.blue}═══════════════════════════════════════════════════════${O.reset}`),console.log(`${O.blue} DRY RUN - Preview of changes${O.reset}`),console.log(`${O.blue}═══════════════════════════════════════════════════════${O.reset}`);for(let n of e){console.log(`${O.cyan}▶ Task: ${n.name}${O.reset}`),console.log(`${O.gray} ${n.description}${O.reset}`);let e=await N(n,t);console.log(e),console.log(`${O.gray}${`─`.repeat(55)}${O.reset}`)}console.log(`${O.blue}═══════════════════════════════════════════════════════${O.reset}`),console.log(`${O.yellow} No changes were applied (dry-run mode)${O.reset}`),console.log(`${O.blue}═══════════════════════════════════════════════════════${O.reset}`)}const F=new Map,I={},L=new Map;function R(e){if(e.name==null||e.name===``)throw TypeError(`Plugin name is required`);if(!Array.isArray(e.taskTypes)||e.taskTypes.length===0)throw TypeError(`Plugin ${e.name} must define at least one task type`);if(typeof e.execute!=`function`)throw TypeError(`Plugin ${e.name} must provide an execute function`);if(F.has(e.name))throw TypeError(`Plugin ${e.name} is already registered`);for(let t of e.taskTypes)if(L.has(t)){let e=L.get(t);throw TypeError(`Task type "${t}" is already registered by plugin "${e}"`)}F.set(e.name,e);for(let t of e.taskTypes)L.set(t,e.name);C(`✓ Registered plugin: ${e.name}${e.version==null?``:` v${e.version}`}`,`info`)}function _e(e){let t=F.get(e);if(t!=null){for(let e of t.taskTypes)L.delete(e);F.delete(e)}}function ve(e){return F.get(e)}function z(e){let t=L.get(e);if(t!=null)return F.get(t)}function B(e){return L.has(e)}function ye(){return Array.from(F.keys())}function be(){F.clear(),L.clear()}function xe(e){e.beforeAll!=null&&(I.beforeAll=e.beforeAll),e.afterAll!=null&&(I.afterAll=e.afterAll),e.beforeTask!=null&&(I.beforeTask=e.beforeTask),e.afterTask!=null&&(I.afterTask=e.afterTask),e.onError!=null&&(I.onError=e.onError)}async function V(e,...t){let n=I[e];if(n!=null)try{e===`beforeAll`||e===`afterAll`?await n(t[0]):(e===`beforeTask`||e===`afterTask`||e===`onError`)&&await n(t[0],t[1])}catch(t){C(`Error in ${e} hook: ${t instanceof Error?t.message:String(t)}`,`error`)}}async function H(e,t,n){let r=z(e.type);if(r==null)throw TypeError(`No plugin found for task type: ${e.type}`);await r.execute(e,t,n)}async function Se(e,t){let n=z(e.type);if(!(n==null||n.getDiff==null))return n.getDiff(e,t)}function Ce(e){let t=z(e.type);return t==null?[`No plugin found for task type: ${e.type}`]:t.validate==null?[]:t.validate(e)}function we(e,t,n,r){return{name:e,...r?.version!=null&&{version:r.version},taskTypes:[t],execute:n,...r?.getDiff!=null&&{getDiff:r.getDiff},...r?.validate!=null&&{validate:r.validate}}}var Te=class e extends _{constructor(e,t){super(e,`TASK_NOT_FOUND`),this.taskId=t,this.name=`TaskNotFoundError`}static forId(t){return new e(`Task not found: ${t}`,t)}},U=class e extends _{constructor(e,t,n){super(e,`PROMPT_VALIDATION_ERROR`),this.promptId=t,this.reason=n,this.name=`PromptValidationError`}static required(t){return new e(`Prompt "${t}" is required`,t,`required`)}static unknownType(t){return new e(`Unknown prompt type: ${t}`,t,`unknown_type`)}},W=class e extends _{constructor(e,t,n){super(e,`PLUGIN_CONFIGURATION_ERROR`),this.pluginType=t,this.configIssue=n,this.name=`PluginConfigurationError`}static templateMissingTemplateOrFile(){return new e(`Template task requires either "template" (inline) or "templateFile" (file path) to be specified`,`template`,`missing_template_or_file`)}static templateHasBothTemplateAndFile(){return new e(`Template task cannot have both "template" and "templateFile" specified. Use one or the other.`,`template`,`both_template_and_file`)}static createMissingTemplateOrFile(){return new e(`Create task requires either "template" (inline) or "templateFile" (file path) to be specified`,`create`,`missing_template_or_file`)}static createHasBothTemplateAndFile(){return new e(`Create task cannot have both "template" and "templateFile" specified. Use one or the other.`,`create`,`both_template_and_file`)}};async function G(e,t=new Map,n={}){let r={};if(e.length===0)return r;for(let i of e){let e={...n,...r};if(x(i.enabled,e))try{let e,n=t.get(i.id);switch(i.type){case`input`:{let t={message:i.message};if(n!==void 0&&(t.default=String(n)),i.required!==void 0&&(t.required=i.required),e=await(0,h.input)(t),i.required&&(e==null||typeof e==`string`&&e.trim()===``))throw C(`${i.message} is required`,`error`),U.required(i.id);break}case`password`:if(e=await(0,h.password)({message:i.message,mask:`*`}),i.required&&(e==null||typeof e==`string`&&e.trim()===``))throw C(`${i.message} is required`,`error`),U.required(i.id);break;case`number`:{let t={message:i.message};if(n!==void 0&&(t.default=Number(n)),i.required!==void 0&&(t.required=i.required),i.min!==void 0&&(t.min=i.min),i.max!==void 0&&(t.max=i.max),e=await(0,h.number)(t),i.required&&e==null)throw C(`${i.message} is required`,`error`),U.required(i.id);break}case`select`:{let t={message:i.message,choices:i.choices.map(e=>({name:e.name,value:e.value}))};n!==void 0&&(t.default=n),e=await(0,h.select)(t);break}case`confirm`:{let t=n===void 0?!1:!!n;e=await(0,h.confirm)({message:i.message,default:t});break}default:throw C(`Unknown prompt type: ${i.type}`,`error`),U.unknownType(i.type)}r[i.id]=e}catch(e){throw e instanceof Error&&C(`Failed to collect prompt "${i.id}": ${e.message}`,`error`),e}}return r}async function Ee(e,t){if(e===void 0)return;if(typeof e!=`object`||!e||Array.isArray(e))return e;let n=e;if(n.type===`exec`){let e=n.value;if(typeof e!=`string`){C(`Prompt "${t}": exec default value must have a string command`,`error`);return}try{let t=(0,f.execSync)(e,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:1e4}).trim();if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return t}if(/^-?\d+(?:\.\d+)?$/u.test(t)){let e=Number.parseFloat(t);if(!Number.isNaN(e))return e}return t===`true`||t===`false`?t===`true`:t}catch(e){C(`Prompt "${t}": failed to execute default value command: ${e instanceof Error?e.message:`Unknown error`}`,`warn`);return}}else if(n.type===`static`)return n.value;return e}async function De(e){let t=new Map,n=e.map(async e=>{if(e.default!==void 0){let n=await Ee(e.default,e.id);n!==void 0&&t.set(e.id,n)}});return await Promise.all(n),t}function Oe(e){let t=[],n=new Set;for(let r of e){if(n.has(r.id)&&t.push(`Duplicate prompt ID: ${r.id}`),n.add(r.id),/^[\w-]+$/u.test(r.id)||t.push(`Invalid prompt ID "${r.id}": must contain only alphanumeric characters, underscores, and hyphens`),(!r.message||r.message.trim()===``)&&t.push(`Prompt "${r.id}" must have a non-empty message`),r.type===`select`){r.choices.length===0&&t.push(`Select prompt "${r.id}" must have at least one choice`);for(let e of r.choices)(!e.name||e.name.trim()===``)&&t.push(`Select prompt "${r.id}" has a choice with empty name`),e.value===void 0&&t.push(`Select prompt "${r.id}" has a choice with undefined value`)}r.type===`number`&&r.min!==void 0&&r.max!==void 0&&r.min>r.max&&t.push(`Number prompt "${r.id}" has min greater than max`)}return t}const ke=(0,d.promisify)(c.default.writeFile);async function Ae(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t)){C(`Condition not met, skipping create task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file);if(c.default.existsSync(n)){C(`File already exists, skipping: ${e.file}`,`info`);return}let r=e.template!=null&&e.template!==``,i=e.templateFile!=null&&e.templateFile!==``;if(!r&&!i)throw W.createMissingTemplateOrFile();if(r&&i)throw W.createHasBothTemplateAndFile();let a;if(i&&e.templateFile.endsWith(`.hbs`))a=ae(e.templateFile,t);else if(i){let n=e.templateFile,r=l.default.isAbsolute(n)?n:l.default.join(u.default.cwd(),n);if(!c.default.existsSync(r))throw y.forPath(n);a=w(c.default.readFileSync(r,`utf-8`),t)}else a=w(e.template,t);let o=l.default.dirname(n);c.default.existsSync(o)||c.default.mkdirSync(o,{recursive:!0}),await ke(n,a),C(`Created file: ${e.file}`,`success`)}const je={name:`create`,version:`1.0.0`,taskTypes:[`create`],execute:async(e,t,n)=>{n.dryRun||await Ae(e.config,t)}};async function Me(e,t){let{paths:n,condition:r}=e;if(r!=null&&r!==``){if(!t){C(`Condition specified but no config provided, skipping deletion`,`warn`);return}if(!E(r,t)){C(`Condition not met, skipping deletion`,`info`);return}}for(let e of n){let t=l.default.join(u.default.cwd(),e);c.default.existsSync(t)&&c.default.rmSync(t,{recursive:!0,force:!0})}}const Ne={name:`delete`,version:`1.0.0`,taskTypes:[`delete`],execute:async(e,t,n)=>{n.dryRun||await Me(e.config,t)}};async function Pe(e,t){if(e.condition!=null&&e.condition!==``){if(!t){C(`Condition specified but no config provided, skipping exec`,`warn`);return}if(!E(e.condition,t)){C(`Condition not met, skipping exec task`,`info`);return}}let n=e.cwd==null?u.default.cwd():l.default.join(u.default.cwd(),e.cwd);(0,f.execSync)(e.command,{cwd:n,stdio:`inherit`})}const Fe={name:`exec`,version:`1.0.0`,taskTypes:[`exec`],execute:async(e,t,n)=>{n.dryRun||await Pe(e.config,t)}};async function Ie(e,t){if(e.condition!=null&&e.condition!==``){if(!t){C(`Condition specified but no config provided, skipping git-init`,`warn`);return}if(!E(e.condition,t)){C(`Condition not met, skipping git-init task`,`info`);return}}if(e.removeExisting){let e=l.default.join(u.default.cwd(),`.git`);c.default.existsSync(e)&&c.default.rmSync(e,{recursive:!0,force:!0})}if((0,f.execSync)(`git init`,{stdio:`inherit`}),e.initialCommit){let t=e.message??`Initial commit`;(0,f.execSync)(`git add .`,{stdio:`inherit`}),(0,f.execSync)(`git commit -m "${t}"`,{stdio:`inherit`})}}const Le={name:`git-init`,version:`1.0.0`,taskTypes:[`git-init`],execute:async(e,t,n)=>{n.dryRun||await Ie(e.config,t)}},Re=(0,d.promisify)(c.default.readFile),ze=(0,d.promisify)(c.default.writeFile);async function Be(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t)){C(`Condition not met, skipping regex-replace task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file),{pattern:r}=e,i=e.flags??``,a=e.replacement||``,o=await Re(n,`utf-8`),s=new RegExp(r,i);o=o.replace(s,w(a,t)),await ze(n,o)}const Ve={name:`regex-replace`,version:`1.0.0`,taskTypes:[`regex-replace`],execute:async(e,t,n)=>{n.dryRun||await Be(e.config,t)}},He=(0,d.promisify)(c.default.rename);async function Ue(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t)){C(`Condition not met, skipping rename task`,`info`);return}let n=l.default.join(u.default.cwd(),w(e.from,t)),r=l.default.join(u.default.cwd(),w(e.to,t));if(!c.default.existsSync(n)){C(`Source path does not exist: ${n}`,`warn`);return}await He(n,r)}const We={name:`rename`,version:`1.0.0`,taskTypes:[`rename`],execute:async(e,t,n)=>{n.dryRun||await Ue(e.config,t)}},Ge=(0,d.promisify)(c.default.readFile),Ke=(0,d.promisify)(c.default.writeFile);async function qe(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t)){C(`Condition not met, skipping replace-in-file task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file),{replacements:r}=e;if(!c.default.existsSync(n)){C(`File not found: ${n}, skipping`,`warn`);return}let i=await Ge(n,`utf-8`);for(let{find:e,replace:n}of r){let r=w(n,t);i=i.replace(new RegExp(e,`gu`),r)}await Ke(n,i)}const Je={name:`replace-in-file`,version:`1.0.0`,taskTypes:[`replace-in-file`],execute:async(e,t,n)=>{n.dryRun||await qe(e.config,t)}};var K=class e extends _{constructor(e,t,n,r){super(e,`DUPLICATE_ID`),this.id=t,this.type=n,this.existingType=r,this.name=`DuplicateIdError`}static forId(t,n,r){return new e(`Duplicate ID "${t}" found in ${n}. This ID is already used in ${r??`unknown`}`,t,n,r)}},q=class e extends _{constructor(e,t,n,r,i){super(e,`ID_CONFLICT`),this.id=t,this.type=n,this.baseSource=r,this.overrideSource=i,this.name=`IdConflictError`}static forTask(t,n,r){return new e(`Task ID conflict: "${t}" is defined in multiple templates.\n Base task from: ${n??`unknown`}\n Override task from: ${r??`unknown`}\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the task.\n Task is being extended/overridden but no override strategy was specified.`,t,`task`,n,r)}static forVariable(t){return new e(`Variable ID conflict: "${t}" is defined in multiple templates.\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the variable.\n Variable is being extended/overridden but no override strategy was specified.`,t,`variable`)}static forPrompt(t){return new e(`Prompt ID conflict: "${t}" is defined in multiple templates.\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the prompt.\n Prompt is being extended/overridden but no override strategy was specified.`,t,`prompt`)}};const Ye=(0,d.promisify)(c.default.readFile),Xe={template:[[`template`,`templateFile`]]};function J(e){if(e==null||e===``)return`current template`;if(Y(e))return e;let t=u.default.cwd();return e.startsWith(t)?l.default.relative(t,e):e}function Y(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}function Ze(e,t){if(Y(e))return e;if(t==null||t===``)return l.default.isAbsolute(e)?e:l.default.resolve(u.default.cwd(),e);if(Y(t))try{let n=new URL(`.`,t);return new URL(e,n).href}catch{throw ee.forRemoteTemplate(e,t)}let n=l.default.dirname(t);return l.default.isAbsolute(e)?e:l.default.resolve(n,e)}async function Qe(e){if(Y(e))return $e(e);if(!c.default.existsSync(e))throw y.forPath(e);return Ye(e,`utf-8`)}async function $e(e){try{let t=await fetch(e);if(!t.ok)throw te.forUrl(e,t.status,t.statusText);return await t.text()}catch(t){throw t instanceof Error&&t.message.includes(`Failed to fetch`)?t:te.forUrl(e,t instanceof Error?t:void 0)}}const X=new Map;async function et(e,t=new Set){let n=Y(e),r;if(r=n||l.default.isAbsolute(e)?e:l.default.resolve(u.default.cwd(),e),X.has(r))return X.get(r);if(t.has(r))throw v.forTemplateInheritance(t,r);t.add(r);let i;if(n)i=await $e(r);else{if(!c.default.existsSync(r))throw y.forPath(r);i=await Ye(r,`utf-8`)}let a;try{a=JSON.parse(i)}catch(e){throw ne.forFile(r,e instanceof Error?e:Error(String(e)))}if(a.name==null||a.name.trim()===``)throw b.missingName(r);if(!/^[a-z\d]+(?:-[a-z\d]+)*$/u.test(a.name))throw b.invalidNameFormat(r,a.name);if(a.tasks!==void 0&&!Array.isArray(a.tasks))throw b.tasksNotArray(r);a.tasks===void 0&&(a.tasks=[]);for(let e of a.tasks)e.$sourceUrl=r;return X.set(r,a),a}async function Z(e,t,n=new Set){let r=Y(e),i;if(i=r||l.default.isAbsolute(e)?e:t==null?l.default.resolve(u.default.cwd(),e):Y(t)?new URL(e,t).href:l.default.resolve(t,e),n.has(i))throw v.forTemplateInheritance(n,i);n.add(i);let a=await et(i);if(a.extends==null||a.extends===``)return a;let o=Y(i)?new URL(`.`,i).href:l.default.dirname(i),s=Array.isArray(a.extends)?a.extends:[a.extends],c=[];for(let e of s){let t=await Z(e,o,n);c.push(t)}return it([...c,a])}function tt(e,t,n){let r=new Map;for(let t of e){if(r.has(t.id))throw K.forId(t.id,`task`,r.get(t.id));r.set(t.id,`task`)}if(t!=null)for(let e of t){if(r.has(e.id))throw K.forId(e.id,`variable`,r.get(e.id));r.set(e.id,`variable`)}if(n!=null)for(let e of n){if(r.has(e.id))throw K.forId(e.id,`prompt`,r.get(e.id));r.set(e.id,`prompt`)}}function nt(e,t){if((t.override??`merge`)===`replace`){C(` → Variable "${t.id}" using 'replace' strategy`,`info`);let{override:e,...n}=t;return n}C(` → Variable "${t.id}" merged (value replaced)`,`info`);let n={...e,...t};return delete n.override,n}function rt(e,t){if((t.override??`merge`)===`replace`){C(` → Prompt "${t.id}" using 'replace' strategy`,`info`);let{override:e,...n}=t;return n}C(` → Prompt "${t.id}" merged`,`info`);let n={...e,...t};return delete n.override,n}function it(e){if(e.length===0)return{name:`Empty Template`,tasks:[]};if(e.length===1){let t=e[0];return tt(t.tasks??[],t.variables,t.prompts),t}let t=new Map,n=new Map,r=new Map;for(let i of e){if(i.prompts!=null)for(let e of i.prompts)if(r.has(e.id)){if(e.override==null)throw q.forPrompt(e.id);let t=r.get(e.id);r.set(e.id,rt(t,e))}else r.set(e.id,{...e});if(i.variables!=null)for(let e of i.variables)if(n.has(e.id)){if(e.override==null)throw q.forVariable(e.id);let t=n.get(e.id);n.set(e.id,nt(t,e))}else n.set(e.id,{...e});for(let e of i.tasks??[])if(t.has(e.id)){if(e.override==null){let n=t.get(e.id);throw q.forTask(e.id,J(n.$sourceUrl),J(e.$sourceUrl))}let n=t.get(e.id);t.set(e.id,st(n,e))}else t.set(e.id,{...e})}let i=Array.from(t.values()),a=r.size>0?Array.from(r.values()):void 0,o=n.size>0?Array.from(n.values()):void 0;tt(i,o,a);let s=e[e.length-1],c={name:s.name,tasks:i};return s.description!=null&&(c.description=s.description),s.dependencies!=null&&(c.dependencies=s.dependencies),a!=null&&(c.prompts=a),o!=null&&(c.variables=o),c}function at(e,t){let n=Xe[e];if(!n)return null;for(let e of n){let n=e.filter(e=>e in t&&t[e]!=null);if(n.length>1)return n}return null}function ot(e,t,n){let r={...e},i=Xe[n]??[];for(let[e,n]of Object.entries(t)){for(let t of i)if(t.includes(e)){for(let n of t)n!==e&&delete r[n];break}r[e]=n}return r}function st(e,t){if((t.override??`merge`)===`replace`){C(` → Task "${t.id}" using 'replace' strategy - completely replacing base task`,`info`),C(` Base: ${J(e.$sourceUrl)}`,`info`),C(` Override: ${J(t.$sourceUrl)}`,`info`);let{override:n,...r}=t;return r}C(` → Merging task "${t.id}"`,`info`),C(` Base: ${J(e.$sourceUrl)}`,`info`),C(` Override: ${J(t.$sourceUrl)}`,`info`);let n;if(typeof e.config==`object`&&e.config!==null&&typeof t.config==`object`&&t.config!==null){n=ot(e.config,t.config,t.type);let r=at(t.type,n);r!==null&&r.length>0&&(C(` ⚠️ Warning: Conflicting config fields detected: ${r.join(`, `)}`,`warn`),C(` Please use override: "replace" or specify only one of these fields`,`warn`))}else n=t.config??e.config;let r=e.prompts?[...e.prompts]:void 0;if(t.prompts&&t.prompts.length>0)if(!r)r=[...t.prompts];else{let e=new Map(r.map(e=>[e.id,e]));for(let n of t.prompts)e.set(n.id,n);r=Array.from(e.values())}let i=e.variables?[...e.variables]:void 0;if(t.variables&&t.variables.length>0)if(!i)i=[...t.variables];else{let e=new Map(i.map(e=>[e.id,e]));for(let n of t.variables)e.set(n.id,n);i=Array.from(e.values())}let a=[...e.dependencies??[],...t.dependencies??[]],o=a.length>0?[...new Set(a)]:void 0,s=t.$sourceUrl??e.$sourceUrl,c={...e,...t,config:n,...r!=null&&{prompts:r},...i!=null&&{variables:i},...o!=null&&{dependencies:o},...s!=null&&{$sourceUrl:s}};return delete c.override,c}function ct(){X.clear()}async function lt(e){C(`Loading tasks from ${e}...`,`info`);let t=await Z(e);C(`Loaded ${t.tasks?.length??0} task(s)`,`info`),t.extends!=null&&t.extends!==``&&C(`Extended from: ${(Array.isArray(t.extends)?t.extends:[t.extends]).join(`, `)}`,`info`),t.prompts!=null&&t.prompts.length>0&&C(`Found ${t.prompts.length} top-level prompt(s)`,`info`),t.variables!=null&&t.variables.length>0&&C(`Found ${t.variables.length} top-level variable(s)`,`info`);let n={tasks:t.tasks??[]};return t.prompts!=null&&(n.prompts=t.prompts),t.variables!=null&&(n.variables=t.variables),n}const ut=(0,d.promisify)(c.default.writeFile);async function dt(e,t,n){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t)){C(`Condition not met, skipping template task`,`info`);return}let r=l.default.join(u.default.cwd(),e.file),i=e.template!=null&&e.template!==``,a=e.templateFile!=null&&e.templateFile!==``;if(!i&&!a)throw W.templateMissingTemplateOrFile();if(i&&a)throw W.templateHasBothTemplateAndFile();let o;if(a&&e.templateFile.endsWith(`.hbs`)){let r=await Qe(Ze(e.templateFile,n?.$sourceUrl));o=(await import(`handlebars`)).default.compile(r)(t)}else o=w(a?await Qe(Ze(e.templateFile,n?.$sourceUrl)):e.template,t);await ut(r,o)}const ft={name:`template`,version:`1.0.0`,taskTypes:[`template`],execute:async(e,t,n)=>{n.dryRun||await dt(e.config,t,e)}},pt=(0,d.promisify)(c.default.readFile),mt=(0,d.promisify)(c.default.writeFile),ht=2;async function gt(e,t){if(e.condition!=null&&e.condition!==``&&!E(e.condition,t)){C(`Condition not met, skipping update-json task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file),{updates:r}=e,i=await pt(n,`utf-8`),a=JSON.parse(i);function o(e){if(typeof e==`string`)return w(e,t);if(Array.isArray(e))return e.map(e=>o(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=o(r);return t}return e}for(let[e,t]of Object.entries(r)){let n=o(t);e.includes(`.`)?T(a,e,n):a[e]=n}await mt(n,`${JSON.stringify(a,null,2)}\n`)}const _t={name:`update-json`,version:`1.0.0`,taskTypes:[`update-json`],execute:async(e,t,n)=>{n.dryRun||await gt(e.config,t)}};function Q(){B(`update-json`)||(R(_t),R(ft),R(je),R(Ve),R(Je),R(Ne),R(We),R(Le),R(Fe))}async function vt(e,t,n=!1){if(Q(),n){C(`[DRY RUN] Would execute: ${e.name}`,`info`);return}if(B(e.type)){await H(e,t,{dryRun:n});return}throw TypeError(`Unknown task type: ${e.type}`)}async function yt(e,t,n,r,i=!1){try{return C(`[${n}/${r}] Running: ${e.name}...`,`info`),await vt(e,t,i),C(`✓ ${e.name}`,`success`),!0}catch(t){return C(`✗ Failed: ${e.name}`,`error`),t instanceof Error&&(C(` Reason: ${t.message}`,`error`),t.stack!=null&&u.default.env.DEBUG!=null&&console.error(t.stack)),e.required&&C(` This is a required task. Initialization cannot continue.`,`error`),!1}}function $(e){let t=[],n=new Set,r=new Set,i=new Map(e.map(e=>[e.id,e]));function a(e){if(n.has(e))return;if(r.has(e))throw v.forTaskDependency(e);r.add(e);let o=i.get(e);if(!o)throw Te.forId(e);if(o.dependencies)for(let e of o.dependencies)a(e);r.delete(e),n.add(e),t.push(o)}for(let t of e)n.has(t.id)||a(t.id);return t}function bt(e){let t=[];for(let n of e)if(!B(n.type))t.push(`Task "${n.id}" (${n.name}): Unknown task type "${n.type}"`);else if(n.type===`template`){let e=xt(n);t.push(...e)}return t}function xt(e){let t=[],n=e.config,r=n.template!=null&&n.template!==``,i=n.templateFile!=null&&n.templateFile!==``;return!r&&!i&&t.push(`Task "${e.id}" (${e.name}): Template task requires either "template" (inline) or "templateFile" (file path) to be specified`),r&&i&&t.push(`Task "${e.id}" (${e.name}): Template task cannot have both "template" and "templateFile" specified. Use one or the other.`),(n.file==null||n.file===``)&&t.push(`Task "${e.id}" (${e.name}): Template task requires "file" property to specify the output file path`),t}function St(e){C(`❌ Template validation failed:`,`error`),C(``,`error`);for(let t of e)C(` • ${t}`,`error`);C(``,`error`),C(`Please fix these errors before continuing.`,`error`)}function Ct(e,t=new Map){let n={};for(let r of e){let e=t.get(r.id);e!==void 0&&(n[r.id]=e)}return n}async function wt(e,t){if(e==null)return;if(typeof e!=`object`||!e||Array.isArray(e))return e;let n=e;if(n.type===`exec`){let e=n.value;if(typeof e!=`string`){C(`Variable "${t}": exec value must have a string command`,`error`);return}try{let t=(0,f.execSync)(e,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:1e4}).trim();if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return t}if(/^-?\d+(?:\.\d+)?$/u.test(t)){let e=Number.parseFloat(t);if(!Number.isNaN(e))return e}return t===`true`||t===`false`?t===`true`:t}catch(e){C(`Variable "${t}": failed to execute command: ${e instanceof Error?e.message:`Unknown error`}`,`warn`);return}}else if(n.type===`static`)return n.value;return e}async function Tt(e){let t=new Map,n=e.map(async e=>{let t=await wt(e.value,e.id);return{id:e.id,value:t}}),r=await Promise.all(n);for(let e of r)e.value!==void 0&&t.set(e.id,e.value);return t}function Et(e){let t=[],n=new Set;for(let r of e)if(n.has(r.id)&&t.push(`Duplicate variable ID: "${r.id}"`),n.add(r.id),/^[\w$]+$/u.test(r.id)||t.push(`Variable ID "${r.id}" is invalid. Must contain only letters, numbers, underscore, or dollar sign.`),r.value===void 0||r.value===null)t.push(`Variable "${r.id}" must have a value`);else if(typeof r.value==`object`&&!Array.isArray(r.value)&&r.value!==null){let e=r.value;e.type==null||e.type===``?t.push(`Variable "${r.id}": value object must have a "type" field ("static" or "exec")`):e.type!==`static`&&e.type!==`exec`&&t.push(`Variable "${r.id}": type must be "static" or "exec", got "${e.type}"`),(e.value===void 0||e.value===null)&&t.push(`Variable "${r.id}": value config must have a "value" field`),e.type===`exec`&&typeof e.value!=`string`&&t.push(`Variable "${r.id}": exec type must have a string command as value`)}return t}async function Dt(e,t){Q(),C(`Validating task configurations...`,`info`);let n=bt(e);n.length>0&&(St(n),u.default.exit(1)),C(`✓ All tasks validated successfully`,`success`);let r=e.filter(e=>x(e.enabled,g()));C(`Resolving task dependencies...`,`info`);let i=$(r);C(`Welcome! Let's execute your tasks.`,`info`),t.dryRun&&C(`🔍 DRY RUN MODE - No changes will be made`,`warn`),C(`This will execute your project tasks based on the defined configuration.`,`info`);let a=g(),o=t.globalVariables??[],s=[],c=[...o];for(let e of i)if(e.variables&&e.variables.length>0)for(let t of e.variables)s.push(t),c.push(t);if(c.length>0){let e=Et(c);e.length>0&&(C(`❌ Variable validation errors:`,`error`),e.forEach(e=>C(` - ${e}`,`error`)),u.default.exit(1)),C(`Resolving variable values...`,`info`);let t=Ct(c,await Tt(c));Object.assign(a,t),Object.keys(t).length>0&&C(`✓ Resolved ${Object.keys(t).length} variable(s)`,`success`)}let l=t.globalPrompts??[],d=[],f=[...l];for(let e of i)if(e.prompts&&e.prompts.length>0)for(let t of e.prompts)d.push(t),f.push(t);if(f.length>0){let e=Oe(f);e.length>0&&(C(`❌ Prompt validation errors:`,`error`),e.forEach(e=>C(` - ${e}`,`error`)),u.default.exit(1)),C(`Resolving prompt default values...`,`info`);let t=await De(f),n={};if(l.length>0&&(C(`📋 Top-level prompts (available to all tasks):`,`info`),n=await G(l,t,a),Object.assign(a,n)),d.length>0){l.length>0&&C(`📋 Task-specific prompts:`,`info`);let e=await G(d,t,a);Object.assign(a,e)}}let p=i.filter(e=>x(e.enabled,a));if(C(`${p.length} of ${i.length} task(s) enabled for execution`,`info`),t.dryRun){await P(p,a),C(`🔍 Dry run completed - no changes were made`,`info`),C(`Run without --dry-run to apply changes`,`info`);return}C(`Starting task execution...`,`info`),await V(`beforeAll`,a);let m=p.length,h=0,_=0,v=[];for(let e=0;e<p.length;e++){let n=p[e];if(n!=null)if(await V(`beforeTask`,n,a),await yt(n,a,e+1,m,t.dryRun))h++,v.push(n.id),await V(`afterTask`,n,a);else if(n.required){_++,await V(`onError`,Error(`Task ${n.name} failed`),n);break}else C(`⚠️ Non-critical task failed, continuing...`,`warn`),await V(`onError`,Error(`Task ${n.name} failed`),n)}_>0&&(C(`❌ Task execution failed with ${_} critical error(s)`,`error`),C(`✓ Completed: ${h}/${m} tasks`,`info`),u.default.exit(1)),await V(`afterAll`,a),C(`✅ All tasks completed successfully!`,`success`),C(`✓ Completed: ${h}/${m} tasks`,`success`),t.dryRun||(C(`Next steps:`,`info`),C(`1. Review the changes made to your project`,`info`),C(`2. Commit the changes to git`,`info`))}const Ot=u.default.argv.includes(`--dry-run`),kt=u.default.argv.includes(`--force`);async function At(e){try{let t=e||[];t.length===0&&(C(`⚠️ No tasks defined. Use --tasks-file to specify tasks or call runWithTasks() programmatically.`,`warn`),C(`Example: scaffoldfy --tasks-file ./tasks.json`,`info`),u.default.exit(1)),await Dt(t,{dryRun:Ot,force:kt,tasksFilePath:void 0})}catch(e){C(`❌ Task execution failed`,`error`),e instanceof Error?(C(`Error: ${e.message}`,`error`),u.default.env.DEBUG!=null&&console.error(e.stack)):console.error(e),u.default.exit(1)}}async function jt(e,t){try{await Dt(e,{dryRun:t?.dryRun??Ot,force:t?.force??kt,tasksFilePath:t?.tasksFilePath??void 0,...t?.globalVariables!=null&&{globalVariables:t.globalVariables},...t?.globalPrompts!=null&&{globalPrompts:t.globalPrompts}})}catch(e){C(`❌ Task execution failed`,`error`),e instanceof Error?(C(`Error: ${e.message}`,`error`),u.default.env.DEBUG!=null&&console.error(e.stack)):console.error(e),u.default.exit(1)}}Object.defineProperty(exports,`A`,{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,`B`,{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,`C`,{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,`D`,{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,`E`,{enumerable:!0,get:function(){return Se}}),Object.defineProperty(exports,`F`,{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,`G`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`H`,{enumerable:!0,get:function(){return ue}}),Object.defineProperty(exports,`I`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`J`,{enumerable:!0,get:function(){return ie}}),Object.defineProperty(exports,`K`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`L`,{enumerable:!0,get:function(){return pe}}),Object.defineProperty(exports,`M`,{enumerable:!0,get:function(){return Ce}}),Object.defineProperty(exports,`N`,{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,`O`,{enumerable:!0,get:function(){return ye}}),Object.defineProperty(exports,`P`,{enumerable:!0,get:function(){return he}}),Object.defineProperty(exports,`R`,{enumerable:!0,get:function(){return ge}}),Object.defineProperty(exports,`S`,{enumerable:!0,get:function(){return we}}),Object.defineProperty(exports,`T`,{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,`U`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`V`,{enumerable:!0,get:function(){return de}}),Object.defineProperty(exports,`W`,{enumerable:!0,get:function(){return re}}),Object.defineProperty(exports,`X`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`Y`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return De}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return wt}}),Object.defineProperty(exports,`b`,{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return vt}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return ct}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return Z}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return Oe}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return it}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return Tt}}),Object.defineProperty(exports,`j`,{enumerable:!0,get:function(){return _e}}),Object.defineProperty(exports,`k`,{enumerable:!0,get:function(){return xe}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return Q}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return et}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return jt}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return Ct}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return lt}}),Object.defineProperty(exports,`q`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return Et}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return At}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return yt}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return Ee}}),Object.defineProperty(exports,`w`,{enumerable:!0,get:function(){return ve}}),Object.defineProperty(exports,`x`,{enumerable:!0,get:function(){return be}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return G}}),Object.defineProperty(exports,`z`,{enumerable:!0,get:function(){return me}});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixpilot/scaffoldfy",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.16.0",
|
|
5
5
|
"author": "PixPilot <m.doaie@hotmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"tsdown": "^0.15.8",
|
|
48
48
|
"typescript": "^5.9.3",
|
|
49
49
|
"@internal/eslint-config": "0.3.0",
|
|
50
|
-
"@internal/tsdown-config": "0.1.0",
|
|
51
50
|
"@internal/prettier-config": "0.0.1",
|
|
52
51
|
"@internal/tsconfig": "0.1.0",
|
|
52
|
+
"@internal/tsdown-config": "0.1.0",
|
|
53
53
|
"@internal/vitest-config": "0.1.0"
|
|
54
54
|
},
|
|
55
55
|
"prettier": "@internal/prettier-config",
|
package/schema/tasks.schema.json
CHANGED
|
@@ -3,7 +3,24 @@
|
|
|
3
3
|
"title": "Template Tasks Configuration",
|
|
4
4
|
"description": "Configuration for template task automation and cleanup",
|
|
5
5
|
"type": "object",
|
|
6
|
+
"required": ["name"],
|
|
6
7
|
"properties": {
|
|
8
|
+
"name": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Unique identifier name for this template. Must contain only lowercase letters, digits, and hyphens. Cannot start or end with a hyphen.",
|
|
11
|
+
"pattern": "^[a-z\\d]+(?:-[a-z\\d]+)*$"
|
|
12
|
+
},
|
|
13
|
+
"description": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Detailed description of what this template does"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"items": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
},
|
|
22
|
+
"description": "Names or identifiers of other templates that this template depends on"
|
|
23
|
+
},
|
|
7
24
|
"extends": {
|
|
8
25
|
"description": "Base template file(s) to extend from. Can be a local path or URL (http/https). Supports single path or array of paths.",
|
|
9
26
|
"oneOf": [
|
package/dist/src-1wb6PUAF.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import e from"node:path";import t from"node:fs";import n from"node:process";import{promisify as r}from"node:util";import{execSync as i}from"node:child_process";import a from"node:readline";import o from"handlebars";import{confirm as s,input as c,number as l,password as u,select as d}from"@inquirer/prompts";function f(){return{}}function p(e,t){return e===void 0?!0:typeof e==`boolean`?e:typeof e==`object`&&`condition`in e?b(e.condition,t):!1}function m(){try{let e=i(`git remote get-url origin`,{encoding:`utf-8`}).trim(),t=e.match(/github\.com[:/](?<owner>[^/]+)\/(?<name>[^/]+)$/u);if(t?.groups){let{owner:n,name:r}=t.groups,i=r;return i.endsWith(`.git`)&&(i=i.slice(0,-4)),{owner:n,name:i,url:e}}return null}catch{return null}}async function h(e,t){let r=a.createInterface({input:n.stdin,output:n.stdout});return new Promise(n=>{let i;i=t==null?`${e}: `:`${e} (${t}): `,r.question(i,e=>{r.close(),n(e.trim()||(t??``))})})}async function g(e,t=!1){return h(`${e} (${t?`Y/n`:`y/N`})`,t?`y`:`n`).then(e=>e.toLowerCase()===`y`||e.toLowerCase()===`yes`)}function _(e,t=`info`){console.log(`${{info:`\x1B[36m`,success:`\x1B[32m`,error:`\x1B[31m`,warn:`\x1B[33m`}[t]}${{info:`ℹ`,success:`✓`,error:`✗`,warn:`⚠`}[t]} ${e}[0m`)}function v(e,t){return e.replace(/\{\{(?<key>\w+)\}\}/gu,(e,n)=>t[n]?.toString()??``)}function y(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++){let t=r[e];t!=null&&t!==``&&((!(t in i)||typeof i[t]!=`object`||i[t]===null)&&(i[t]={}),i=i[t])}let a=r[r.length-1];a!=null&&a!==``&&(i[a]=n)}function b(e,t){try{let n={...t};return Function(...Object.keys(n),`'use strict'; return (${e})`)(...Object.values(n))}catch(t){return _(`Failed to evaluate condition: ${e}`,`warn`),t instanceof Error&&_(` Error: ${t.message}`,`warn`),!1}}function ee(r,i){try{let a=e.isAbsolute(r)?r:e.join(n.cwd(),r);if(!t.existsSync(a))throw Error(`Template file not found: ${r}`);return te(t.readFileSync(a,`utf-8`),i)}catch(e){throw _(`Failed to read template file: ${r}`,`error`),e instanceof Error&&_(` Error: ${e.message}`,`error`),e}}function te(e,t){try{return o.compile(e)(t)}catch(e){throw _(`Failed to compile Handlebars template`,`error`),e instanceof Error&&_(` Error: ${e.message}`,`error`),e}}const x=r(t.readFile),S={reset:`\x1B[0m`,red:`\x1B[31m`,green:`\x1B[32m`,yellow:`\x1B[33m`,blue:`\x1B[34m`,cyan:`\x1B[36m`,gray:`\x1B[90m`};function C(e,t){switch(t){case`add`:return`${S.green}+ ${e}${S.reset}`;case`remove`:return`${S.red}- ${e}${S.reset}`;case`context`:return`${S.gray} ${e}${S.reset}`;default:return e}}function w(e,t){let n=e.split(`
|
|
2
|
-
`),r=t.split(`
|
|
3
|
-
`),i=[],a=Math.max(n.length,r.length);for(let e=0;e<a;e++){let t=n[e],a=r[e];t===a?t!==void 0&&i.push(C(t,`context`)):(t!==void 0&&i.push(C(t,`remove`)),a!==void 0&&i.push(C(a,`add`)))}return i}async function ne(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${S.yellow}⊘ Condition not met - task would be skipped${S.reset}`;let a=e.join(n.cwd(),r.file);if(!t.existsSync(a))return`${S.red}✗ File not found: ${r.file}${S.reset}`;try{let e=await x(a,`utf-8`),t=JSON.parse(e),n={...t};function o(e){if(typeof e==`string`)return v(e,i);if(Array.isArray(e))return e.map(e=>o(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=o(r);return t}return e}for(let[e,n]of Object.entries(r.updates)){let r=o(n);e.includes(`.`)?y(t,e,r):t[e]=r}let s=JSON.stringify(n,null,2),c=JSON.stringify(t,null,2);if(s===c)return`${S.cyan}→ No changes${S.reset}`;let l=w(s,c);return`${S.blue}File: ${r.file}${S.reset}\n${l.join(`
|
|
4
|
-
`)}`}catch(e){return`${S.red}✗ Error: ${e instanceof Error?e.message:String(e)}${S.reset}`}}async function T(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${S.yellow}⊘ Condition not met - task would be skipped${S.reset}`;if(r.template==null||r.template===``)return`${S.red}✗ No template content provided for file: ${r.file}${S.reset}`;let a=e.join(n.cwd(),r.file),o=v(r.template,i);if(!t.existsSync(a)){let e=o.split(`
|
|
5
|
-
`).slice(0,10).join(`
|
|
6
|
-
`),t=o.split(`
|
|
7
|
-
`).length>10;return`${S.blue}File: ${r.file}${S.reset}\n${S.green}+ New file would be created${S.reset}\n${S.gray}Content preview:${S.reset}\n${e}${t?`
|
|
8
|
-
...`:``}`}try{let e=await x(a,`utf-8`);if(e===o)return`${S.cyan}→ No changes${S.reset}`;let t=w(e,o);return`${S.blue}File: ${r.file}${S.reset}\n${t.join(`
|
|
9
|
-
`)}`}catch(e){return`${S.red}✗ Error: ${e instanceof Error?e.message:String(e)}${S.reset}`}}async function re(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${S.yellow}⊘ Condition not met - task would be skipped${S.reset}`;let a=e.join(n.cwd(),r.file);if(t.existsSync(a))return`${S.cyan}→ File already exists, would be skipped: ${r.file}${S.reset}`;let o=r.template!=null&&r.template!==``,s=r.templateFile!=null&&r.templateFile!==``;if(!o&&!s)return`${S.red}✗ No template content provided for file: ${r.file}${S.reset}`;try{let e;if(o)e=v(r.template,i);else return`${S.blue}File: ${r.file}${S.reset}\n${S.green}+ New file would be created from template: ${r.templateFile}${S.reset}`;let t=e.split(`
|
|
10
|
-
`).slice(0,10).join(`
|
|
11
|
-
`),n=e.split(`
|
|
12
|
-
`).length>10;return`${S.blue}File: ${r.file}${S.reset}\n${S.green}+ New file would be created${S.reset}\n${S.gray}Content preview:${S.reset}\n${t}${n?`
|
|
13
|
-
...`:``}`}catch(e){return`${S.red}✗ Error: ${e instanceof Error?e.message:String(e)}${S.reset}`}}async function E(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${S.yellow}⊘ Condition not met - task would be skipped${S.reset}`;let a=e.join(n.cwd(),r.file);if(!t.existsSync(a))return`${S.red}✗ File not found: ${r.file}${S.reset}`;try{let e=await x(a,`utf-8`),t=new RegExp(r.pattern,r.flags??`g`),n=v(r.replacement,i),o=e.replace(t,n);if(e===o)return`${S.cyan}→ No matches found${S.reset}`;let s=w(e,o);return`${S.blue}File: ${r.file}${S.reset}\n${s.join(`
|
|
14
|
-
`)}`}catch(e){return`${S.red}✗ Error: ${e instanceof Error?e.message:String(e)}${S.reset}`}}async function D(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${S.yellow}⊘ Condition not met - task would be skipped${S.reset}`;let a=e.join(n.cwd(),r.file);if(!t.existsSync(a))return`${S.red}✗ File not found: ${r.file}${S.reset}`;try{let e=await x(a,`utf-8`),t=e;for(let{find:t,replace:n}of r.replacements){let r=v(t,i),a=v(n,i);e=e.replace(r,a)}if(t===e)return`${S.cyan}→ No changes${S.reset}`;let n=w(t,e);return`${S.blue}File: ${r.file}${S.reset}\n${n.join(`
|
|
15
|
-
`)}`}catch(e){return`${S.red}✗ Error: ${e instanceof Error?e.message:String(e)}${S.reset}`}}function O(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${S.yellow}⊘ Condition not met - task would be skipped${S.reset}`;let a=r.paths.map(e=>v(e,i)).filter(r=>t.existsSync(e.join(n.cwd(),r)));return a.length===0?`${S.cyan}→ No files/directories to delete${S.reset}`:`${S.red}Would delete:${S.reset}\n${a.map(e=>`${S.red} - ${e}${S.reset}`).join(`
|
|
16
|
-
`)}`}function k(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${S.yellow}⊘ Condition not met - task would be skipped${S.reset}`;let a=v(r.from,i),o=v(r.to,i),s=e.join(n.cwd(),a),c=e.join(n.cwd(),o);return t.existsSync(s)?t.existsSync(c)?`${S.yellow}⚠ Destination already exists: ${o}${S.reset}\n${S.cyan}Would rename: ${a} → ${o}${S.reset}`:`${S.cyan}Would rename: ${a} → ${o}${S.reset}`:`${S.red}✗ Source not found: ${a}${S.reset}`}function A(r){if(r.condition!=null&&r.condition!==``)return`${S.yellow}⊘ Condition check skipped in dry-run${S.reset}`;let i=e.join(n.cwd(),`.git`),a=t.existsSync(i),o=[];if(r.removeExisting&&a&&o.push(`${S.red}Would remove existing .git directory${S.reset}`),o.push(`${S.green}Would initialize git repository${S.reset}`),r.initialCommit){let e=r.message??`Initial commit`;o.push(`${S.green}Would create initial commit: "${e}"${S.reset}`)}return o.join(`
|
|
17
|
-
`)}function ie(e,t){if(e.condition!=null&&e.condition!==``&&!b(e.condition,t))return`${S.yellow}⊘ Condition not met - task would be skipped${S.reset}`;let r=v(e.command,t),i=e.cwd==null?n.cwd():v(e.cwd,t);return`${S.yellow}Would execute:${S.reset}\n${S.cyan} Command: ${r}${S.reset}\n${S.cyan} Working directory: ${i}${S.reset}`}async function j(e,t){try{switch(e.type){case`update-json`:return await ne(e.config,t);case`template`:return await T(e.config,t);case`create`:return await re(e.config,t);case`regex-replace`:return await E(e.config,t);case`replace-in-file`:return await D(e.config,t);case`delete`:return O(e.config,t);case`rename`:return k(e.config,t);case`git-init`:return A(e.config);case`exec`:return ie(e.config,t);default:{let t=e.type;return`${S.yellow}⚠ Diff not available for task type: ${t}${S.reset}`}}}catch(e){return`${S.red}✗ Error generating diff: ${e instanceof Error?e.message:String(e)}${S.reset}`}}async function M(e,t){console.log(`${S.blue}═══════════════════════════════════════════════════════${S.reset}`),console.log(`${S.blue} DRY RUN - Preview of changes${S.reset}`),console.log(`${S.blue}═══════════════════════════════════════════════════════${S.reset}`);for(let n of e){console.log(`${S.cyan}▶ Task: ${n.name}${S.reset}`),console.log(`${S.gray} ${n.description}${S.reset}`);let e=await j(n,t);console.log(e),console.log(`${S.gray}${`─`.repeat(55)}${S.reset}`)}console.log(`${S.blue}═══════════════════════════════════════════════════════${S.reset}`),console.log(`${S.yellow} No changes were applied (dry-run mode)${S.reset}`),console.log(`${S.blue}═══════════════════════════════════════════════════════${S.reset}`)}const N=new Map,P={},F=new Map;function I(e){if(e.name==null||e.name===``)throw TypeError(`Plugin name is required`);if(!Array.isArray(e.taskTypes)||e.taskTypes.length===0)throw TypeError(`Plugin ${e.name} must define at least one task type`);if(typeof e.execute!=`function`)throw TypeError(`Plugin ${e.name} must provide an execute function`);if(N.has(e.name))throw TypeError(`Plugin ${e.name} is already registered`);for(let t of e.taskTypes)if(F.has(t)){let e=F.get(t);throw TypeError(`Task type "${t}" is already registered by plugin "${e}"`)}N.set(e.name,e);for(let t of e.taskTypes)F.set(t,e.name);_(`✓ Registered plugin: ${e.name}${e.version==null?``:` v${e.version}`}`,`info`)}function ae(e){let t=N.get(e);if(t!=null){for(let e of t.taskTypes)F.delete(e);N.delete(e)}}function oe(e){return N.get(e)}function L(e){let t=F.get(e);if(t!=null)return N.get(t)}function R(e){return F.has(e)}function se(){return Array.from(N.keys())}function ce(){N.clear(),F.clear()}function le(e){e.beforeAll!=null&&(P.beforeAll=e.beforeAll),e.afterAll!=null&&(P.afterAll=e.afterAll),e.beforeTask!=null&&(P.beforeTask=e.beforeTask),e.afterTask!=null&&(P.afterTask=e.afterTask),e.onError!=null&&(P.onError=e.onError)}async function z(e,...t){let n=P[e];if(n!=null)try{e===`beforeAll`||e===`afterAll`?await n(t[0]):(e===`beforeTask`||e===`afterTask`||e===`onError`)&&await n(t[0],t[1])}catch(t){_(`Error in ${e} hook: ${t instanceof Error?t.message:String(t)}`,`error`)}}async function B(e,t,n){let r=L(e.type);if(r==null)throw TypeError(`No plugin found for task type: ${e.type}`);await r.execute(e,t,n)}async function ue(e,t){let n=L(e.type);if(!(n==null||n.getDiff==null))return n.getDiff(e,t)}function de(e){let t=L(e.type);return t==null?[`No plugin found for task type: ${e.type}`]:t.validate==null?[]:t.validate(e)}function fe(e,t,n,r){return{name:e,...r?.version!=null&&{version:r.version},taskTypes:[t],execute:n,...r?.getDiff!=null&&{getDiff:r.getDiff},...r?.validate!=null&&{validate:r.validate}}}async function V(e,t=new Map,n={}){let r={};if(e.length===0)return r;for(let i of e){let e={...n,...r};if(p(i.enabled,e))try{let e,n=t.get(i.id);switch(i.type){case`input`:{let t={message:i.message};if(n!==void 0&&(t.default=String(n)),i.required!==void 0&&(t.required=i.required),e=await c(t),i.required&&(e==null||typeof e==`string`&&e.trim()===``))throw _(`${i.message} is required`,`error`),Error(`Prompt "${i.id}" is required`);break}case`password`:if(e=await u({message:i.message,mask:`*`}),i.required&&(e==null||typeof e==`string`&&e.trim()===``))throw _(`${i.message} is required`,`error`),Error(`Prompt "${i.id}" is required`);break;case`number`:{let t={message:i.message};if(n!==void 0&&(t.default=Number(n)),i.required!==void 0&&(t.required=i.required),i.min!==void 0&&(t.min=i.min),i.max!==void 0&&(t.max=i.max),e=await l(t),i.required&&e==null)throw _(`${i.message} is required`,`error`),Error(`Prompt "${i.id}" is required`);break}case`select`:{let t={message:i.message,choices:i.choices.map(e=>({name:e.name,value:e.value}))};n!==void 0&&(t.default=n),e=await d(t);break}case`confirm`:{let t=n===void 0?!1:!!n;e=await s({message:i.message,default:t});break}default:throw _(`Unknown prompt type: ${i.type}`,`error`),Error(`Unknown prompt type: ${i.type}`)}r[i.id]=e}catch(e){throw e instanceof Error&&_(`Failed to collect prompt "${i.id}": ${e.message}`,`error`),e}}return r}async function H(e,t){if(e===void 0)return;if(typeof e!=`object`||!e||Array.isArray(e))return e;let n=e;if(n.type===`exec`){let e=n.value;if(typeof e!=`string`){_(`Prompt "${t}": exec default value must have a string command`,`error`);return}try{let t=i(e,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:1e4}).trim();if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return t}if(/^-?\d+(?:\.\d+)?$/u.test(t)){let e=Number.parseFloat(t);if(!Number.isNaN(e))return e}return t===`true`||t===`false`?t===`true`:t}catch(e){_(`Prompt "${t}": failed to execute default value command: ${e instanceof Error?e.message:`Unknown error`}`,`warn`);return}}else if(n.type===`static`)return n.value;return e}async function U(e){let t=new Map,n=e.map(async e=>{if(e.default!==void 0){let n=await H(e.default,e.id);n!==void 0&&t.set(e.id,n)}});return await Promise.all(n),t}function W(e){let t=[],n=new Set;for(let r of e){if(n.has(r.id)&&t.push(`Duplicate prompt ID: ${r.id}`),n.add(r.id),/^[\w-]+$/u.test(r.id)||t.push(`Invalid prompt ID "${r.id}": must contain only alphanumeric characters, underscores, and hyphens`),(!r.message||r.message.trim()===``)&&t.push(`Prompt "${r.id}" must have a non-empty message`),r.type===`select`){r.choices.length===0&&t.push(`Select prompt "${r.id}" must have at least one choice`);for(let e of r.choices)(!e.name||e.name.trim()===``)&&t.push(`Select prompt "${r.id}" has a choice with empty name`),e.value===void 0&&t.push(`Select prompt "${r.id}" has a choice with undefined value`)}r.type===`number`&&r.min!==void 0&&r.max!==void 0&&r.min>r.max&&t.push(`Number prompt "${r.id}" has min greater than max`)}return t}const pe=r(t.writeFile);async function me(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i)){_(`Condition not met, skipping create task`,`info`);return}let a=e.join(n.cwd(),r.file);if(t.existsSync(a)){_(`File already exists, skipping: ${r.file}`,`info`);return}let o=r.template!=null&&r.template!==``,s=r.templateFile!=null&&r.templateFile!==``;if(!o&&!s)throw Error(`Create task requires either "template" (inline) or "templateFile" (file path) to be specified`);if(o&&s)throw Error(`Create task cannot have both "template" and "templateFile" specified. Use one or the other.`);let c;if(s&&r.templateFile.endsWith(`.hbs`))c=ee(r.templateFile,i);else if(s){let a=r.templateFile,o=e.isAbsolute(a)?a:e.join(n.cwd(),a);if(!t.existsSync(o))throw Error(`Template file not found: ${a}`);c=v(t.readFileSync(o,`utf-8`),i)}else c=v(r.template,i);let l=e.dirname(a);t.existsSync(l)||t.mkdirSync(l,{recursive:!0}),await pe(a,c),_(`Created file: ${r.file}`,`success`)}const he={name:`create`,version:`1.0.0`,taskTypes:[`create`],execute:async(e,t,n)=>{n.dryRun||await me(e.config,t)}};async function ge(r,i){let{paths:a,condition:o}=r;if(o!=null&&o!==``){if(!i){_(`Condition specified but no config provided, skipping deletion`,`warn`);return}if(!b(o,i)){_(`Condition not met, skipping deletion`,`info`);return}}for(let r of a){let i=e.join(n.cwd(),r);t.existsSync(i)&&t.rmSync(i,{recursive:!0,force:!0})}}const _e={name:`delete`,version:`1.0.0`,taskTypes:[`delete`],execute:async(e,t,n)=>{n.dryRun||await ge(e.config,t)}};async function ve(t,r){if(t.condition!=null&&t.condition!==``){if(!r){_(`Condition specified but no config provided, skipping exec`,`warn`);return}if(!b(t.condition,r)){_(`Condition not met, skipping exec task`,`info`);return}}let a=t.cwd==null?n.cwd():e.join(n.cwd(),t.cwd);i(t.command,{cwd:a,stdio:`inherit`})}const ye={name:`exec`,version:`1.0.0`,taskTypes:[`exec`],execute:async(e,t,n)=>{n.dryRun||await ve(e.config,t)}};async function be(r,a){if(r.condition!=null&&r.condition!==``){if(!a){_(`Condition specified but no config provided, skipping git-init`,`warn`);return}if(!b(r.condition,a)){_(`Condition not met, skipping git-init task`,`info`);return}}if(r.removeExisting){let r=e.join(n.cwd(),`.git`);t.existsSync(r)&&t.rmSync(r,{recursive:!0,force:!0})}if(i(`git init`,{stdio:`inherit`}),r.initialCommit){let e=r.message??`Initial commit`;i(`git add .`,{stdio:`inherit`}),i(`git commit -m "${e}"`,{stdio:`inherit`})}}const xe={name:`git-init`,version:`1.0.0`,taskTypes:[`git-init`],execute:async(e,t,n)=>{n.dryRun||await be(e.config,t)}},Se=r(t.readFile),Ce=r(t.writeFile);async function we(t,r){if(t.condition!=null&&t.condition!==``&&!b(t.condition,r)){_(`Condition not met, skipping regex-replace task`,`info`);return}let i=e.join(n.cwd(),t.file),{pattern:a}=t,o=t.flags??``,s=t.replacement||``,c=await Se(i,`utf-8`),l=new RegExp(a,o);c=c.replace(l,v(s,r)),await Ce(i,c)}const Te={name:`regex-replace`,version:`1.0.0`,taskTypes:[`regex-replace`],execute:async(e,t,n)=>{n.dryRun||await we(e.config,t)}},Ee=r(t.rename);async function De(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i)){_(`Condition not met, skipping rename task`,`info`);return}let a=e.join(n.cwd(),v(r.from,i)),o=e.join(n.cwd(),v(r.to,i));if(!t.existsSync(a)){_(`Source path does not exist: ${a}`,`warn`);return}await Ee(a,o)}const Oe={name:`rename`,version:`1.0.0`,taskTypes:[`rename`],execute:async(e,t,n)=>{n.dryRun||await De(e.config,t)}},ke=r(t.readFile),Ae=r(t.writeFile);async function je(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i)){_(`Condition not met, skipping replace-in-file task`,`info`);return}let a=e.join(n.cwd(),r.file),{replacements:o}=r;if(!t.existsSync(a)){_(`File not found: ${a}, skipping`,`warn`);return}let s=await ke(a,`utf-8`);for(let{find:e,replace:t}of o){let n=v(t,i);s=s.replace(new RegExp(e,`gu`),n)}await Ae(a,s)}const Me={name:`replace-in-file`,version:`1.0.0`,taskTypes:[`replace-in-file`],execute:async(e,t,n)=>{n.dryRun||await je(e.config,t)}},G=r(t.readFile),K={template:[[`template`,`templateFile`]]};function q(t){if(t==null||t===``)return`current template`;if(J(t))return t;let r=n.cwd();return t.startsWith(r)?e.relative(r,t):t}function J(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}function Y(t,r){if(J(t))return t;if(r==null||r===``)return e.isAbsolute(t)?t:e.resolve(n.cwd(),t);if(J(r))try{let e=new URL(`.`,r);return new URL(t,e).href}catch{throw Error(`Failed to resolve templateFile "${t}" relative to remote template "${r}"`)}let i=e.dirname(r);return e.isAbsolute(t)?t:e.resolve(i,t)}async function X(e){if(J(e))return Z(e);if(!t.existsSync(e))throw Error(`Template file not found: ${e}`);return G(e,`utf-8`)}async function Z(e){try{let t=await fetch(e);if(!t.ok)throw Error(`Failed to fetch template from ${e}: ${t.status} ${t.statusText}`);return await t.text()}catch(t){throw t instanceof Error&&t.message.includes(`Failed to fetch`)?t:Error(`Failed to fetch template from ${e}: ${t instanceof Error?t.message:String(t)}`)}}const Q=new Map;async function Ne(r,i=new Set){let a=J(r),o;if(o=a||e.isAbsolute(r)?r:e.resolve(n.cwd(),r),Q.has(o))return Q.get(o);if(i.has(o))throw Error(`Circular dependency detected: ${Array.from(i).join(` -> `)} -> ${o}`);i.add(o);let s;if(a)s=await Z(o);else{if(!t.existsSync(o))throw Error(`Template file not found: ${o}`);s=await G(o,`utf-8`)}let c;try{c=JSON.parse(s)}catch(e){throw Error(`Failed to parse template file ${o}: ${e instanceof Error?e.message:String(e)}`)}if(c.tasks!==void 0&&!Array.isArray(c.tasks))throw TypeError(`Invalid template file ${o}: 'tasks' must be an array if provided`);c.tasks===void 0&&(c.tasks=[]);for(let e of c.tasks)e.$sourceUrl=o;return Q.set(o,c),c}async function $(t,r,i=new Set){let a=J(t),o;if(o=a||e.isAbsolute(t)?t:r==null?e.resolve(n.cwd(),t):J(r)?new URL(t,r).href:e.resolve(r,t),i.has(o))throw Error(`Circular dependency detected: ${Array.from(i).join(` -> `)} -> ${o}`);i.add(o);let s=await Ne(o);if(s.extends==null||s.extends===``)return s;let c=J(o)?new URL(`.`,o).href:e.dirname(o),l=Array.isArray(s.extends)?s.extends:[s.extends],u=[];for(let e of l){let t=await $(e,c,i);u.push(t)}return Le([...u,s])}function Pe(e,t,n){let r=new Map;for(let t of e){if(r.has(t.id))throw Error(`Duplicate ID "${t.id}" found in task. This ID is already used in ${r.get(t.id)}`);r.set(t.id,`task`)}if(t!=null)for(let e of t){if(r.has(e.id))throw Error(`Duplicate ID "${e.id}" found in variable. This ID is already used in ${r.get(e.id)}`);r.set(e.id,`variable`)}if(n!=null)for(let e of n){if(r.has(e.id))throw Error(`Duplicate ID "${e.id}" found in prompt. This ID is already used in ${r.get(e.id)}`);r.set(e.id,`prompt`)}}function Fe(e,t){if((t.override??`merge`)===`replace`){_(` → Variable "${t.id}" using 'replace' strategy`,`info`);let{override:e,...n}=t;return n}_(` → Variable "${t.id}" merged (value replaced)`,`info`);let n={...e,...t};return delete n.override,n}function Ie(e,t){if((t.override??`merge`)===`replace`){_(` → Prompt "${t.id}" using 'replace' strategy`,`info`);let{override:e,...n}=t;return n}_(` → Prompt "${t.id}" merged`,`info`);let n={...e,...t};return delete n.override,n}function Le(e){if(e.length===0)return{tasks:[]};if(e.length===1){let t=e[0];return Pe(t.tasks??[],t.variables,t.prompts),t}let t=new Map,n=new Map,r=new Map;for(let i of e){if(i.prompts!=null)for(let e of i.prompts)if(r.has(e.id)){if(e.override==null)throw Error(`Prompt ID conflict: "${e.id}" is defined in multiple templates.\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the prompt.\n Prompt is being extended/overridden but no override strategy was specified.`);let t=r.get(e.id);r.set(e.id,Ie(t,e))}else r.set(e.id,{...e});if(i.variables!=null)for(let e of i.variables)if(n.has(e.id)){if(e.override==null)throw Error(`Variable ID conflict: "${e.id}" is defined in multiple templates.\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the variable.\n Variable is being extended/overridden but no override strategy was specified.`);let t=n.get(e.id);n.set(e.id,Fe(t,e))}else n.set(e.id,{...e});for(let e of i.tasks??[])if(t.has(e.id)){if(e.override==null){let n=t.get(e.id);throw Error(`Task ID conflict: "${e.id}" is defined in multiple templates.\n Base task from: ${q(n.$sourceUrl)}\n Override task from: ${q(e.$sourceUrl)}\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the task.\n Task is being extended/overridden but no override strategy was specified.`)}let n=t.get(e.id);t.set(e.id,Be(n,e))}else t.set(e.id,{...e})}let i=Array.from(t.values()),a=r.size>0?Array.from(r.values()):void 0,o=n.size>0?Array.from(n.values()):void 0;Pe(i,o,a);let s={tasks:i};return a!=null&&(s.prompts=a),o!=null&&(s.variables=o),s}function Re(e,t){let n=K[e];if(!n)return null;for(let e of n){let n=e.filter(e=>e in t&&t[e]!=null);if(n.length>1)return n}return null}function ze(e,t,n){let r={...e},i=K[n]??[];for(let[e,n]of Object.entries(t)){for(let t of i)if(t.includes(e)){for(let n of t)n!==e&&delete r[n];break}r[e]=n}return r}function Be(e,t){if((t.override??`merge`)===`replace`){_(` → Task "${t.id}" using 'replace' strategy - completely replacing base task`,`info`),_(` Base: ${q(e.$sourceUrl)}`,`info`),_(` Override: ${q(t.$sourceUrl)}`,`info`);let{override:n,...r}=t;return r}_(` → Merging task "${t.id}"`,`info`),_(` Base: ${q(e.$sourceUrl)}`,`info`),_(` Override: ${q(t.$sourceUrl)}`,`info`);let n;if(typeof e.config==`object`&&e.config!==null&&typeof t.config==`object`&&t.config!==null){n=ze(e.config,t.config,t.type);let r=Re(t.type,n);r!==null&&r.length>0&&(_(` ⚠️ Warning: Conflicting config fields detected: ${r.join(`, `)}`,`warn`),_(` Please use override: "replace" or specify only one of these fields`,`warn`))}else n=t.config??e.config;let r=e.prompts?[...e.prompts]:void 0;if(t.prompts&&t.prompts.length>0)if(!r)r=[...t.prompts];else{let e=new Map(r.map(e=>[e.id,e]));for(let n of t.prompts)e.set(n.id,n);r=Array.from(e.values())}let i=e.variables?[...e.variables]:void 0;if(t.variables&&t.variables.length>0)if(!i)i=[...t.variables];else{let e=new Map(i.map(e=>[e.id,e]));for(let n of t.variables)e.set(n.id,n);i=Array.from(e.values())}let a=[...e.dependencies??[],...t.dependencies??[]],o=a.length>0?[...new Set(a)]:void 0,s=t.$sourceUrl??e.$sourceUrl,c={...e,...t,config:n,...r!=null&&{prompts:r},...i!=null&&{variables:i},...o!=null&&{dependencies:o},...s!=null&&{$sourceUrl:s}};return delete c.override,c}function Ve(){Q.clear()}async function He(e){_(`Loading tasks from ${e}...`,`info`);let t=await $(e);_(`Loaded ${t.tasks?.length??0} task(s)`,`info`),t.extends!=null&&t.extends!==``&&_(`Extended from: ${(Array.isArray(t.extends)?t.extends:[t.extends]).join(`, `)}`,`info`),t.prompts!=null&&t.prompts.length>0&&_(`Found ${t.prompts.length} top-level prompt(s)`,`info`),t.variables!=null&&t.variables.length>0&&_(`Found ${t.variables.length} top-level variable(s)`,`info`);let n={tasks:t.tasks??[]};return t.prompts!=null&&(n.prompts=t.prompts),t.variables!=null&&(n.variables=t.variables),n}const Ue=r(t.writeFile);async function We(t,r,i){if(t.condition!=null&&t.condition!==``&&!b(t.condition,r)){_(`Condition not met, skipping template task`,`info`);return}let a=e.join(n.cwd(),t.file),o=t.template!=null&&t.template!==``,s=t.templateFile!=null&&t.templateFile!==``;if(!o&&!s)throw Error(`Template task requires either "template" (inline) or "templateFile" (file path) to be specified`);if(o&&s)throw Error(`Template task cannot have both "template" and "templateFile" specified. Use one or the other.`);let c;if(s&&t.templateFile.endsWith(`.hbs`)){let e=await X(Y(t.templateFile,i?.$sourceUrl));c=(await import(`handlebars`)).default.compile(e)(r)}else c=v(s?await X(Y(t.templateFile,i?.$sourceUrl)):t.template,r);await Ue(a,c)}const Ge={name:`template`,version:`1.0.0`,taskTypes:[`template`],execute:async(e,t,n)=>{n.dryRun||await We(e.config,t,e)}},Ke=r(t.readFile),qe=r(t.writeFile);async function Je(t,r){if(t.condition!=null&&t.condition!==``&&!b(t.condition,r)){_(`Condition not met, skipping update-json task`,`info`);return}let i=e.join(n.cwd(),t.file),{updates:a}=t,o=await Ke(i,`utf-8`),s=JSON.parse(o);function c(e){if(typeof e==`string`)return v(e,r);if(Array.isArray(e))return e.map(e=>c(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=c(r);return t}return e}for(let[e,t]of Object.entries(a)){let n=c(t);e.includes(`.`)?y(s,e,n):s[e]=n}await qe(i,`${JSON.stringify(s,null,2)}\n`)}const Ye={name:`update-json`,version:`1.0.0`,taskTypes:[`update-json`],execute:async(e,t,n)=>{n.dryRun||await Je(e.config,t)}};let Xe=!1;function Ze(){Xe||=(I(Ye),I(Ge),I(he),I(Te),I(Me),I(_e),I(Oe),I(xe),I(ye),!0)}async function Qe(e,t,n=!1){if(Ze(),n){_(`[DRY RUN] Would execute: ${e.name}`,`info`);return}if(R(e.type)){await B(e,t,{dryRun:n});return}throw TypeError(`Unknown task type: ${e.type}`)}async function $e(e,t,r,i,a=!1){try{return _(`[${r}/${i}] Running: ${e.name}...`,`info`),await Qe(e,t,a),_(`✓ ${e.name}`,`success`),!0}catch(t){return _(`✗ Failed: ${e.name}`,`error`),t instanceof Error&&(_(` Reason: ${t.message}`,`error`),t.stack!=null&&n.env.DEBUG!=null&&console.error(t.stack)),e.required&&_(` This is a required task. Initialization cannot continue.`,`error`),!1}}function et(e){let t=[],n=new Set,r=new Set,i=new Map(e.map(e=>[e.id,e]));function a(e){if(n.has(e))return;if(r.has(e))throw Error(`Circular dependency detected involving task: ${e}`);r.add(e);let o=i.get(e);if(!o)throw Error(`Task not found: ${e}`);if(o.dependencies)for(let e of o.dependencies)a(e);r.delete(e),n.add(e),t.push(o)}for(let t of e)n.has(t.id)||a(t.id);return t}function tt(e){let t=[];for(let n of e)if(!R(n.type))t.push(`Task "${n.id}" (${n.name}): Unknown task type "${n.type}"`);else if(n.type===`template`){let e=nt(n);t.push(...e)}return t}function nt(e){let t=[],n=e.config,r=n.template!=null&&n.template!==``,i=n.templateFile!=null&&n.templateFile!==``;return!r&&!i&&t.push(`Task "${e.id}" (${e.name}): Template task requires either "template" (inline) or "templateFile" (file path) to be specified`),r&&i&&t.push(`Task "${e.id}" (${e.name}): Template task cannot have both "template" and "templateFile" specified. Use one or the other.`),(n.file==null||n.file===``)&&t.push(`Task "${e.id}" (${e.name}): Template task requires "file" property to specify the output file path`),t}function rt(e){_(`❌ Template validation failed:`,`error`),_(``,`error`);for(let t of e)_(` • ${t}`,`error`);_(``,`error`),_(`Please fix these errors before continuing.`,`error`)}function it(e,t=new Map){let n={};for(let r of e){let e=t.get(r.id);e!==void 0&&(n[r.id]=e)}return n}async function at(e,t){if(e==null)return;if(typeof e!=`object`||!e||Array.isArray(e))return e;let n=e;if(n.type===`exec`){let e=n.value;if(typeof e!=`string`){_(`Variable "${t}": exec value must have a string command`,`error`);return}try{let t=i(e,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:1e4}).trim();if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return t}if(/^-?\d+(?:\.\d+)?$/u.test(t)){let e=Number.parseFloat(t);if(!Number.isNaN(e))return e}return t===`true`||t===`false`?t===`true`:t}catch(e){_(`Variable "${t}": failed to execute command: ${e instanceof Error?e.message:`Unknown error`}`,`warn`);return}}else if(n.type===`static`)return n.value;return e}async function ot(e){let t=new Map,n=e.map(async e=>{let t=await at(e.value,e.id);return{id:e.id,value:t}}),r=await Promise.all(n);for(let e of r)e.value!==void 0&&t.set(e.id,e.value);return t}function st(e){let t=[],n=new Set;for(let r of e)if(n.has(r.id)&&t.push(`Duplicate variable ID: "${r.id}"`),n.add(r.id),/^[\w$]+$/u.test(r.id)||t.push(`Variable ID "${r.id}" is invalid. Must contain only letters, numbers, underscore, or dollar sign.`),r.value===void 0||r.value===null)t.push(`Variable "${r.id}" must have a value`);else if(typeof r.value==`object`&&!Array.isArray(r.value)&&r.value!==null){let e=r.value;e.type==null||e.type===``?t.push(`Variable "${r.id}": value object must have a "type" field ("static" or "exec")`):e.type!==`static`&&e.type!==`exec`&&t.push(`Variable "${r.id}": type must be "static" or "exec", got "${e.type}"`),(e.value===void 0||e.value===null)&&t.push(`Variable "${r.id}": value config must have a "value" field`),e.type===`exec`&&typeof e.value!=`string`&&t.push(`Variable "${r.id}": exec type must have a string command as value`)}return t}async function ct(e,t){_(`Validating task configurations...`,`info`);let r=tt(e);r.length>0&&(rt(r),n.exit(1)),_(`✓ All tasks validated successfully`,`success`);let i=e.filter(e=>p(e.enabled,f()));_(`Resolving task dependencies...`,`info`);let a=et(i);_(`Welcome! Let's execute your tasks.`,`info`),t.dryRun&&_(`🔍 DRY RUN MODE - No changes will be made`,`warn`),_(`This will execute your project tasks based on the defined configuration.`,`info`);let o=f(),s=t.globalVariables??[],c=[],l=[...s];for(let e of a)if(e.variables&&e.variables.length>0)for(let t of e.variables)c.push(t),l.push(t);if(l.length>0){let e=st(l);e.length>0&&(_(`❌ Variable validation errors:`,`error`),e.forEach(e=>_(` - ${e}`,`error`)),n.exit(1)),_(`Resolving variable values...`,`info`);let t=it(l,await ot(l));Object.assign(o,t),Object.keys(t).length>0&&_(`✓ Resolved ${Object.keys(t).length} variable(s)`,`success`)}let u=t.globalPrompts??[],d=[],m=[...u];for(let e of a)if(e.prompts&&e.prompts.length>0)for(let t of e.prompts)d.push(t),m.push(t);if(m.length>0){let e=W(m);e.length>0&&(_(`❌ Prompt validation errors:`,`error`),e.forEach(e=>_(` - ${e}`,`error`)),n.exit(1)),_(`Resolving prompt default values...`,`info`);let t=await U(m),r={};if(u.length>0&&(_(`📋 Top-level prompts (available to all tasks):`,`info`),r=await V(u,t,o),Object.assign(o,r)),d.length>0){u.length>0&&_(`📋 Task-specific prompts:`,`info`);let e=await V(d,t,o);Object.assign(o,e)}}let h=a.filter(e=>p(e.enabled,o));if(_(`${h.length} of ${a.length} task(s) enabled for execution`,`info`),t.dryRun){await M(h,o),_(`🔍 Dry run completed - no changes were made`,`info`),_(`Run without --dry-run to apply changes`,`info`);return}_(`Starting task execution...`,`info`),await z(`beforeAll`,o);let g=h.length,v=0,y=0,b=[];for(let e=0;e<h.length;e++){let n=h[e];if(n!=null)if(await z(`beforeTask`,n,o),await $e(n,o,e+1,g,t.dryRun))v++,b.push(n.id),await z(`afterTask`,n,o);else if(n.required){y++,await z(`onError`,Error(`Task ${n.name} failed`),n);break}else _(`⚠️ Non-critical task failed, continuing...`,`warn`),await z(`onError`,Error(`Task ${n.name} failed`),n)}y>0&&(_(`❌ Task execution failed with ${y} critical error(s)`,`error`),_(`✓ Completed: ${v}/${g} tasks`,`info`),n.exit(1)),await z(`afterAll`,o),_(`✅ All tasks completed successfully!`,`success`),_(`✓ Completed: ${v}/${g} tasks`,`success`),t.dryRun||(_(`Next steps:`,`info`),_(`1. Review the changes made to your project`,`info`),_(`2. Commit the changes to git`,`info`))}const lt=n.argv.includes(`--dry-run`),ut=n.argv.includes(`--force`);async function dt(e){try{let t=e||[];t.length===0&&(_(`⚠️ No tasks defined. Use --tasks-file to specify tasks or call runWithTasks() programmatically.`,`warn`),_(`Example: scaffoldfy --tasks-file ./tasks.json`,`info`),n.exit(1)),await ct(t,{dryRun:lt,force:ut,tasksFilePath:void 0})}catch(e){_(`❌ Task execution failed`,`error`),e instanceof Error?(_(`Error: ${e.message}`,`error`),n.env.DEBUG!=null&&console.error(e.stack)):console.error(e),n.exit(1)}}async function ft(e,t){try{await ct(e,{dryRun:t?.dryRun??lt,force:t?.force??ut,tasksFilePath:t?.tasksFilePath??void 0,...t?.globalVariables!=null&&{globalVariables:t.globalVariables},...t?.globalPrompts!=null&&{globalPrompts:t.globalPrompts}})}catch(e){_(`❌ Task execution failed`,`error`),e instanceof Error?(_(`Error: ${e.message}`,`error`),n.env.DEBUG!=null&&console.error(e.stack)):console.error(e),n.exit(1)}}export{ae as A,T as B,oe as C,se as D,R as E,A as F,_ as G,b as H,E as I,y as J,h as K,k as L,M,O as N,le as O,ie as P,D as R,B as S,ue as T,m as U,ne as V,v as W,H as _,at as a,ce as b,Qe as c,$ as d,He as f,U as g,W as h,ot as i,de as j,I as k,$e as l,Le as m,ft as n,it as o,Ne as p,g as q,st as r,et as s,dt as t,Ve as u,V as v,L as w,fe as x,z as y,j as z};
|
package/dist/src-BP7X1T83.cjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`node:fs`);c=s(c);let l=require(`node:path`);l=s(l);let u=require(`node:process`);u=s(u);let d=require(`node:util`);d=s(d);let f=require(`node:child_process`);f=s(f);let p=require(`node:readline`);p=s(p);let m=require(`handlebars`);m=s(m);let h=require(`@inquirer/prompts`);h=s(h);function g(){return{}}function _(e,t){return e===void 0?!0:typeof e==`boolean`?e:typeof e==`object`&&`condition`in e?C(e.condition,t):!1}function v(){try{let e=(0,f.execSync)(`git remote get-url origin`,{encoding:`utf-8`}).trim(),t=e.match(/github\.com[:/](?<owner>[^/]+)\/(?<name>[^/]+)$/u);if(t?.groups){let{owner:n,name:r}=t.groups,i=r;return i.endsWith(`.git`)&&(i=i.slice(0,-4)),{owner:n,name:i,url:e}}return null}catch{return null}}async function y(e,t){let n=p.default.createInterface({input:u.default.stdin,output:u.default.stdout});return new Promise(r=>{let i;i=t==null?`${e}: `:`${e} (${t}): `,n.question(i,e=>{n.close(),r(e.trim()||(t??``))})})}async function ee(e,t=!1){return y(`${e} (${t?`Y/n`:`y/N`})`,t?`y`:`n`).then(e=>e.toLowerCase()===`y`||e.toLowerCase()===`yes`)}function b(e,t=`info`){console.log(`${{info:`\x1B[36m`,success:`\x1B[32m`,error:`\x1B[31m`,warn:`\x1B[33m`}[t]}${{info:`ℹ`,success:`✓`,error:`✗`,warn:`⚠`}[t]} ${e}[0m`)}function x(e,t){return e.replace(/\{\{(?<key>\w+)\}\}/gu,(e,n)=>t[n]?.toString()??``)}function S(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++){let t=r[e];t!=null&&t!==``&&((!(t in i)||typeof i[t]!=`object`||i[t]===null)&&(i[t]={}),i=i[t])}let a=r[r.length-1];a!=null&&a!==``&&(i[a]=n)}function C(e,t){try{let n={...t};return Function(...Object.keys(n),`'use strict'; return (${e})`)(...Object.values(n))}catch(t){return b(`Failed to evaluate condition: ${e}`,`warn`),t instanceof Error&&b(` Error: ${t.message}`,`warn`),!1}}function te(e,t){try{let n=l.default.isAbsolute(e)?e:l.default.join(u.default.cwd(),e);if(!c.default.existsSync(n))throw Error(`Template file not found: ${e}`);return ne(c.default.readFileSync(n,`utf-8`),t)}catch(t){throw b(`Failed to read template file: ${e}`,`error`),t instanceof Error&&b(` Error: ${t.message}`,`error`),t}}function ne(e,t){try{return m.default.compile(e)(t)}catch(e){throw b(`Failed to compile Handlebars template`,`error`),e instanceof Error&&b(` Error: ${e.message}`,`error`),e}}const w=(0,d.promisify)(c.default.readFile),re=2,ie=10,ae=55,T={reset:`\x1B[0m`,red:`\x1B[31m`,green:`\x1B[32m`,yellow:`\x1B[33m`,blue:`\x1B[34m`,cyan:`\x1B[36m`,gray:`\x1B[90m`};function E(e,t){switch(t){case`add`:return`${T.green}+ ${e}${T.reset}`;case`remove`:return`${T.red}- ${e}${T.reset}`;case`context`:return`${T.gray} ${e}${T.reset}`;default:return e}}function D(e,t){let n=e.split(`
|
|
2
|
-
`),r=t.split(`
|
|
3
|
-
`),i=[],a=Math.max(n.length,r.length);for(let e=0;e<a;e++){let t=n[e],a=r[e];t===a?t!==void 0&&i.push(E(t,`context`)):(t!==void 0&&i.push(E(t,`remove`)),a!==void 0&&i.push(E(a,`add`)))}return i}async function O(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t))return`${T.yellow}⊘ Condition not met - task would be skipped${T.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${T.red}✗ File not found: ${e.file}${T.reset}`;try{let r=await w(n,`utf-8`),i=JSON.parse(r),a={...i};function o(e){if(typeof e==`string`)return x(e,t);if(Array.isArray(e))return e.map(e=>o(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=o(r);return t}return e}for(let[t,n]of Object.entries(e.updates)){let e=o(n);t.includes(`.`)?S(i,t,e):i[t]=e}let s=JSON.stringify(a,null,2),c=JSON.stringify(i,null,2);if(s===c)return`${T.cyan}→ No changes${T.reset}`;let l=D(s,c);return`${T.blue}File: ${e.file}${T.reset}\n${l.join(`
|
|
4
|
-
`)}`}catch(e){return`${T.red}✗ Error: ${e instanceof Error?e.message:String(e)}${T.reset}`}}async function k(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t))return`${T.yellow}⊘ Condition not met - task would be skipped${T.reset}`;if(e.template==null||e.template===``)return`${T.red}✗ No template content provided for file: ${e.file}${T.reset}`;let n=l.default.join(u.default.cwd(),e.file),r=x(e.template,t);if(!c.default.existsSync(n)){let t=r.split(`
|
|
5
|
-
`).slice(0,10).join(`
|
|
6
|
-
`),n=r.split(`
|
|
7
|
-
`).length>10;return`${T.blue}File: ${e.file}${T.reset}\n${T.green}+ New file would be created${T.reset}\n${T.gray}Content preview:${T.reset}\n${t}${n?`
|
|
8
|
-
...`:``}`}try{let t=await w(n,`utf-8`);if(t===r)return`${T.cyan}→ No changes${T.reset}`;let i=D(t,r);return`${T.blue}File: ${e.file}${T.reset}\n${i.join(`
|
|
9
|
-
`)}`}catch(e){return`${T.red}✗ Error: ${e instanceof Error?e.message:String(e)}${T.reset}`}}async function oe(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t))return`${T.yellow}⊘ Condition not met - task would be skipped${T.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(c.default.existsSync(n))return`${T.cyan}→ File already exists, would be skipped: ${e.file}${T.reset}`;let r=e.template!=null&&e.template!==``,i=e.templateFile!=null&&e.templateFile!==``;if(!r&&!i)return`${T.red}✗ No template content provided for file: ${e.file}${T.reset}`;try{let n;if(r)n=x(e.template,t);else return`${T.blue}File: ${e.file}${T.reset}\n${T.green}+ New file would be created from template: ${e.templateFile}${T.reset}`;let i=n.split(`
|
|
10
|
-
`).slice(0,10).join(`
|
|
11
|
-
`),a=n.split(`
|
|
12
|
-
`).length>10;return`${T.blue}File: ${e.file}${T.reset}\n${T.green}+ New file would be created${T.reset}\n${T.gray}Content preview:${T.reset}\n${i}${a?`
|
|
13
|
-
...`:``}`}catch(e){return`${T.red}✗ Error: ${e instanceof Error?e.message:String(e)}${T.reset}`}}async function se(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t))return`${T.yellow}⊘ Condition not met - task would be skipped${T.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${T.red}✗ File not found: ${e.file}${T.reset}`;try{let r=await w(n,`utf-8`),i=new RegExp(e.pattern,e.flags??`g`),a=x(e.replacement,t),o=r.replace(i,a);if(r===o)return`${T.cyan}→ No matches found${T.reset}`;let s=D(r,o);return`${T.blue}File: ${e.file}${T.reset}\n${s.join(`
|
|
14
|
-
`)}`}catch(e){return`${T.red}✗ Error: ${e instanceof Error?e.message:String(e)}${T.reset}`}}async function ce(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t))return`${T.yellow}⊘ Condition not met - task would be skipped${T.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${T.red}✗ File not found: ${e.file}${T.reset}`;try{let r=await w(n,`utf-8`),i=r;for(let{find:n,replace:i}of e.replacements){let e=x(n,t),a=x(i,t);r=r.replace(e,a)}if(i===r)return`${T.cyan}→ No changes${T.reset}`;let a=D(i,r);return`${T.blue}File: ${e.file}${T.reset}\n${a.join(`
|
|
15
|
-
`)}`}catch(e){return`${T.red}✗ Error: ${e instanceof Error?e.message:String(e)}${T.reset}`}}function le(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t))return`${T.yellow}⊘ Condition not met - task would be skipped${T.reset}`;let n=e.paths.map(e=>x(e,t)).filter(e=>c.default.existsSync(l.default.join(u.default.cwd(),e)));return n.length===0?`${T.cyan}→ No files/directories to delete${T.reset}`:`${T.red}Would delete:${T.reset}\n${n.map(e=>`${T.red} - ${e}${T.reset}`).join(`
|
|
16
|
-
`)}`}function ue(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t))return`${T.yellow}⊘ Condition not met - task would be skipped${T.reset}`;let n=x(e.from,t),r=x(e.to,t),i=l.default.join(u.default.cwd(),n),a=l.default.join(u.default.cwd(),r);return c.default.existsSync(i)?c.default.existsSync(a)?`${T.yellow}⚠ Destination already exists: ${r}${T.reset}\n${T.cyan}Would rename: ${n} → ${r}${T.reset}`:`${T.cyan}Would rename: ${n} → ${r}${T.reset}`:`${T.red}✗ Source not found: ${n}${T.reset}`}function A(e){if(e.condition!=null&&e.condition!==``)return`${T.yellow}⊘ Condition check skipped in dry-run${T.reset}`;let t=l.default.join(u.default.cwd(),`.git`),n=c.default.existsSync(t),r=[];if(e.removeExisting&&n&&r.push(`${T.red}Would remove existing .git directory${T.reset}`),r.push(`${T.green}Would initialize git repository${T.reset}`),e.initialCommit){let t=e.message??`Initial commit`;r.push(`${T.green}Would create initial commit: "${t}"${T.reset}`)}return r.join(`
|
|
17
|
-
`)}function j(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t))return`${T.yellow}⊘ Condition not met - task would be skipped${T.reset}`;let n=x(e.command,t),r=e.cwd==null?u.default.cwd():x(e.cwd,t);return`${T.yellow}Would execute:${T.reset}\n${T.cyan} Command: ${n}${T.reset}\n${T.cyan} Working directory: ${r}${T.reset}`}async function M(e,t){try{switch(e.type){case`update-json`:return await O(e.config,t);case`template`:return await k(e.config,t);case`create`:return await oe(e.config,t);case`regex-replace`:return await se(e.config,t);case`replace-in-file`:return await ce(e.config,t);case`delete`:return le(e.config,t);case`rename`:return ue(e.config,t);case`git-init`:return A(e.config);case`exec`:return j(e.config,t);default:{let t=e.type;return`${T.yellow}⚠ Diff not available for task type: ${t}${T.reset}`}}}catch(e){return`${T.red}✗ Error generating diff: ${e instanceof Error?e.message:String(e)}${T.reset}`}}async function N(e,t){console.log(`${T.blue}═══════════════════════════════════════════════════════${T.reset}`),console.log(`${T.blue} DRY RUN - Preview of changes${T.reset}`),console.log(`${T.blue}═══════════════════════════════════════════════════════${T.reset}`);for(let n of e){console.log(`${T.cyan}▶ Task: ${n.name}${T.reset}`),console.log(`${T.gray} ${n.description}${T.reset}`);let e=await M(n,t);console.log(e),console.log(`${T.gray}${`─`.repeat(55)}${T.reset}`)}console.log(`${T.blue}═══════════════════════════════════════════════════════${T.reset}`),console.log(`${T.yellow} No changes were applied (dry-run mode)${T.reset}`),console.log(`${T.blue}═══════════════════════════════════════════════════════${T.reset}`)}const P=new Map,F={},I=new Map;function L(e){if(e.name==null||e.name===``)throw TypeError(`Plugin name is required`);if(!Array.isArray(e.taskTypes)||e.taskTypes.length===0)throw TypeError(`Plugin ${e.name} must define at least one task type`);if(typeof e.execute!=`function`)throw TypeError(`Plugin ${e.name} must provide an execute function`);if(P.has(e.name))throw TypeError(`Plugin ${e.name} is already registered`);for(let t of e.taskTypes)if(I.has(t)){let e=I.get(t);throw TypeError(`Task type "${t}" is already registered by plugin "${e}"`)}P.set(e.name,e);for(let t of e.taskTypes)I.set(t,e.name);b(`✓ Registered plugin: ${e.name}${e.version==null?``:` v${e.version}`}`,`info`)}function de(e){let t=P.get(e);if(t!=null){for(let e of t.taskTypes)I.delete(e);P.delete(e)}}function fe(e){return P.get(e)}function R(e){let t=I.get(e);if(t!=null)return P.get(t)}function z(e){return I.has(e)}function pe(){return Array.from(P.keys())}function me(){P.clear(),I.clear()}function he(e){e.beforeAll!=null&&(F.beforeAll=e.beforeAll),e.afterAll!=null&&(F.afterAll=e.afterAll),e.beforeTask!=null&&(F.beforeTask=e.beforeTask),e.afterTask!=null&&(F.afterTask=e.afterTask),e.onError!=null&&(F.onError=e.onError)}async function B(e,...t){let n=F[e];if(n!=null)try{e===`beforeAll`||e===`afterAll`?await n(t[0]):(e===`beforeTask`||e===`afterTask`||e===`onError`)&&await n(t[0],t[1])}catch(t){b(`Error in ${e} hook: ${t instanceof Error?t.message:String(t)}`,`error`)}}async function V(e,t,n){let r=R(e.type);if(r==null)throw TypeError(`No plugin found for task type: ${e.type}`);await r.execute(e,t,n)}async function ge(e,t){let n=R(e.type);if(!(n==null||n.getDiff==null))return n.getDiff(e,t)}function _e(e){let t=R(e.type);return t==null?[`No plugin found for task type: ${e.type}`]:t.validate==null?[]:t.validate(e)}function ve(e,t,n,r){return{name:e,...r?.version!=null&&{version:r.version},taskTypes:[t],execute:n,...r?.getDiff!=null&&{getDiff:r.getDiff},...r?.validate!=null&&{validate:r.validate}}}async function H(e,t=new Map,n={}){let r={};if(e.length===0)return r;for(let i of e){let e={...n,...r};if(_(i.enabled,e))try{let e,n=t.get(i.id);switch(i.type){case`input`:{let t={message:i.message};if(n!==void 0&&(t.default=String(n)),i.required!==void 0&&(t.required=i.required),e=await(0,h.input)(t),i.required&&(e==null||typeof e==`string`&&e.trim()===``))throw b(`${i.message} is required`,`error`),Error(`Prompt "${i.id}" is required`);break}case`password`:if(e=await(0,h.password)({message:i.message,mask:`*`}),i.required&&(e==null||typeof e==`string`&&e.trim()===``))throw b(`${i.message} is required`,`error`),Error(`Prompt "${i.id}" is required`);break;case`number`:{let t={message:i.message};if(n!==void 0&&(t.default=Number(n)),i.required!==void 0&&(t.required=i.required),i.min!==void 0&&(t.min=i.min),i.max!==void 0&&(t.max=i.max),e=await(0,h.number)(t),i.required&&e==null)throw b(`${i.message} is required`,`error`),Error(`Prompt "${i.id}" is required`);break}case`select`:{let t={message:i.message,choices:i.choices.map(e=>({name:e.name,value:e.value}))};n!==void 0&&(t.default=n),e=await(0,h.select)(t);break}case`confirm`:{let t=n===void 0?!1:!!n;e=await(0,h.confirm)({message:i.message,default:t});break}default:throw b(`Unknown prompt type: ${i.type}`,`error`),Error(`Unknown prompt type: ${i.type}`)}r[i.id]=e}catch(e){throw e instanceof Error&&b(`Failed to collect prompt "${i.id}": ${e.message}`,`error`),e}}return r}async function U(e,t){if(e===void 0)return;if(typeof e!=`object`||!e||Array.isArray(e))return e;let n=e;if(n.type===`exec`){let e=n.value;if(typeof e!=`string`){b(`Prompt "${t}": exec default value must have a string command`,`error`);return}try{let t=(0,f.execSync)(e,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:1e4}).trim();if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return t}if(/^-?\d+(?:\.\d+)?$/u.test(t)){let e=Number.parseFloat(t);if(!Number.isNaN(e))return e}return t===`true`||t===`false`?t===`true`:t}catch(e){b(`Prompt "${t}": failed to execute default value command: ${e instanceof Error?e.message:`Unknown error`}`,`warn`);return}}else if(n.type===`static`)return n.value;return e}async function W(e){let t=new Map,n=e.map(async e=>{if(e.default!==void 0){let n=await U(e.default,e.id);n!==void 0&&t.set(e.id,n)}});return await Promise.all(n),t}function G(e){let t=[],n=new Set;for(let r of e){if(n.has(r.id)&&t.push(`Duplicate prompt ID: ${r.id}`),n.add(r.id),/^[\w-]+$/u.test(r.id)||t.push(`Invalid prompt ID "${r.id}": must contain only alphanumeric characters, underscores, and hyphens`),(!r.message||r.message.trim()===``)&&t.push(`Prompt "${r.id}" must have a non-empty message`),r.type===`select`){r.choices.length===0&&t.push(`Select prompt "${r.id}" must have at least one choice`);for(let e of r.choices)(!e.name||e.name.trim()===``)&&t.push(`Select prompt "${r.id}" has a choice with empty name`),e.value===void 0&&t.push(`Select prompt "${r.id}" has a choice with undefined value`)}r.type===`number`&&r.min!==void 0&&r.max!==void 0&&r.min>r.max&&t.push(`Number prompt "${r.id}" has min greater than max`)}return t}const ye=(0,d.promisify)(c.default.writeFile);async function be(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t)){b(`Condition not met, skipping create task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file);if(c.default.existsSync(n)){b(`File already exists, skipping: ${e.file}`,`info`);return}let r=e.template!=null&&e.template!==``,i=e.templateFile!=null&&e.templateFile!==``;if(!r&&!i)throw Error(`Create task requires either "template" (inline) or "templateFile" (file path) to be specified`);if(r&&i)throw Error(`Create task cannot have both "template" and "templateFile" specified. Use one or the other.`);let a;if(i&&e.templateFile.endsWith(`.hbs`))a=te(e.templateFile,t);else if(i){let n=e.templateFile,r=l.default.isAbsolute(n)?n:l.default.join(u.default.cwd(),n);if(!c.default.existsSync(r))throw Error(`Template file not found: ${n}`);a=x(c.default.readFileSync(r,`utf-8`),t)}else a=x(e.template,t);let o=l.default.dirname(n);c.default.existsSync(o)||c.default.mkdirSync(o,{recursive:!0}),await ye(n,a),b(`Created file: ${e.file}`,`success`)}const xe={name:`create`,version:`1.0.0`,taskTypes:[`create`],execute:async(e,t,n)=>{n.dryRun||await be(e.config,t)}};async function Se(e,t){let{paths:n,condition:r}=e;if(r!=null&&r!==``){if(!t){b(`Condition specified but no config provided, skipping deletion`,`warn`);return}if(!C(r,t)){b(`Condition not met, skipping deletion`,`info`);return}}for(let e of n){let t=l.default.join(u.default.cwd(),e);c.default.existsSync(t)&&c.default.rmSync(t,{recursive:!0,force:!0})}}const Ce={name:`delete`,version:`1.0.0`,taskTypes:[`delete`],execute:async(e,t,n)=>{n.dryRun||await Se(e.config,t)}};async function we(e,t){if(e.condition!=null&&e.condition!==``){if(!t){b(`Condition specified but no config provided, skipping exec`,`warn`);return}if(!C(e.condition,t)){b(`Condition not met, skipping exec task`,`info`);return}}let n=e.cwd==null?u.default.cwd():l.default.join(u.default.cwd(),e.cwd);(0,f.execSync)(e.command,{cwd:n,stdio:`inherit`})}const Te={name:`exec`,version:`1.0.0`,taskTypes:[`exec`],execute:async(e,t,n)=>{n.dryRun||await we(e.config,t)}};async function Ee(e,t){if(e.condition!=null&&e.condition!==``){if(!t){b(`Condition specified but no config provided, skipping git-init`,`warn`);return}if(!C(e.condition,t)){b(`Condition not met, skipping git-init task`,`info`);return}}if(e.removeExisting){let e=l.default.join(u.default.cwd(),`.git`);c.default.existsSync(e)&&c.default.rmSync(e,{recursive:!0,force:!0})}if((0,f.execSync)(`git init`,{stdio:`inherit`}),e.initialCommit){let t=e.message??`Initial commit`;(0,f.execSync)(`git add .`,{stdio:`inherit`}),(0,f.execSync)(`git commit -m "${t}"`,{stdio:`inherit`})}}const De={name:`git-init`,version:`1.0.0`,taskTypes:[`git-init`],execute:async(e,t,n)=>{n.dryRun||await Ee(e.config,t)}},Oe=(0,d.promisify)(c.default.readFile),ke=(0,d.promisify)(c.default.writeFile);async function Ae(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t)){b(`Condition not met, skipping regex-replace task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file),{pattern:r}=e,i=e.flags??``,a=e.replacement||``,o=await Oe(n,`utf-8`),s=new RegExp(r,i);o=o.replace(s,x(a,t)),await ke(n,o)}const je={name:`regex-replace`,version:`1.0.0`,taskTypes:[`regex-replace`],execute:async(e,t,n)=>{n.dryRun||await Ae(e.config,t)}},Me=(0,d.promisify)(c.default.rename);async function Ne(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t)){b(`Condition not met, skipping rename task`,`info`);return}let n=l.default.join(u.default.cwd(),x(e.from,t)),r=l.default.join(u.default.cwd(),x(e.to,t));if(!c.default.existsSync(n)){b(`Source path does not exist: ${n}`,`warn`);return}await Me(n,r)}const Pe={name:`rename`,version:`1.0.0`,taskTypes:[`rename`],execute:async(e,t,n)=>{n.dryRun||await Ne(e.config,t)}},Fe=(0,d.promisify)(c.default.readFile),Ie=(0,d.promisify)(c.default.writeFile);async function Le(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t)){b(`Condition not met, skipping replace-in-file task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file),{replacements:r}=e;if(!c.default.existsSync(n)){b(`File not found: ${n}, skipping`,`warn`);return}let i=await Fe(n,`utf-8`);for(let{find:e,replace:n}of r){let r=x(n,t);i=i.replace(new RegExp(e,`gu`),r)}await Ie(n,i)}const Re={name:`replace-in-file`,version:`1.0.0`,taskTypes:[`replace-in-file`],execute:async(e,t,n)=>{n.dryRun||await Le(e.config,t)}},K=(0,d.promisify)(c.default.readFile),q={template:[[`template`,`templateFile`]]};function J(e){if(e==null||e===``)return`current template`;if(Y(e))return e;let t=u.default.cwd();return e.startsWith(t)?l.default.relative(t,e):e}function Y(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}function X(e,t){if(Y(e))return e;if(t==null||t===``)return l.default.isAbsolute(e)?e:l.default.resolve(u.default.cwd(),e);if(Y(t))try{let n=new URL(`.`,t);return new URL(e,n).href}catch{throw Error(`Failed to resolve templateFile "${e}" relative to remote template "${t}"`)}let n=l.default.dirname(t);return l.default.isAbsolute(e)?e:l.default.resolve(n,e)}async function ze(e){if(Y(e))return Be(e);if(!c.default.existsSync(e))throw Error(`Template file not found: ${e}`);return K(e,`utf-8`)}async function Be(e){try{let t=await fetch(e);if(!t.ok)throw Error(`Failed to fetch template from ${e}: ${t.status} ${t.statusText}`);return await t.text()}catch(t){throw t instanceof Error&&t.message.includes(`Failed to fetch`)?t:Error(`Failed to fetch template from ${e}: ${t instanceof Error?t.message:String(t)}`)}}const Z=new Map;async function Ve(e,t=new Set){let n=Y(e),r;if(r=n||l.default.isAbsolute(e)?e:l.default.resolve(u.default.cwd(),e),Z.has(r))return Z.get(r);if(t.has(r))throw Error(`Circular dependency detected: ${Array.from(t).join(` -> `)} -> ${r}`);t.add(r);let i;if(n)i=await Be(r);else{if(!c.default.existsSync(r))throw Error(`Template file not found: ${r}`);i=await K(r,`utf-8`)}let a;try{a=JSON.parse(i)}catch(e){throw Error(`Failed to parse template file ${r}: ${e instanceof Error?e.message:String(e)}`)}if(a.tasks!==void 0&&!Array.isArray(a.tasks))throw TypeError(`Invalid template file ${r}: 'tasks' must be an array if provided`);a.tasks===void 0&&(a.tasks=[]);for(let e of a.tasks)e.$sourceUrl=r;return Z.set(r,a),a}async function Q(e,t,n=new Set){let r=Y(e),i;if(i=r||l.default.isAbsolute(e)?e:t==null?l.default.resolve(u.default.cwd(),e):Y(t)?new URL(e,t).href:l.default.resolve(t,e),n.has(i))throw Error(`Circular dependency detected: ${Array.from(n).join(` -> `)} -> ${i}`);n.add(i);let a=await Ve(i);if(a.extends==null||a.extends===``)return a;let o=Y(i)?new URL(`.`,i).href:l.default.dirname(i),s=Array.isArray(a.extends)?a.extends:[a.extends],c=[];for(let e of s){let t=await Q(e,o,n);c.push(t)}return Ge([...c,a])}function He(e,t,n){let r=new Map;for(let t of e){if(r.has(t.id))throw Error(`Duplicate ID "${t.id}" found in task. This ID is already used in ${r.get(t.id)}`);r.set(t.id,`task`)}if(t!=null)for(let e of t){if(r.has(e.id))throw Error(`Duplicate ID "${e.id}" found in variable. This ID is already used in ${r.get(e.id)}`);r.set(e.id,`variable`)}if(n!=null)for(let e of n){if(r.has(e.id))throw Error(`Duplicate ID "${e.id}" found in prompt. This ID is already used in ${r.get(e.id)}`);r.set(e.id,`prompt`)}}function Ue(e,t){if((t.override??`merge`)===`replace`){b(` → Variable "${t.id}" using 'replace' strategy`,`info`);let{override:e,...n}=t;return n}b(` → Variable "${t.id}" merged (value replaced)`,`info`);let n={...e,...t};return delete n.override,n}function We(e,t){if((t.override??`merge`)===`replace`){b(` → Prompt "${t.id}" using 'replace' strategy`,`info`);let{override:e,...n}=t;return n}b(` → Prompt "${t.id}" merged`,`info`);let n={...e,...t};return delete n.override,n}function Ge(e){if(e.length===0)return{tasks:[]};if(e.length===1){let t=e[0];return He(t.tasks??[],t.variables,t.prompts),t}let t=new Map,n=new Map,r=new Map;for(let i of e){if(i.prompts!=null)for(let e of i.prompts)if(r.has(e.id)){if(e.override==null)throw Error(`Prompt ID conflict: "${e.id}" is defined in multiple templates.\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the prompt.\n Prompt is being extended/overridden but no override strategy was specified.`);let t=r.get(e.id);r.set(e.id,We(t,e))}else r.set(e.id,{...e});if(i.variables!=null)for(let e of i.variables)if(n.has(e.id)){if(e.override==null)throw Error(`Variable ID conflict: "${e.id}" is defined in multiple templates.\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the variable.\n Variable is being extended/overridden but no override strategy was specified.`);let t=n.get(e.id);n.set(e.id,Ue(t,e))}else n.set(e.id,{...e});for(let e of i.tasks??[])if(t.has(e.id)){if(e.override==null){let n=t.get(e.id);throw Error(`Task ID conflict: "${e.id}" is defined in multiple templates.\n Base task from: ${J(n.$sourceUrl)}\n Override task from: ${J(e.$sourceUrl)}\n You must specify an override strategy: add "override": "merge" or "override": "replace" to the task.\n Task is being extended/overridden but no override strategy was specified.`)}let n=t.get(e.id);t.set(e.id,Je(n,e))}else t.set(e.id,{...e})}let i=Array.from(t.values()),a=r.size>0?Array.from(r.values()):void 0,o=n.size>0?Array.from(n.values()):void 0;He(i,o,a);let s={tasks:i};return a!=null&&(s.prompts=a),o!=null&&(s.variables=o),s}function Ke(e,t){let n=q[e];if(!n)return null;for(let e of n){let n=e.filter(e=>e in t&&t[e]!=null);if(n.length>1)return n}return null}function qe(e,t,n){let r={...e},i=q[n]??[];for(let[e,n]of Object.entries(t)){for(let t of i)if(t.includes(e)){for(let n of t)n!==e&&delete r[n];break}r[e]=n}return r}function Je(e,t){if((t.override??`merge`)===`replace`){b(` → Task "${t.id}" using 'replace' strategy - completely replacing base task`,`info`),b(` Base: ${J(e.$sourceUrl)}`,`info`),b(` Override: ${J(t.$sourceUrl)}`,`info`);let{override:n,...r}=t;return r}b(` → Merging task "${t.id}"`,`info`),b(` Base: ${J(e.$sourceUrl)}`,`info`),b(` Override: ${J(t.$sourceUrl)}`,`info`);let n;if(typeof e.config==`object`&&e.config!==null&&typeof t.config==`object`&&t.config!==null){n=qe(e.config,t.config,t.type);let r=Ke(t.type,n);r!==null&&r.length>0&&(b(` ⚠️ Warning: Conflicting config fields detected: ${r.join(`, `)}`,`warn`),b(` Please use override: "replace" or specify only one of these fields`,`warn`))}else n=t.config??e.config;let r=e.prompts?[...e.prompts]:void 0;if(t.prompts&&t.prompts.length>0)if(!r)r=[...t.prompts];else{let e=new Map(r.map(e=>[e.id,e]));for(let n of t.prompts)e.set(n.id,n);r=Array.from(e.values())}let i=e.variables?[...e.variables]:void 0;if(t.variables&&t.variables.length>0)if(!i)i=[...t.variables];else{let e=new Map(i.map(e=>[e.id,e]));for(let n of t.variables)e.set(n.id,n);i=Array.from(e.values())}let a=[...e.dependencies??[],...t.dependencies??[]],o=a.length>0?[...new Set(a)]:void 0,s=t.$sourceUrl??e.$sourceUrl,c={...e,...t,config:n,...r!=null&&{prompts:r},...i!=null&&{variables:i},...o!=null&&{dependencies:o},...s!=null&&{$sourceUrl:s}};return delete c.override,c}function Ye(){Z.clear()}async function Xe(e){b(`Loading tasks from ${e}...`,`info`);let t=await Q(e);b(`Loaded ${t.tasks?.length??0} task(s)`,`info`),t.extends!=null&&t.extends!==``&&b(`Extended from: ${(Array.isArray(t.extends)?t.extends:[t.extends]).join(`, `)}`,`info`),t.prompts!=null&&t.prompts.length>0&&b(`Found ${t.prompts.length} top-level prompt(s)`,`info`),t.variables!=null&&t.variables.length>0&&b(`Found ${t.variables.length} top-level variable(s)`,`info`);let n={tasks:t.tasks??[]};return t.prompts!=null&&(n.prompts=t.prompts),t.variables!=null&&(n.variables=t.variables),n}const Ze=(0,d.promisify)(c.default.writeFile);async function Qe(e,t,n){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t)){b(`Condition not met, skipping template task`,`info`);return}let r=l.default.join(u.default.cwd(),e.file),i=e.template!=null&&e.template!==``,a=e.templateFile!=null&&e.templateFile!==``;if(!i&&!a)throw Error(`Template task requires either "template" (inline) or "templateFile" (file path) to be specified`);if(i&&a)throw Error(`Template task cannot have both "template" and "templateFile" specified. Use one or the other.`);let o;if(a&&e.templateFile.endsWith(`.hbs`)){let r=await ze(X(e.templateFile,n?.$sourceUrl));o=(await import(`handlebars`)).default.compile(r)(t)}else o=x(a?await ze(X(e.templateFile,n?.$sourceUrl)):e.template,t);await Ze(r,o)}const $e={name:`template`,version:`1.0.0`,taskTypes:[`template`],execute:async(e,t,n)=>{n.dryRun||await Qe(e.config,t,e)}},et=(0,d.promisify)(c.default.readFile),tt=(0,d.promisify)(c.default.writeFile),nt=2;async function rt(e,t){if(e.condition!=null&&e.condition!==``&&!C(e.condition,t)){b(`Condition not met, skipping update-json task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file),{updates:r}=e,i=await et(n,`utf-8`),a=JSON.parse(i);function o(e){if(typeof e==`string`)return x(e,t);if(Array.isArray(e))return e.map(e=>o(e));if(typeof e==`object`&&e){let t={};for(let[n,r]of Object.entries(e))t[n]=o(r);return t}return e}for(let[e,t]of Object.entries(r)){let n=o(t);e.includes(`.`)?S(a,e,n):a[e]=n}await tt(n,`${JSON.stringify(a,null,2)}\n`)}const it={name:`update-json`,version:`1.0.0`,taskTypes:[`update-json`],execute:async(e,t,n)=>{n.dryRun||await rt(e.config,t)}};let at=!1;function ot(){at||=(L(it),L($e),L(xe),L(je),L(Re),L(Ce),L(Pe),L(De),L(Te),!0)}async function st(e,t,n=!1){if(ot(),n){b(`[DRY RUN] Would execute: ${e.name}`,`info`);return}if(z(e.type)){await V(e,t,{dryRun:n});return}throw TypeError(`Unknown task type: ${e.type}`)}async function ct(e,t,n,r,i=!1){try{return b(`[${n}/${r}] Running: ${e.name}...`,`info`),await st(e,t,i),b(`✓ ${e.name}`,`success`),!0}catch(t){return b(`✗ Failed: ${e.name}`,`error`),t instanceof Error&&(b(` Reason: ${t.message}`,`error`),t.stack!=null&&u.default.env.DEBUG!=null&&console.error(t.stack)),e.required&&b(` This is a required task. Initialization cannot continue.`,`error`),!1}}function lt(e){let t=[],n=new Set,r=new Set,i=new Map(e.map(e=>[e.id,e]));function a(e){if(n.has(e))return;if(r.has(e))throw Error(`Circular dependency detected involving task: ${e}`);r.add(e);let o=i.get(e);if(!o)throw Error(`Task not found: ${e}`);if(o.dependencies)for(let e of o.dependencies)a(e);r.delete(e),n.add(e),t.push(o)}for(let t of e)n.has(t.id)||a(t.id);return t}function ut(e){let t=[];for(let n of e)if(!z(n.type))t.push(`Task "${n.id}" (${n.name}): Unknown task type "${n.type}"`);else if(n.type===`template`){let e=dt(n);t.push(...e)}return t}function dt(e){let t=[],n=e.config,r=n.template!=null&&n.template!==``,i=n.templateFile!=null&&n.templateFile!==``;return!r&&!i&&t.push(`Task "${e.id}" (${e.name}): Template task requires either "template" (inline) or "templateFile" (file path) to be specified`),r&&i&&t.push(`Task "${e.id}" (${e.name}): Template task cannot have both "template" and "templateFile" specified. Use one or the other.`),(n.file==null||n.file===``)&&t.push(`Task "${e.id}" (${e.name}): Template task requires "file" property to specify the output file path`),t}function ft(e){b(`❌ Template validation failed:`,`error`),b(``,`error`);for(let t of e)b(` • ${t}`,`error`);b(``,`error`),b(`Please fix these errors before continuing.`,`error`)}function $(e,t=new Map){let n={};for(let r of e){let e=t.get(r.id);e!==void 0&&(n[r.id]=e)}return n}async function pt(e,t){if(e==null)return;if(typeof e!=`object`||!e||Array.isArray(e))return e;let n=e;if(n.type===`exec`){let e=n.value;if(typeof e!=`string`){b(`Variable "${t}": exec value must have a string command`,`error`);return}try{let t=(0,f.execSync)(e,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:1e4}).trim();if(t.startsWith(`{`)||t.startsWith(`[`))try{return JSON.parse(t)}catch{return t}if(/^-?\d+(?:\.\d+)?$/u.test(t)){let e=Number.parseFloat(t);if(!Number.isNaN(e))return e}return t===`true`||t===`false`?t===`true`:t}catch(e){b(`Variable "${t}": failed to execute command: ${e instanceof Error?e.message:`Unknown error`}`,`warn`);return}}else if(n.type===`static`)return n.value;return e}async function mt(e){let t=new Map,n=e.map(async e=>{let t=await pt(e.value,e.id);return{id:e.id,value:t}}),r=await Promise.all(n);for(let e of r)e.value!==void 0&&t.set(e.id,e.value);return t}function ht(e){let t=[],n=new Set;for(let r of e)if(n.has(r.id)&&t.push(`Duplicate variable ID: "${r.id}"`),n.add(r.id),/^[\w$]+$/u.test(r.id)||t.push(`Variable ID "${r.id}" is invalid. Must contain only letters, numbers, underscore, or dollar sign.`),r.value===void 0||r.value===null)t.push(`Variable "${r.id}" must have a value`);else if(typeof r.value==`object`&&!Array.isArray(r.value)&&r.value!==null){let e=r.value;e.type==null||e.type===``?t.push(`Variable "${r.id}": value object must have a "type" field ("static" or "exec")`):e.type!==`static`&&e.type!==`exec`&&t.push(`Variable "${r.id}": type must be "static" or "exec", got "${e.type}"`),(e.value===void 0||e.value===null)&&t.push(`Variable "${r.id}": value config must have a "value" field`),e.type===`exec`&&typeof e.value!=`string`&&t.push(`Variable "${r.id}": exec type must have a string command as value`)}return t}async function gt(e,t){b(`Validating task configurations...`,`info`);let n=ut(e);n.length>0&&(ft(n),u.default.exit(1)),b(`✓ All tasks validated successfully`,`success`);let r=e.filter(e=>_(e.enabled,g()));b(`Resolving task dependencies...`,`info`);let i=lt(r);b(`Welcome! Let's execute your tasks.`,`info`),t.dryRun&&b(`🔍 DRY RUN MODE - No changes will be made`,`warn`),b(`This will execute your project tasks based on the defined configuration.`,`info`);let a=g(),o=t.globalVariables??[],s=[],c=[...o];for(let e of i)if(e.variables&&e.variables.length>0)for(let t of e.variables)s.push(t),c.push(t);if(c.length>0){let e=ht(c);e.length>0&&(b(`❌ Variable validation errors:`,`error`),e.forEach(e=>b(` - ${e}`,`error`)),u.default.exit(1)),b(`Resolving variable values...`,`info`);let t=$(c,await mt(c));Object.assign(a,t),Object.keys(t).length>0&&b(`✓ Resolved ${Object.keys(t).length} variable(s)`,`success`)}let l=t.globalPrompts??[],d=[],f=[...l];for(let e of i)if(e.prompts&&e.prompts.length>0)for(let t of e.prompts)d.push(t),f.push(t);if(f.length>0){let e=G(f);e.length>0&&(b(`❌ Prompt validation errors:`,`error`),e.forEach(e=>b(` - ${e}`,`error`)),u.default.exit(1)),b(`Resolving prompt default values...`,`info`);let t=await W(f),n={};if(l.length>0&&(b(`📋 Top-level prompts (available to all tasks):`,`info`),n=await H(l,t,a),Object.assign(a,n)),d.length>0){l.length>0&&b(`📋 Task-specific prompts:`,`info`);let e=await H(d,t,a);Object.assign(a,e)}}let p=i.filter(e=>_(e.enabled,a));if(b(`${p.length} of ${i.length} task(s) enabled for execution`,`info`),t.dryRun){await N(p,a),b(`🔍 Dry run completed - no changes were made`,`info`),b(`Run without --dry-run to apply changes`,`info`);return}b(`Starting task execution...`,`info`),await B(`beforeAll`,a);let m=p.length,h=0,v=0,y=[];for(let e=0;e<p.length;e++){let n=p[e];if(n!=null)if(await B(`beforeTask`,n,a),await ct(n,a,e+1,m,t.dryRun))h++,y.push(n.id),await B(`afterTask`,n,a);else if(n.required){v++,await B(`onError`,Error(`Task ${n.name} failed`),n);break}else b(`⚠️ Non-critical task failed, continuing...`,`warn`),await B(`onError`,Error(`Task ${n.name} failed`),n)}v>0&&(b(`❌ Task execution failed with ${v} critical error(s)`,`error`),b(`✓ Completed: ${h}/${m} tasks`,`info`),u.default.exit(1)),await B(`afterAll`,a),b(`✅ All tasks completed successfully!`,`success`),b(`✓ Completed: ${h}/${m} tasks`,`success`),t.dryRun||(b(`Next steps:`,`info`),b(`1. Review the changes made to your project`,`info`),b(`2. Commit the changes to git`,`info`))}const _t=u.default.argv.includes(`--dry-run`),vt=u.default.argv.includes(`--force`);async function yt(e){try{let t=e||[];t.length===0&&(b(`⚠️ No tasks defined. Use --tasks-file to specify tasks or call runWithTasks() programmatically.`,`warn`),b(`Example: scaffoldfy --tasks-file ./tasks.json`,`info`),u.default.exit(1)),await gt(t,{dryRun:_t,force:vt,tasksFilePath:void 0})}catch(e){b(`❌ Task execution failed`,`error`),e instanceof Error?(b(`Error: ${e.message}`,`error`),u.default.env.DEBUG!=null&&console.error(e.stack)):console.error(e),u.default.exit(1)}}async function bt(e,t){try{await gt(e,{dryRun:t?.dryRun??_t,force:t?.force??vt,tasksFilePath:t?.tasksFilePath??void 0,...t?.globalVariables!=null&&{globalVariables:t.globalVariables},...t?.globalPrompts!=null&&{globalPrompts:t.globalPrompts}})}catch(e){b(`❌ Task execution failed`,`error`),e instanceof Error?(b(`Error: ${e.message}`,`error`),u.default.env.DEBUG!=null&&console.error(e.stack)):console.error(e),u.default.exit(1)}}Object.defineProperty(exports,`A`,{enumerable:!0,get:function(){return de}}),Object.defineProperty(exports,`B`,{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,`C`,{enumerable:!0,get:function(){return fe}}),Object.defineProperty(exports,`D`,{enumerable:!0,get:function(){return pe}}),Object.defineProperty(exports,`E`,{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,`F`,{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,`G`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`H`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`I`,{enumerable:!0,get:function(){return se}}),Object.defineProperty(exports,`J`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`K`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`L`,{enumerable:!0,get:function(){return ue}}),Object.defineProperty(exports,`M`,{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,`N`,{enumerable:!0,get:function(){return le}}),Object.defineProperty(exports,`O`,{enumerable:!0,get:function(){return he}}),Object.defineProperty(exports,`P`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`R`,{enumerable:!0,get:function(){return ce}}),Object.defineProperty(exports,`S`,{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,`T`,{enumerable:!0,get:function(){return ge}}),Object.defineProperty(exports,`U`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`V`,{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,`W`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`Y`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return U}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return pt}}),Object.defineProperty(exports,`b`,{enumerable:!0,get:function(){return me}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return st}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return Q}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return Xe}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return G}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return mt}}),Object.defineProperty(exports,`j`,{enumerable:!0,get:function(){return _e}}),Object.defineProperty(exports,`k`,{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return ct}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return Ge}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return bt}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return Ve}}),Object.defineProperty(exports,`q`,{enumerable:!0,get:function(){return ee}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return ht}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return lt}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return yt}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return Ye}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,`w`,{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,`x`,{enumerable:!0,get:function(){return ve}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,`z`,{enumerable:!0,get:function(){return M}});
|