@pixpilot/scaffoldfy 0.7.0 → 0.9.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/dist/index.d.ts CHANGED
@@ -1,7 +1,75 @@
1
+ //#region src/plugins/create/types.d.ts
2
+
3
+ interface CreateConfig {
4
+ file: string;
5
+ template?: string;
6
+ templateFile?: string;
7
+ condition?: ConditionExpression;
8
+ }
9
+ //#endregion
10
+ //#region src/plugins/delete/types.d.ts
11
+ interface DeleteConfig {
12
+ paths: string[];
13
+ condition?: ConditionExpression;
14
+ }
15
+ //#endregion
16
+ //#region src/plugins/exec/types.d.ts
17
+ interface ExecConfig {
18
+ command: string;
19
+ cwd?: string;
20
+ condition?: ConditionExpression;
21
+ }
22
+ //#endregion
23
+ //#region src/plugins/git-init/types.d.ts
24
+ interface GitInitConfig {
25
+ removeExisting: boolean;
26
+ initialCommit: boolean;
27
+ message?: string;
28
+ condition?: ConditionExpression;
29
+ }
30
+ //#endregion
31
+ //#region src/plugins/regex-replace/types.d.ts
32
+ interface RegexReplaceConfig {
33
+ file: string;
34
+ pattern: string;
35
+ flags?: string;
36
+ replacement: string;
37
+ condition?: ConditionExpression;
38
+ }
39
+ //#endregion
40
+ //#region src/plugins/rename/types.d.ts
41
+ interface RenameConfig {
42
+ from: string;
43
+ to: string;
44
+ condition?: ConditionExpression;
45
+ }
46
+ //#endregion
47
+ //#region src/plugins/replace-in-file/types.d.ts
48
+ interface ReplaceInFileConfig {
49
+ file: string;
50
+ replacements: Array<{
51
+ find: string;
52
+ replace: string;
53
+ }>;
54
+ condition?: ConditionExpression;
55
+ }
56
+ //#endregion
57
+ //#region src/plugins/template/types.d.ts
58
+ interface TemplateConfig {
59
+ file: string;
60
+ template?: string;
61
+ templateFile?: string;
62
+ condition?: ConditionExpression;
63
+ }
64
+ //#endregion
65
+ //#region src/plugins/update-json/types.d.ts
66
+ interface UpdateJsonConfig {
67
+ file: string;
68
+ updates: Record<string, unknown>;
69
+ condition?: ConditionExpression;
70
+ }
71
+ //#endregion
1
72
  //#region src/types.d.ts
2
- /**
3
- * Task Types and Interfaces for Template Initialization
4
- */
5
73
  interface InitConfig {
6
74
  [key: string]: unknown;
7
75
  }
@@ -11,10 +79,10 @@ interface InitConfig {
11
79
  type PromptType = 'input' | 'select' | 'confirm' | 'password' | 'number';
12
80
  /**
13
81
  * Default value types for prompts
14
- * - 'value': Static value
15
- * - 'execute': Execute a command to get the value
82
+ * - 'static': Static value provided directly
83
+ * - 'exec': Execute a command to get the value dynamically
16
84
  */
17
- type DefaultValueType = 'value' | 'execute';
85
+ type DefaultValueType = 'static' | 'exec';
18
86
  /**
19
87
  * Default value configuration for prompts
20
88
  */
@@ -23,15 +91,29 @@ interface DefaultValueConfig<T = string | number | boolean> {
23
91
  value: T | string;
24
92
  }
25
93
  /**
26
- * Type for default values that can be either static or executable
94
+ * Type for default values that can be either static or executable.
95
+ * - For simple static values, pass the value directly (e.g., "default-name", 42, true)
96
+ * - For executable defaults, use { type: 'exec', value: 'command' }
97
+ * - For explicit static values, use { type: 'static', value: yourValue }
27
98
  */
28
99
  type DefaultValue<T = string | number | boolean> = T | DefaultValueConfig<T>;
100
+ /**
101
+ * Conditional enabled configuration for prompts and tasks
102
+ * Allows dynamic enabling/disabling based on runtime conditions
103
+ */
104
+ interface ConditionalEnabled {
105
+ condition: ConditionExpression;
106
+ }
107
+ /**
108
+ * Type for enabled field that can be boolean or conditional
109
+ */
110
+ type EnabledValue = boolean | ConditionalEnabled;
29
111
  interface BasePrompt {
30
112
  id: string;
31
113
  type: PromptType;
32
114
  message: string;
33
115
  required?: boolean;
34
- global?: boolean;
116
+ enabled?: EnabledValue;
35
117
  }
36
118
  interface InputPrompt extends BasePrompt {
37
119
  type: 'input' | 'password';
@@ -57,7 +139,26 @@ interface ConfirmPrompt extends BasePrompt {
57
139
  default?: DefaultValue<boolean>;
58
140
  }
59
141
  type PromptDefinition = InputPrompt | NumberPrompt | SelectPrompt | ConfirmPrompt;
60
- type TaskType = 'update-json' | 'template' | 'regex-replace' | 'replace-in-file' | 'delete' | 'rename' | 'git-init' | 'exec';
142
+ /**
143
+ * Variable value configuration for defining optional global or task-scoped variables
144
+ * Variables are similar to prompts but don't require user input - they can have static
145
+ * values or values resolved from executable commands
146
+ *
147
+ * Note: Top-level variables are always global. Task-level variables are task-scoped.
148
+ */
149
+ interface VariableDefinition {
150
+ id: string;
151
+ value: DefaultValue;
152
+ }
153
+ /**
154
+ * JavaScript expression evaluated at runtime to determine if a task or operation should execute.
155
+ * Has access to all prompt values, variables, and config variables.
156
+ * @example "useTypeScript === true"
157
+ * @example "nodeVersion >= 16 && includeTests === true"
158
+ * @example "packageManager === 'pnpm'"
159
+ */
160
+ type ConditionExpression = string;
161
+ type TaskType = 'update-json' | 'template' | 'create' | 'regex-replace' | 'replace-in-file' | 'delete' | 'rename' | 'git-init' | 'exec';
61
162
  interface RollbackConfig {
62
163
  type: TaskType;
63
164
  config: unknown;
@@ -67,58 +168,13 @@ interface TaskDefinition {
67
168
  name: string;
68
169
  description: string;
69
170
  required: boolean;
70
- enabled: boolean;
171
+ enabled: EnabledValue;
71
172
  type: TaskType;
72
- config: unknown;
173
+ config: UpdateJsonConfig | TemplateConfig | CreateConfig | RegexReplaceConfig | ReplaceInFileConfig | DeleteConfig | RenameConfig | GitInitConfig | ExecConfig | Record<string, unknown>;
73
174
  dependencies?: string[];
74
175
  rollback?: RollbackConfig;
75
176
  prompts?: PromptDefinition[];
76
- }
77
- interface UpdateJsonConfig {
78
- file: string;
79
- updates: Record<string, unknown>;
80
- condition?: string;
81
- }
82
- interface TemplateConfig {
83
- file: string;
84
- template?: string;
85
- templateFile?: string;
86
- condition?: string;
87
- }
88
- interface RegexReplaceConfig {
89
- file: string;
90
- pattern: string;
91
- flags?: string;
92
- replacement: string;
93
- condition?: string;
94
- }
95
- interface ReplaceInFileConfig {
96
- file: string;
97
- replacements: Array<{
98
- find: string;
99
- replace: string;
100
- }>;
101
- condition?: string;
102
- }
103
- interface DeleteConfig {
104
- paths: string[];
105
- condition?: string;
106
- }
107
- interface RenameConfig {
108
- from: string;
109
- to: string;
110
- condition?: string;
111
- }
112
- interface GitInitConfig {
113
- removeExisting: boolean;
114
- initialCommit: boolean;
115
- message?: string;
116
- condition?: string;
117
- }
118
- interface ExecConfig {
119
- command: string;
120
- cwd?: string;
121
- condition?: string;
177
+ variables?: VariableDefinition[];
122
178
  }
123
179
  interface InitializationMetadata {
124
180
  initializedAt: string;
@@ -131,6 +187,8 @@ interface InitializationMetadata {
131
187
  */
132
188
  interface TasksConfiguration {
133
189
  extends?: string | string[];
190
+ variables?: VariableDefinition[];
191
+ prompts?: PromptDefinition[];
134
192
  tasks: TaskDefinition[];
135
193
  }
136
194
  /**
@@ -308,11 +366,13 @@ declare function createPlugin(name: string, taskType: string, execute: (task: Ta
308
366
  //#region src/prompts/collect-prompts.d.ts
309
367
  /**
310
368
  * Collect prompt answers from task-defined prompts
369
+ * Only prompts with enabled=true (or enabled condition that evaluates to true) will be shown
311
370
  * @param prompts - Array of prompt definitions from tasks
312
371
  * @param resolvedDefaults - Map of pre-resolved default values
372
+ * @param config - Current configuration context (for evaluating enabled conditions)
313
373
  * @returns Object mapping prompt IDs to their values
314
374
  */
315
- declare function collectPrompts(prompts: PromptDefinition[], resolvedDefaults?: Map<string, unknown>): Promise<Record<string, unknown>>;
375
+ declare function collectPrompts(prompts: PromptDefinition[], resolvedDefaults?: Map<string, unknown>, config?: InitConfig): Promise<Record<string, unknown>>;
316
376
  //#endregion
317
377
  //#region src/prompts/resolve-all-default-values.d.ts
318
378
  /**
@@ -395,9 +455,13 @@ declare function clearTemplateCache(): void;
395
455
  /**
396
456
  * Load tasks from a configuration file with template inheritance support
397
457
  * @param tasksFilePath - Path to the tasks configuration file
398
- * @returns Array of task definitions
458
+ * @returns Task configuration with tasks, optional variables, and optional prompts
399
459
  */
400
- declare function loadTasksWithInheritance(tasksFilePath: string): Promise<TaskDefinition[]>;
460
+ declare function loadTasksWithInheritance(tasksFilePath: string): Promise<{
461
+ tasks: TaskDefinition[];
462
+ variables?: VariableDefinition[];
463
+ prompts?: PromptDefinition[];
464
+ }>;
401
465
  //#endregion
402
466
  //#region src/utils.d.ts
403
467
  /**
@@ -433,6 +497,43 @@ declare function setNestedProperty(obj: Record<string, unknown>, propertyPath: s
433
497
  */
434
498
  declare function evaluateCondition(condition: string, config: InitConfig): boolean;
435
499
  //#endregion
500
+ //#region src/variables/collect-variables.d.ts
501
+ /**
502
+ * Collect variable values from resolved variables
503
+ * Variables don't require user interaction - they're just resolved from static
504
+ * values or executable commands
505
+ *
506
+ * @param variables - Array of variable definitions
507
+ * @param resolvedValues - Map of pre-resolved variable values
508
+ * @returns Object mapping variable IDs to their values
509
+ */
510
+ declare function collectVariables(variables: VariableDefinition[], resolvedValues?: Map<string, unknown>): Record<string, unknown>;
511
+ //#endregion
512
+ //#region src/variables/resolve-all-variable-values.d.ts
513
+ /**
514
+ * Pre-resolve all variable values (execute commands in parallel for efficiency)
515
+ * @param variables - Array of variable definitions
516
+ * @returns Map of variable IDs to their resolved values
517
+ */
518
+ declare function resolveAllVariableValues(variables: VariableDefinition[]): Promise<Map<string, unknown>>;
519
+ //#endregion
520
+ //#region src/variables/resolve-variable-value.d.ts
521
+ /**
522
+ * Resolve a variable value that may be static or executable
523
+ * @param value - The variable value configuration
524
+ * @param variableId - The variable ID for error reporting
525
+ * @returns The resolved variable value
526
+ */
527
+ declare function resolveVariableValue<T = string | number | boolean>(value: DefaultValue<T>, variableId: string): Promise<T | undefined>;
528
+ //#endregion
529
+ //#region src/variables/validate-variables.d.ts
530
+ /**
531
+ * Validate variable definitions for common errors
532
+ * @param variables - Array of variable definitions to validate
533
+ * @returns Array of error messages (empty if no errors)
534
+ */
535
+ declare function validateVariables(variables: VariableDefinition[]): string[];
536
+ //#endregion
436
537
  //#region src/index.d.ts
437
538
  /**
438
539
  * Main function for running initialization with default/empty tasks
@@ -446,11 +547,15 @@ declare function main(customTasks?: TaskDefinition[]): Promise<void>;
446
547
  * @param options.dryRun - Preview changes without applying them
447
548
  * @param options.force - Force re-initialization even if already initialized
448
549
  * @param options.tasksFilePath - Path to the tasks file
550
+ * @param options.globalVariables - Optional top-level global variables
551
+ * @param options.globalPrompts - Optional top-level global prompts
449
552
  */
450
553
  declare function runWithTasks(customTasks: TaskDefinition[], options?: {
451
554
  dryRun?: boolean | undefined;
452
555
  force?: boolean | undefined;
453
556
  tasksFilePath?: string | undefined;
557
+ globalVariables?: VariableDefinition[] | undefined;
558
+ globalPrompts?: PromptDefinition[] | undefined;
454
559
  }): Promise<void>;
455
560
  //#endregion
456
- export { BasePrompt, ConfirmPrompt, DefaultValue, DefaultValueConfig, DefaultValueType, DeleteConfig, ExecConfig, GitInitConfig, InitConfig, InitializationMetadata, InputPrompt, NumberPrompt, PluginHooks, PromptDefinition, PromptType, RegexReplaceConfig, RenameConfig, ReplaceInFileConfig, RollbackConfig, SelectPrompt, TaskDefinition, TaskPlugin, TaskType, TasksConfiguration, TemplateConfig, UpdateJsonConfig, callHook, clearPlugins, clearTemplateCache, collectPrompts, createPlugin, displayTasksDiff, evaluateCondition, executePluginTask, executeTask, getDeleteDiff, getExecDiff, getGitInitDiff, getGitRepoInfo, getPlugin, getPluginForTaskType, getPluginTaskDiff, getRegexReplaceDiff, getRenameDiff, getReplaceInFileDiff, getTaskDiff, getTemplateDiff, getUpdateJsonDiff, interpolateTemplate, isPluginTaskType, listPlugins, loadAndMergeTemplate, loadInitializationState, loadTasksWithInheritance, loadTemplate, log, main, mergeTemplates, prompt, promptYesNo, registerHooks, registerPlugin, resolveAllDefaultValues, resolveDefaultValue, runTask, runWithTasks, saveInitializationState, setNestedProperty, topologicalSort, unregisterPlugin, validatePluginTask, validatePrompts };
561
+ export { BasePrompt, ConditionExpression, ConditionalEnabled, ConfirmPrompt, type CreateConfig, DefaultValue, DefaultValueConfig, DefaultValueType, type DeleteConfig, EnabledValue, type ExecConfig, type GitInitConfig, InitConfig, InitializationMetadata, InputPrompt, 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, loadInitializationState, loadTasksWithInheritance, loadTemplate, log, main, mergeTemplates, prompt, promptYesNo, registerHooks, registerPlugin, resolveAllDefaultValues, resolveAllVariableValues, resolveDefaultValue, resolveVariableValue, runTask, runWithTasks, saveInitializationState, 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,K as l,L as u,M as d,N as f,O as p,P as m,R as h,S as g,T as _,U as v,V as y,W as b,_ as x,a as S,b as C,c as w,d as T,f as E,g as D,h as O,i as k,j as A,k as j,l as M,m as N,n as P,o as F,p as I,r as L,s as R,t as z,u as B,v as V,w as H,x as U,y as W,z as G}from"./src-_h_NfVky.js";export{x as callHook,V as clearPlugins,L as clearTemplateCache,D as collectPrompts,W as createPlugin,e as displayTasksDiff,t as evaluateCondition,C as executePluginTask,M as executeTask,A as getDeleteDiff,d as getExecDiff,f as getGitInitDiff,y as getGitRepoInfo,U as getPlugin,g as getPluginForTaskType,n as getPluginTaskDiff,m as getRegexReplaceDiff,a as getRenameDiff,c as getReplaceInFileDiff,u as getTaskDiff,h as getTemplateDiff,G as getUpdateJsonDiff,s as interpolateTemplate,H as isPluginTaskType,_ as listPlugins,k as loadAndMergeTemplate,T as loadInitializationState,S as loadTasksWithInheritance,F as loadTemplate,v as log,z as main,R as mergeTemplates,b as prompt,o as promptYesNo,i as registerHooks,r as registerPlugin,N as resolveAllDefaultValues,O as resolveDefaultValue,B as runTask,P as runWithTasks,E as saveInitializationState,l as setNestedProperty,w as topologicalSort,p as unregisterPlugin,j as validatePluginTask,I as validatePrompts};
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,X as S,Y as C,_ as w,a as T,b as E,c as D,d as O,f as k,g as A,h as j,i as M,j as N,k as P,l as F,m as I,n as L,o as R,p as z,q as B,r as V,s as H,t as U,u as W,v as G,w as K,x as q,y as J,z as Y}from"./src-IzX9FHaO.js";export{q as callHook,_ as clearPlugins,V as clearTemplateCache,E as collectPrompts,O as collectVariables,n as createPlugin,h as displayTasksDiff,x as evaluateCondition,K as executePluginTask,z as executeTask,a as getDeleteDiff,c as getExecDiff,d as getGitInitDiff,o as getGitRepoInfo,v as getPlugin,i as getPluginForTaskType,r as getPluginTaskDiff,g as getRegexReplaceDiff,Y as getRenameDiff,t as getReplaceInFileDiff,b as getTaskDiff,s as getTemplateDiff,y as getUpdateJsonDiff,u as interpolateTemplate,m as isPluginTaskType,P as listPlugins,M as loadAndMergeTemplate,j as loadInitializationState,T as loadTasksWithInheritance,R as loadTemplate,B as log,U as main,H as mergeTemplates,l as prompt,C as promptYesNo,e as registerHooks,N as registerPlugin,G as resolveAllDefaultValues,F as resolveAllVariableValues,J as resolveDefaultValue,W as resolveVariableValue,I as runTask,L as runWithTasks,A as saveInitializationState,S as setNestedProperty,k as topologicalSort,f as unregisterPlugin,p as validatePluginTask,w as validatePrompts,D as validateVariables};
@@ -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:child_process`);d=s(d);let f=require(`node:util`);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?w(e.condition,t):!1}function v(){try{let e=(0,d.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 b(e,t=!1){return y(`${e} (${t?`Y/n`:`y/N`})`,t?`y`:`n`).then(e=>e.toLowerCase()===`y`||e.toLowerCase()===`yes`)}function x(e,t=`info`){console.log(`${{info:`\x1B[36m`,success:`\x1B[32m`,error:`\x1B[31m`,warn:`\x1B[33m`}[t]}${{info:`ℹ`,success:`✓`,error:`✗`,warn:`⚠`}[t]} ${e}`)}function S(e,t){return e.replace(/\{\{(?<key>\w+)\}\}/gu,(e,n)=>t[n]?.toString()??``)}function C(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 w(e,t){try{let n={...t};return Function(...Object.keys(n),`'use strict'; return (${e})`)(...Object.values(n))}catch(t){return x(`Failed to evaluate condition: ${e}`,`warn`),t instanceof Error&&x(` Error: ${t.message}`,`warn`),!1}}function T(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 ee(c.default.readFileSync(n,`utf-8`),t)}catch(t){throw x(`Failed to read template file: ${e}`,`error`),t instanceof Error&&x(` Error: ${t.message}`,`error`),t}}function ee(e,t){try{return m.default.compile(e)(t)}catch(e){throw x(`Failed to compile Handlebars template`,`error`),e instanceof Error&&x(` Error: ${e.message}`,`error`),e}}const E=(0,f.promisify)(c.default.readFile),te=2,ne=10,re=55,D={reset:`\x1B[0m`,red:`\x1B[31m`,green:`\x1B[32m`,yellow:`\x1B[33m`,blue:`\x1B[34m`,cyan:`\x1B[36m`,gray:`\x1B[90m`};function O(e,t){switch(t){case`add`:return`${D.green}+ ${e}${D.reset}`;case`remove`:return`${D.red}- ${e}${D.reset}`;case`context`:return`${D.gray} ${e}${D.reset}`;default:return e}}function k(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(O(t,`context`)):(t!==void 0&&i.push(O(t,`remove`)),a!==void 0&&i.push(O(a,`add`)))}return i}async function A(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t))return`${D.yellow}⊘ Condition not met - task would be skipped${D.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${D.red}✗ File not found: ${e.file}${D.reset}`;try{let r=await E(n,`utf-8`),i=JSON.parse(r),a={...i};function o(e){if(typeof e==`string`)return S(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(`.`)?C(i,t,e):i[t]=e}let s=JSON.stringify(a,null,2),c=JSON.stringify(i,null,2);if(s===c)return`${D.cyan}→ No changes${D.reset}`;let l=k(s,c);return`${D.blue}File: ${e.file}${D.reset}\n${l.join(`
4
+ `)}`}catch(e){return`${D.red}✗ Error: ${e instanceof Error?e.message:String(e)}${D.reset}`}}async function j(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t))return`${D.yellow}⊘ Condition not met - task would be skipped${D.reset}`;if(e.template==null||e.template===``)return`${D.red}✗ No template content provided for file: ${e.file}${D.reset}`;let n=l.default.join(u.default.cwd(),e.file),r=S(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`${D.blue}File: ${e.file}${D.reset}\n${D.green}+ New file would be created${D.reset}\n${D.gray}Content preview:${D.reset}\n${t}${n?`
8
+ ...`:``}`}try{let t=await E(n,`utf-8`);if(t===r)return`${D.cyan}→ No changes${D.reset}`;let i=k(t,r);return`${D.blue}File: ${e.file}${D.reset}\n${i.join(`
9
+ `)}`}catch(e){return`${D.red}✗ Error: ${e instanceof Error?e.message:String(e)}${D.reset}`}}async function ie(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t))return`${D.yellow}⊘ Condition not met - task would be skipped${D.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(c.default.existsSync(n))return`${D.cyan}→ File already exists, would be skipped: ${e.file}${D.reset}`;let r=e.template!=null&&e.template!==``,i=e.templateFile!=null&&e.templateFile!==``;if(!r&&!i)return`${D.red}✗ No template content provided for file: ${e.file}${D.reset}`;try{let n;if(r)n=S(e.template,t);else return`${D.blue}File: ${e.file}${D.reset}\n${D.green}+ New file would be created from template: ${e.templateFile}${D.reset}`;let i=n.split(`
10
+ `).slice(0,10).join(`
11
+ `),a=n.split(`
12
+ `).length>10;return`${D.blue}File: ${e.file}${D.reset}\n${D.green}+ New file would be created${D.reset}\n${D.gray}Content preview:${D.reset}\n${i}${a?`
13
+ ...`:``}`}catch(e){return`${D.red}✗ Error: ${e instanceof Error?e.message:String(e)}${D.reset}`}}async function ae(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t))return`${D.yellow}⊘ Condition not met - task would be skipped${D.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${D.red}✗ File not found: ${e.file}${D.reset}`;try{let r=await E(n,`utf-8`),i=new RegExp(e.pattern,e.flags??`g`),a=S(e.replacement,t),o=r.replace(i,a);if(r===o)return`${D.cyan}→ No matches found${D.reset}`;let s=k(r,o);return`${D.blue}File: ${e.file}${D.reset}\n${s.join(`
14
+ `)}`}catch(e){return`${D.red}✗ Error: ${e instanceof Error?e.message:String(e)}${D.reset}`}}async function oe(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t))return`${D.yellow}⊘ Condition not met - task would be skipped${D.reset}`;let n=l.default.join(u.default.cwd(),e.file);if(!c.default.existsSync(n))return`${D.red}✗ File not found: ${e.file}${D.reset}`;try{let r=await E(n,`utf-8`),i=r;for(let{find:n,replace:i}of e.replacements){let e=S(n,t),a=S(i,t);r=r.replace(e,a)}if(i===r)return`${D.cyan}→ No changes${D.reset}`;let a=k(i,r);return`${D.blue}File: ${e.file}${D.reset}\n${a.join(`
15
+ `)}`}catch(e){return`${D.red}✗ Error: ${e instanceof Error?e.message:String(e)}${D.reset}`}}function se(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t))return`${D.yellow}⊘ Condition not met - task would be skipped${D.reset}`;let n=e.paths.map(e=>S(e,t)).filter(e=>c.default.existsSync(l.default.join(u.default.cwd(),e)));return n.length===0?`${D.cyan}→ No files/directories to delete${D.reset}`:`${D.red}Would delete:${D.reset}\n${n.map(e=>`${D.red} - ${e}${D.reset}`).join(`
16
+ `)}`}function M(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t))return`${D.yellow}⊘ Condition not met - task would be skipped${D.reset}`;let n=S(e.from,t),r=S(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)?`${D.yellow}⚠ Destination already exists: ${r}${D.reset}\n${D.cyan}Would rename: ${n} → ${r}${D.reset}`:`${D.cyan}Would rename: ${n} → ${r}${D.reset}`:`${D.red}✗ Source not found: ${n}${D.reset}`}function N(e){if(e.condition!=null&&e.condition!==``)return`${D.yellow}⊘ Condition check skipped in dry-run${D.reset}`;let t=l.default.join(u.default.cwd(),`.git`),n=c.default.existsSync(t),r=[];if(e.removeExisting&&n&&r.push(`${D.red}Would remove existing .git directory${D.reset}`),r.push(`${D.green}Would initialize git repository${D.reset}`),e.initialCommit){let t=e.message??`Initial commit`;r.push(`${D.green}Would create initial commit: "${t}"${D.reset}`)}return r.join(`
17
+ `)}function P(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t))return`${D.yellow}⊘ Condition not met - task would be skipped${D.reset}`;let n=S(e.command,t),r=e.cwd==null?u.default.cwd():S(e.cwd,t);return`${D.yellow}Would execute:${D.reset}\n${D.cyan} Command: ${n}${D.reset}\n${D.cyan} Working directory: ${r}${D.reset}`}async function F(e,t){try{switch(e.type){case`update-json`:return await A(e.config,t);case`template`:return await j(e.config,t);case`create`:return await ie(e.config,t);case`regex-replace`:return await ae(e.config,t);case`replace-in-file`:return await oe(e.config,t);case`delete`:return se(e.config,t);case`rename`:return M(e.config,t);case`git-init`:return N(e.config);case`exec`:return P(e.config,t);default:{let t=e.type;return`${D.yellow}⚠ Diff not available for task type: ${t}${D.reset}`}}}catch(e){return`${D.red}✗ Error generating diff: ${e instanceof Error?e.message:String(e)}${D.reset}`}}async function I(e,t){console.log(``),console.log(`${D.blue}═══════════════════════════════════════════════════════${D.reset}`),console.log(`${D.blue} DRY RUN - Preview of changes${D.reset}`),console.log(`${D.blue}═══════════════════════════════════════════════════════${D.reset}`),console.log(``);for(let n of e){console.log(`${D.cyan}▶ Task: ${n.name}${D.reset}`),console.log(`${D.gray} ${n.description}${D.reset}`),console.log(``);let e=await F(n,t);console.log(e),console.log(``),console.log(`${D.gray}${`─`.repeat(55)}${D.reset}`),console.log(``)}console.log(`${D.blue}═══════════════════════════════════════════════════════${D.reset}`),console.log(`${D.yellow} No changes were applied (dry-run mode)${D.reset}`),console.log(`${D.blue}═══════════════════════════════════════════════════════${D.reset}`),console.log(``)}const L=new Map,R={},z=new Map;function B(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(L.has(e.name))throw TypeError(`Plugin ${e.name} is already registered`);for(let t of e.taskTypes)if(z.has(t)){let e=z.get(t);throw TypeError(`Task type "${t}" is already registered by plugin "${e}"`)}L.set(e.name,e);for(let t of e.taskTypes)z.set(t,e.name);x(`✓ Registered plugin: ${e.name}${e.version==null?``:` v${e.version}`}`,`info`)}function ce(e){let t=L.get(e);if(t!=null){for(let e of t.taskTypes)z.delete(e);L.delete(e)}}function le(e){return L.get(e)}function V(e){let t=z.get(e);if(t!=null)return L.get(t)}function H(e){return z.has(e)}function ue(){return Array.from(L.keys())}function de(){L.clear(),z.clear()}function fe(e){e.beforeAll!=null&&(R.beforeAll=e.beforeAll),e.afterAll!=null&&(R.afterAll=e.afterAll),e.beforeTask!=null&&(R.beforeTask=e.beforeTask),e.afterTask!=null&&(R.afterTask=e.afterTask),e.onError!=null&&(R.onError=e.onError)}async function U(e,...t){let n=R[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){x(`Error in ${e} hook: ${t instanceof Error?t.message:String(t)}`,`error`)}}async function W(e,t,n){let r=V(e.type);if(r==null)throw TypeError(`No plugin found for task type: ${e.type}`);await r.execute(e,t,n)}async function pe(e,t){let n=V(e.type);if(!(n==null||n.getDiff==null))return n.getDiff(e,t)}function me(e){let t=V(e.type);return t==null?[`No plugin found for task type: ${e.type}`]:t.validate==null?[]:t.validate(e)}function he(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 G(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 x(`${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 x(`${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 x(`${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 x(`Unknown prompt type: ${i.type}`,`error`),Error(`Unknown prompt type: ${i.type}`)}r[i.id]=e}catch(e){throw e instanceof Error&&x(`Failed to collect prompt "${i.id}": ${e.message}`,`error`),e}}return console.log(``),r}async function K(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`){x(`Prompt "${t}": exec default value must have a string command`,`error`);return}try{let t=(0,d.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){x(`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 q(e){let t=new Map,n=e.map(async e=>{if(e.default!==void 0){let n=await K(e.default,e.id);n!==void 0&&t.set(e.id,n)}});return await Promise.all(n),t}function J(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 Y=`.scaffoldfyialized`;function X(){let e=l.default.join(u.default.cwd(),Y);if(!c.default.existsSync(e))return null;try{let t=c.default.readFileSync(e,`utf-8`);return JSON.parse(t)}catch{return null}}function ge(e,t,n=!1){if(n)return;let r=l.default.join(u.default.cwd(),`package.json`),i=`0.0.0`;try{i=JSON.parse(c.default.readFileSync(r,`utf-8`)).version??`0.0.0`}catch{}let a={initializedAt:new Date().toISOString(),config:e,completedTasks:t,version:i},o=l.default.join(u.default.cwd(),Y);c.default.writeFileSync(o,JSON.stringify(a,null,2))}const _e=(0,f.promisify)(c.default.writeFile);async function ve(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t)){x(`Condition not met, skipping create task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file);if(c.default.existsSync(n)){x(`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=T(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=S(c.default.readFileSync(r,`utf-8`),t)}else a=S(e.template,t);let o=l.default.dirname(n);c.default.existsSync(o)||c.default.mkdirSync(o,{recursive:!0}),await _e(n,a),x(`Created file: ${e.file}`,`success`)}const ye={name:`create`,version:`1.0.0`,taskTypes:[`create`],execute:async(e,t,n)=>{n.dryRun||await ve(e.config,t)}};async function be(e,t){let{paths:n,condition:r}=e;if(r!=null&&r!==``){if(!t){x(`Condition specified but no config provided, skipping deletion`,`warn`);return}if(!w(r,t)){x(`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 xe={name:`delete`,version:`1.0.0`,taskTypes:[`delete`],execute:async(e,t,n)=>{n.dryRun||await be(e.config,t)}};async function Se(e,t){if(e.condition!=null&&e.condition!==``){if(!t){x(`Condition specified but no config provided, skipping exec`,`warn`);return}if(!w(e.condition,t)){x(`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,d.execSync)(e.command,{cwd:n,stdio:`inherit`})}const Ce={name:`exec`,version:`1.0.0`,taskTypes:[`exec`],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){x(`Condition specified but no config provided, skipping git-init`,`warn`);return}if(!w(e.condition,t)){x(`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,d.execSync)(`git init`,{stdio:`inherit`}),e.initialCommit){let t=e.message??`Initial commit`;(0,d.execSync)(`git add .`,{stdio:`inherit`}),(0,d.execSync)(`git commit -m "${t}"`,{stdio:`inherit`})}}const Te={name:`git-init`,version:`1.0.0`,taskTypes:[`git-init`],execute:async(e,t,n)=>{n.dryRun||await we(e.config,t)}},Ee=(0,f.promisify)(c.default.readFile),De=(0,f.promisify)(c.default.writeFile);async function Oe(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t)){x(`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 Ee(n,`utf-8`),s=new RegExp(r,i);o=o.replace(s,S(a,t)),await De(n,o)}const ke={name:`regex-replace`,version:`1.0.0`,taskTypes:[`regex-replace`],execute:async(e,t,n)=>{n.dryRun||await Oe(e.config,t)}},Ae=(0,f.promisify)(c.default.rename);async function je(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t)){x(`Condition not met, skipping rename task`,`info`);return}let n=l.default.join(u.default.cwd(),S(e.from,t)),r=l.default.join(u.default.cwd(),S(e.to,t));if(!c.default.existsSync(n)){x(`Source path does not exist: ${n}`,`warn`);return}await Ae(n,r)}const Me={name:`rename`,version:`1.0.0`,taskTypes:[`rename`],execute:async(e,t,n)=>{n.dryRun||await je(e.config,t)}},Ne=(0,f.promisify)(c.default.readFile),Pe=(0,f.promisify)(c.default.writeFile);async function Fe(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t)){x(`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)){x(`File not found: ${n}, skipping`,`warn`);return}let i=await Ne(n,`utf-8`);for(let{find:e,replace:n}of r){let r=S(n,t);i=i.replace(new RegExp(e,`gu`),r)}await Pe(n,i)}const Ie={name:`replace-in-file`,version:`1.0.0`,taskTypes:[`replace-in-file`],execute:async(e,t,n)=>{n.dryRun||await Fe(e.config,t)}},Le=(0,f.promisify)(c.default.writeFile);async function Re(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t)){x(`Condition not met, skipping template task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file),r=e.template!=null&&e.template!==``,i=e.templateFile!=null&&e.templateFile!==``;if(!r&&!i)throw Error(`Template task requires either "template" (inline) or "templateFile" (file path) to be specified`);if(r&&i)throw Error(`Template task cannot have both "template" and "templateFile" specified. Use one or the other.`);let a;if(i&&e.templateFile.endsWith(`.hbs`))a=T(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=S(c.default.readFileSync(r,`utf-8`),t)}else a=S(e.template,t);await Le(n,a)}const ze={name:`template`,version:`1.0.0`,taskTypes:[`template`],execute:async(e,t,n)=>{n.dryRun||await Re(e.config,t)}},Be=(0,f.promisify)(c.default.readFile),Ve=(0,f.promisify)(c.default.writeFile),He=2;async function Ue(e,t){if(e.condition!=null&&e.condition!==``&&!w(e.condition,t)){x(`Condition not met, skipping update-json task`,`info`);return}let n=l.default.join(u.default.cwd(),e.file),{updates:r}=e,i=await Be(n,`utf-8`),a=JSON.parse(i);function o(e){if(typeof e==`string`)return S(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(`.`)?C(a,e,n):a[e]=n}await Ve(n,`${JSON.stringify(a,null,2)}\n`)}const We={name:`update-json`,version:`1.0.0`,taskTypes:[`update-json`],execute:async(e,t,n)=>{n.dryRun||await Ue(e.config,t)}};let Ge=!1;function Ke(){Ge||=(B(We),B(ze),B(ye),B(ke),B(Ie),B(xe),B(Me),B(Te),B(Ce),!0)}async function qe(e,t,n=!1){if(Ke(),n){x(`[DRY RUN] Would execute: ${e.name}`,`info`);return}if(H(e.type)){await W(e,t,{dryRun:n});return}throw TypeError(`Unknown task type: ${e.type}`)}async function Je(e,t,n,r,i=!1){try{return x(`[${n}/${r}] Running: ${e.name}...`,`info`),await qe(e,t,i),x(`✓ ${e.name}`,`success`),!0}catch(t){return x(`✗ Failed: ${e.name}`,`error`),t instanceof Error&&(x(` Reason: ${t.message}`,`error`),t.stack!=null&&u.default.env.DEBUG!=null&&console.error(t.stack)),e.required&&x(` This is a required task. Initialization cannot continue.`,`error`),!1}}function Ye(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 Xe(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 Ze(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`){x(`Variable "${t}": exec value must have a string command`,`error`);return}try{let t=(0,d.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){x(`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 Qe(e){let t=new Map,n=e.map(async e=>{let t=await Ze(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 $e(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}const et=(0,f.promisify)(c.default.readFile);async function tt(e,t){let n=X();n&&!t.force&&(console.log(``),x(`⚠️ This template has already been initialized!`,`warn`),console.log(``),x(` Initialized at: ${new Date(n.initializedAt).toLocaleString()}`,`info`),console.log(``),await b(`Do you want to re-initialize? This may cause issues`,!1)||(x(`Initialization cancelled`,`info`),u.default.exit(0)),console.log(``),x(`⚠️ Proceeding with re-initialization...`,`warn`),console.log(``));let r=e.filter(e=>_(e.enabled,g()));x(`Resolving task dependencies...`,`info`);let i=Ye(r);console.log(``),x(`Welcome to the template initialization script!`,`info`),console.log(``),t.dryRun&&(x(`🔍 DRY RUN MODE - No changes will be made`,`warn`),console.log(``)),x(`This will initialize your project based on the defined tasks.`,`info`),console.log(``);let a=g(),o=t.globalVariables??[],s=[],f=[...o];for(let e of i)if(e.variables&&e.variables.length>0)for(let t of e.variables)s.push(t),f.push(t);if(f.length>0){let e=$e(f);e.length>0&&(x(`❌ Variable validation errors:`,`error`),e.forEach(e=>x(` - ${e}`,`error`)),console.log(``),u.default.exit(1)),x(`Resolving variable values...`,`info`);let t=await Qe(f);console.log(``);let n=Xe(f,t);Object.assign(a,n),Object.keys(n).length>0&&(x(`✓ Resolved ${Object.keys(n).length} variable(s)`,`success`),console.log(``))}let p=t.globalPrompts??[],m=[],h=[...p];for(let e of i)if(e.prompts&&e.prompts.length>0)for(let t of e.prompts)m.push(t),h.push(t);if(h.length>0){let e=J(h);e.length>0&&(x(`❌ Prompt validation errors:`,`error`),e.forEach(e=>x(` - ${e}`,`error`)),console.log(``),u.default.exit(1)),x(`Resolving prompt default values...`,`info`);let t=await q(h);console.log(``);let n={};if(p.length>0&&(console.log(``),x(`📋 Top-level prompts (available to all tasks):`,`info`),console.log(``),n=await G(p,t,a),Object.assign(a,n)),m.length>0){p.length>0&&(x(`📋 Task-specific prompts:`,`info`),console.log(``));let e=await G(m,t,a);Object.assign(a,e)}}let v=i.filter(e=>_(e.enabled,a));if(console.log(``),x(`${v.length} of ${i.length} task(s) enabled for execution`,`info`),t.dryRun){await I(v,a),x(`🔍 Dry run completed - no changes were made`,`info`),x(`Run without --dry-run to apply changes`,`info`);return}console.log(``),x(`Starting initialization tasks...`,`info`),console.log(``),await U(`beforeAll`,a);let y=v.length,S=0,C=0,w=[];for(let e=0;e<v.length;e++){let n=v[e];if(n!=null){if(await U(`beforeTask`,n,a),await Je(n,a,e+1,y,t.dryRun))S++,w.push(n.id),await U(`afterTask`,n,a);else if(n.required){C++,await U(`onError`,Error(`Task ${n.name} failed`),n);break}else x(`⚠️ Non-critical task failed, continuing...`,`warn`),await U(`onError`,Error(`Task ${n.name} failed`),n);console.log(``)}}if(C>0&&(x(`❌ Initialization failed with ${C} critical error(s)`,`error`),x(`✓ Completed: ${S}/${y} tasks`,`info`),u.default.exit(1)),await U(`afterAll`,a),ge(a,w,t.dryRun),x(`✅ Initialization completed successfully!`,`success`),console.log(``),x(`✓ Completed: ${S}/${y} tasks`,`success`),console.log(``),!t.dryRun&&t.tasksFilePath!=null&&c.default.existsSync(t.tasksFilePath))try{c.default.unlinkSync(t.tasksFilePath),x(`🗑️ Removed tasks file: ${l.default.basename(t.tasksFilePath)}`,`info`),console.log(``)}catch(e){x(`⚠️ Failed to remove tasks file: ${e instanceof Error?e.message:`Unknown error`}`,`warn`)}if(!t.dryRun){x(`Next steps:`,`info`),x(`1. Review the changes made to your project`,`info`),x(`2. Commit the changes to git`,`info`);let e=l.default.join(u.default.cwd(),`package.json`);c.default.existsSync(e)&&JSON.parse(await et(e,`utf-8`)).scripts?.[`turbo:gen:init`]!=null&&(x(`3. Run "pnpm run turbo:gen:init" to create your first package`,`info`),console.log(``),await b(`Would you like to run turbo:gen:init now?`,!0)&&(console.log(``),x(`Running turbo:gen:init...`,`info`),(0,d.execSync)(`pnpm run turbo:gen:init`,{stdio:`inherit`})))}console.log(``)}const nt=(0,f.promisify)(c.default.readFile);function Z(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}async function rt(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 it(e,t=new Set){let n=Z(e),r;if(r=n||l.default.isAbsolute(e)?e:l.default.resolve(u.default.cwd(),e),Q.has(r))return Q.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 rt(r);else{if(!c.default.existsSync(r))throw Error(`Template file not found: ${r}`);i=await nt(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(!Array.isArray(a.tasks))throw TypeError(`Invalid template file ${r}: 'tasks' array is required`);return Q.set(r,a),a}async function $(e,t,n=new Set){let r=Z(e),i;if(i=r||l.default.isAbsolute(e)?e:t==null?l.default.resolve(u.default.cwd(),e):Z(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 it(i);if(a.extends==null||a.extends===``)return a;let o=Z(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 $(e,o,n);c.push(t)}return at([...c,a])}function at(e){if(e.length===0)return{tasks:[]};if(e.length===1)return e[0];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)r.set(e.id,{...e});if(i.variables!=null)for(let e of i.variables)n.set(e.id,{...e});for(let e of i.tasks)if(t.has(e.id)){let n=t.get(e.id);t.set(e.id,ot(n,e))}else t.set(e.id,{...e})}let i={tasks:Array.from(t.values())};return r.size>0&&(i.prompts=Array.from(r.values())),n.size>0&&(i.variables=Array.from(n.values())),i}function ot(e,t){let n=typeof e.config==`object`&&e.config!==null&&typeof t.config==`object`&&t.config!==null?{...e.config,...t.config}:t.config,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;return{...e,...t,config:n,...r!=null&&{prompts:r},...i!=null&&{variables:i},...o!=null&&{dependencies:o}}}function st(){Q.clear()}async function ct(e){x(`Loading tasks from ${e}...`,`info`);let t=await $(e);x(`Loaded ${t.tasks.length} task(s)`,`info`),t.extends!=null&&t.extends!==``&&x(`Extended from: ${(Array.isArray(t.extends)?t.extends:[t.extends]).join(`, `)}`,`info`),t.prompts!=null&&t.prompts.length>0&&x(`Found ${t.prompts.length} top-level prompt(s)`,`info`),t.variables!=null&&t.variables.length>0&&x(`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 lt=u.default.argv.includes(`--dry-run`),ut=u.default.argv.includes(`--force`);async function dt(e){try{let t=e||[];t.length===0&&(x(`⚠️ No tasks defined. Use --tasks-file to specify tasks or call runWithTasks() programmatically.`,`warn`),console.log(``),x(`Example: scaffoldfy --tasks-file ./tasks.json`,`info`),console.log(``),u.default.exit(1)),await tt(t,{dryRun:lt,force:ut,tasksFilePath:void 0})}catch(e){x(`❌ Initialization failed`,`error`),e instanceof Error?(x(`Error: ${e.message}`,`error`),u.default.env.DEBUG!=null&&console.error(e.stack)):console.error(e),u.default.exit(1)}}async function ft(e,t){try{await tt(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){x(`❌ Initialization failed`,`error`),e instanceof Error?(x(`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 fe}}),Object.defineProperty(exports,`B`,{enumerable:!0,get:function(){return oe}}),Object.defineProperty(exports,`C`,{enumerable:!0,get:function(){return he}}),Object.defineProperty(exports,`D`,{enumerable:!0,get:function(){return pe}}),Object.defineProperty(exports,`E`,{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,`F`,{enumerable:!0,get:function(){return se}}),Object.defineProperty(exports,`G`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`H`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`I`,{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,`J`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`K`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`L`,{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,`M`,{enumerable:!0,get:function(){return ce}}),Object.defineProperty(exports,`N`,{enumerable:!0,get:function(){return me}}),Object.defineProperty(exports,`O`,{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,`P`,{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,`R`,{enumerable:!0,get:function(){return ae}}),Object.defineProperty(exports,`S`,{enumerable:!0,get:function(){return de}}),Object.defineProperty(exports,`T`,{enumerable:!0,get:function(){return le}}),Object.defineProperty(exports,`U`,{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,`V`,{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,`W`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`X`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`Y`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`Z`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return J}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return ct}}),Object.defineProperty(exports,`b`,{enumerable:!0,get:function(){return G}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return $e}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return Xe}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return Ye}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return ge}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return X}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,`j`,{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,`k`,{enumerable:!0,get:function(){return ue}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return Qe}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return Je}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return ft}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return it}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return qe}}),Object.defineProperty(exports,`q`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return st}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return at}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return dt}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return Ze}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,`w`,{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,`x`,{enumerable:!0,get:function(){return U}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,`z`,{enumerable:!0,get:function(){return M}});
@@ -0,0 +1,17 @@
1
+ import e from"node:path";import t from"node:fs";import n from"node:process";import{execSync as r}from"node:child_process";import{promisify as i}from"node:util";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=r(`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}`)}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 x(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 S(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 S(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 C=i(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!==``&&!b(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 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`${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 O(r,i){if(r.condition!=null&&r.condition!==``&&!b(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=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`${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 ee(r,i){if(r.condition!=null&&r.condition!==``&&!b(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=v(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 k(r,i){if(r.condition!=null&&r.condition!==``&&!b(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=v(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 A(r,i){if(r.condition!=null&&r.condition!==``&&!b(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=v(t,i),a=v(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 te(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let a=r.paths.map(e=>v(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 ne(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i))return`${w.yellow}⊘ Condition not met - task would be skipped${w.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)?`${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 re(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 ie(e,t){if(e.condition!=null&&e.condition!==``&&!b(e.condition,t))return`${w.yellow}⊘ Condition not met - task would be skipped${w.reset}`;let r=v(e.command,t),i=e.cwd==null?n.cwd():v(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 ae(e,t){try{switch(e.type){case`update-json`:return await D(e.config,t);case`template`:return await O(e.config,t);case`create`:return await ee(e.config,t);case`regex-replace`:return await k(e.config,t);case`replace-in-file`:return await A(e.config,t);case`delete`:return te(e.config,t);case`rename`:return ne(e.config,t);case`git-init`:return re(e.config);case`exec`:return ie(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(``),console.log(`${w.blue}═══════════════════════════════════════════════════════${w.reset}`),console.log(`${w.blue} DRY RUN - Preview of changes${w.reset}`),console.log(`${w.blue}═══════════════════════════════════════════════════════${w.reset}`),console.log(``);for(let n of e){console.log(`${w.cyan}▶ Task: ${n.name}${w.reset}`),console.log(`${w.gray} ${n.description}${w.reset}`),console.log(``);let e=await ae(n,t);console.log(e),console.log(``),console.log(`${w.gray}${`─`.repeat(55)}${w.reset}`),console.log(``)}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}`),console.log(``)}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);_(`✓ Registered plugin: ${e.name}${e.version==null?``:` v${e.version}`}`,`info`)}function oe(e){let t=M.get(e);if(t!=null){for(let e of t.taskTypes)P.delete(e);M.delete(e)}}function se(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 ce(){return Array.from(M.keys())}function le(){M.clear(),P.clear()}function ue(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){_(`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 de(e,t){let n=I(e.type);if(!(n==null||n.getDiff==null))return n.getDiff(e,t)}function fe(e){let t=I(e.type);return t==null?[`No plugin found for task type: ${e.type}`]:t.validate==null?[]:t.validate(e)}function pe(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 B(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 console.log(``),r}async function V(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=r(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 H(e){let t=new Map,n=e.map(async e=>{if(e.default!==void 0){let n=await V(e.default,e.id);n!==void 0&&t.set(e.id,n)}});return await Promise.all(n),t}function U(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 W=`.scaffoldfyialized`;function G(){let r=e.join(n.cwd(),W);if(!t.existsSync(r))return null;try{let e=t.readFileSync(r,`utf-8`);return JSON.parse(e)}catch{return null}}function K(r,i,a=!1){if(a)return;let o=e.join(n.cwd(),`package.json`),s=`0.0.0`;try{s=JSON.parse(t.readFileSync(o,`utf-8`)).version??`0.0.0`}catch{}let c={initializedAt:new Date().toISOString(),config:r,completedTasks:i,version:s},l=e.join(n.cwd(),W);t.writeFileSync(l,JSON.stringify(c,null,2))}const me=i(t.writeFile);async function he(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=x(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 me(a,c),_(`Created file: ${r.file}`,`success`)}const ge={name:`create`,version:`1.0.0`,taskTypes:[`create`],execute:async(e,t,n)=>{n.dryRun||await he(e.config,t)}};async function _e(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 ve={name:`delete`,version:`1.0.0`,taskTypes:[`delete`],execute:async(e,t,n)=>{n.dryRun||await _e(e.config,t)}};async function ye(t,i){if(t.condition!=null&&t.condition!==``){if(!i){_(`Condition specified but no config provided, skipping exec`,`warn`);return}if(!b(t.condition,i)){_(`Condition not met, skipping exec task`,`info`);return}}let a=t.cwd==null?n.cwd():e.join(n.cwd(),t.cwd);r(t.command,{cwd:a,stdio:`inherit`})}const be={name:`exec`,version:`1.0.0`,taskTypes:[`exec`],execute:async(e,t,n)=>{n.dryRun||await ye(e.config,t)}};async function xe(i,a){if(i.condition!=null&&i.condition!==``){if(!a){_(`Condition specified but no config provided, skipping git-init`,`warn`);return}if(!b(i.condition,a)){_(`Condition not met, skipping git-init task`,`info`);return}}if(i.removeExisting){let r=e.join(n.cwd(),`.git`);t.existsSync(r)&&t.rmSync(r,{recursive:!0,force:!0})}if(r(`git init`,{stdio:`inherit`}),i.initialCommit){let e=i.message??`Initial commit`;r(`git add .`,{stdio:`inherit`}),r(`git commit -m "${e}"`,{stdio:`inherit`})}}const Se={name:`git-init`,version:`1.0.0`,taskTypes:[`git-init`],execute:async(e,t,n)=>{n.dryRun||await xe(e.config,t)}},Ce=i(t.readFile),we=i(t.writeFile);async function Te(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 Ce(i,`utf-8`),l=new RegExp(a,o);c=c.replace(l,v(s,r)),await we(i,c)}const Ee={name:`regex-replace`,version:`1.0.0`,taskTypes:[`regex-replace`],execute:async(e,t,n)=>{n.dryRun||await Te(e.config,t)}},De=i(t.rename);async function Oe(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 De(a,o)}const ke={name:`rename`,version:`1.0.0`,taskTypes:[`rename`],execute:async(e,t,n)=>{n.dryRun||await Oe(e.config,t)}},Ae=i(t.readFile),je=i(t.writeFile);async function Me(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 Ae(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 je(a,s)}const Ne={name:`replace-in-file`,version:`1.0.0`,taskTypes:[`replace-in-file`],execute:async(e,t,n)=>{n.dryRun||await Me(e.config,t)}},Pe=i(t.writeFile);async function Fe(r,i){if(r.condition!=null&&r.condition!==``&&!b(r.condition,i)){_(`Condition not met, skipping template task`,`info`);return}let a=e.join(n.cwd(),r.file),o=r.template!=null&&r.template!==``,s=r.templateFile!=null&&r.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&&r.templateFile.endsWith(`.hbs`))c=x(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);await Pe(a,c)}const Ie={name:`template`,version:`1.0.0`,taskTypes:[`template`],execute:async(e,t,n)=>{n.dryRun||await Fe(e.config,t)}},Le=i(t.readFile),Re=i(t.writeFile);async function ze(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 Le(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 Re(i,`${JSON.stringify(s,null,2)}\n`)}const Be={name:`update-json`,version:`1.0.0`,taskTypes:[`update-json`],execute:async(e,t,n)=>{n.dryRun||await ze(e.config,t)}};let Ve=!1;function He(){Ve||=(F(Be),F(Ie),F(ge),F(Ee),F(Ne),F(ve),F(ke),F(Se),F(be),!0)}async function q(e,t,n=!1){if(He(),n){_(`[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 J(e,t,r,i,a=!1){try{return _(`[${r}/${i}] Running: ${e.name}...`,`info`),await q(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 Y(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 Ue(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 We(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=r(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 Ge(e){let t=new Map,n=e.map(async e=>{let t=await We(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 Ke(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}const qe=i(t.readFile);async function Je(i,a){let o=G();o&&!a.force&&(console.log(``),_(`⚠️ This template has already been initialized!`,`warn`),console.log(``),_(` Initialized at: ${new Date(o.initializedAt).toLocaleString()}`,`info`),console.log(``),await g(`Do you want to re-initialize? This may cause issues`,!1)||(_(`Initialization cancelled`,`info`),n.exit(0)),console.log(``),_(`⚠️ Proceeding with re-initialization...`,`warn`),console.log(``));let s=i.filter(e=>p(e.enabled,f()));_(`Resolving task dependencies...`,`info`);let c=Y(s);console.log(``),_(`Welcome to the template initialization script!`,`info`),console.log(``),a.dryRun&&(_(`🔍 DRY RUN MODE - No changes will be made`,`warn`),console.log(``)),_(`This will initialize your project based on the defined tasks.`,`info`),console.log(``);let l=f(),u=a.globalVariables??[],d=[],m=[...u];for(let e of c)if(e.variables&&e.variables.length>0)for(let t of e.variables)d.push(t),m.push(t);if(m.length>0){let e=Ke(m);e.length>0&&(_(`❌ Variable validation errors:`,`error`),e.forEach(e=>_(` - ${e}`,`error`)),console.log(``),n.exit(1)),_(`Resolving variable values...`,`info`);let t=await Ge(m);console.log(``);let r=Ue(m,t);Object.assign(l,r),Object.keys(r).length>0&&(_(`✓ Resolved ${Object.keys(r).length} variable(s)`,`success`),console.log(``))}let h=a.globalPrompts??[],v=[],y=[...h];for(let e of c)if(e.prompts&&e.prompts.length>0)for(let t of e.prompts)v.push(t),y.push(t);if(y.length>0){let e=U(y);e.length>0&&(_(`❌ Prompt validation errors:`,`error`),e.forEach(e=>_(` - ${e}`,`error`)),console.log(``),n.exit(1)),_(`Resolving prompt default values...`,`info`);let t=await H(y);console.log(``);let r={};if(h.length>0&&(console.log(``),_(`📋 Top-level prompts (available to all tasks):`,`info`),console.log(``),r=await B(h,t,l),Object.assign(l,r)),v.length>0){h.length>0&&(_(`📋 Task-specific prompts:`,`info`),console.log(``));let e=await B(v,t,l);Object.assign(l,e)}}let b=c.filter(e=>p(e.enabled,l));if(console.log(``),_(`${b.length} of ${c.length} task(s) enabled for execution`,`info`),a.dryRun){await j(b,l),_(`🔍 Dry run completed - no changes were made`,`info`),_(`Run without --dry-run to apply changes`,`info`);return}console.log(``),_(`Starting initialization tasks...`,`info`),console.log(``),await R(`beforeAll`,l);let x=b.length,S=0,C=0,w=[];for(let e=0;e<b.length;e++){let t=b[e];if(t!=null){if(await R(`beforeTask`,t,l),await J(t,l,e+1,x,a.dryRun))S++,w.push(t.id),await R(`afterTask`,t,l);else if(t.required){C++,await R(`onError`,Error(`Task ${t.name} failed`),t);break}else _(`⚠️ Non-critical task failed, continuing...`,`warn`),await R(`onError`,Error(`Task ${t.name} failed`),t);console.log(``)}}if(C>0&&(_(`❌ Initialization failed with ${C} critical error(s)`,`error`),_(`✓ Completed: ${S}/${x} tasks`,`info`),n.exit(1)),await R(`afterAll`,l),K(l,w,a.dryRun),_(`✅ Initialization completed successfully!`,`success`),console.log(``),_(`✓ Completed: ${S}/${x} tasks`,`success`),console.log(``),!a.dryRun&&a.tasksFilePath!=null&&t.existsSync(a.tasksFilePath))try{t.unlinkSync(a.tasksFilePath),_(`🗑️ Removed tasks file: ${e.basename(a.tasksFilePath)}`,`info`),console.log(``)}catch(e){_(`⚠️ Failed to remove tasks file: ${e instanceof Error?e.message:`Unknown error`}`,`warn`)}if(!a.dryRun){_(`Next steps:`,`info`),_(`1. Review the changes made to your project`,`info`),_(`2. Commit the changes to git`,`info`);let i=e.join(n.cwd(),`package.json`);t.existsSync(i)&&JSON.parse(await qe(i,`utf-8`)).scripts?.[`turbo:gen:init`]!=null&&(_(`3. Run "pnpm run turbo:gen:init" to create your first package`,`info`),console.log(``),await g(`Would you like to run turbo:gen:init now?`,!0)&&(console.log(``),_(`Running turbo:gen:init...`,`info`),r(`pnpm run turbo:gen:init`,{stdio:`inherit`})))}console.log(``)}const Ye=i(t.readFile);function X(e){try{let t=new URL(e);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}async function Xe(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 Ze(r,i=new Set){let a=X(r),o;if(o=a||e.isAbsolute(r)?r:e.resolve(n.cwd(),r),Z.has(o))return Z.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 Xe(o);else{if(!t.existsSync(o))throw Error(`Template file not found: ${o}`);s=await Ye(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(!Array.isArray(c.tasks))throw TypeError(`Invalid template file ${o}: 'tasks' array is required`);return Z.set(o,c),c}async function Q(t,r,i=new Set){let a=X(t),o;if(o=a||e.isAbsolute(t)?t:r==null?e.resolve(n.cwd(),t):X(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 Ze(o);if(s.extends==null||s.extends===``)return s;let c=X(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 Q(e,c,i);u.push(t)}return $([...u,s])}function $(e){if(e.length===0)return{tasks:[]};if(e.length===1)return e[0];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)r.set(e.id,{...e});if(i.variables!=null)for(let e of i.variables)n.set(e.id,{...e});for(let e of i.tasks)if(t.has(e.id)){let n=t.get(e.id);t.set(e.id,Qe(n,e))}else t.set(e.id,{...e})}let i={tasks:Array.from(t.values())};return r.size>0&&(i.prompts=Array.from(r.values())),n.size>0&&(i.variables=Array.from(n.values())),i}function Qe(e,t){let n=typeof e.config==`object`&&e.config!==null&&typeof t.config==`object`&&t.config!==null?{...e.config,...t.config}:t.config,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;return{...e,...t,config:n,...r!=null&&{prompts:r},...i!=null&&{variables:i},...o!=null&&{dependencies:o}}}function $e(){Z.clear()}async function et(e){_(`Loading tasks from ${e}...`,`info`);let t=await Q(e);_(`Loaded ${t.tasks.length} 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 tt=n.argv.includes(`--dry-run`),nt=n.argv.includes(`--force`);async function rt(e){try{let t=e||[];t.length===0&&(_(`⚠️ No tasks defined. Use --tasks-file to specify tasks or call runWithTasks() programmatically.`,`warn`),console.log(``),_(`Example: scaffoldfy --tasks-file ./tasks.json`,`info`),console.log(``),n.exit(1)),await Je(t,{dryRun:tt,force:nt,tasksFilePath:void 0})}catch(e){_(`❌ Initialization 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 it(e,t){try{await Je(e,{dryRun:t?.dryRun??tt,force:t?.force??nt,tasksFilePath:t?.tasksFilePath??void 0,...t?.globalVariables!=null&&{globalVariables:t.globalVariables},...t?.globalPrompts!=null&&{globalPrompts:t.globalPrompts}})}catch(e){_(`❌ Initialization failed`,`error`),e instanceof Error?(_(`Error: ${e.message}`,`error`),n.env.DEBUG!=null&&console.error(e.stack)):console.error(e),n.exit(1)}}export{ue as A,A as B,pe as C,de as D,I as E,te as F,m as G,O as H,ie as I,h as J,v as K,re as L,oe as M,fe as N,L as O,j as P,k as R,le as S,se as T,D as U,ae as V,b as W,y as X,g as Y,U as _,et as a,B as b,Ke as c,Ue as d,Y as f,K as g,G as h,Q as i,F as j,ce as k,Ge as l,J as m,it as n,Ze as o,q as p,_ as q,$e as r,$ as s,rt as t,We as u,H as v,z as w,R as x,V as y,ne as z};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pixpilot/scaffoldfy",
3
3
  "type": "module",
4
- "version": "0.7.0",
4
+ "version": "0.9.0",
5
5
  "author": "PixPilot <m.doaie@hotmail.com>",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -47,10 +47,10 @@
47
47
  "tsdown": "^0.15.8",
48
48
  "typescript": "^5.9.3",
49
49
  "@internal/eslint-config": "0.3.0",
50
+ "@internal/prettier-config": "0.0.1",
50
51
  "@internal/tsconfig": "0.1.0",
51
52
  "@internal/tsdown-config": "0.1.0",
52
- "@internal/vitest-config": "0.1.0",
53
- "@internal/prettier-config": "0.0.1"
53
+ "@internal/vitest-config": "0.1.0"
54
54
  },
55
55
  "prettier": "@internal/prettier-config",
56
56
  "scripts": {