200 lines
5.9 KiB
TypeScript
200 lines
5.9 KiB
TypeScript
import * as plugins from './tswatch.plugins.js';
|
|
import * as paths from './tswatch.paths.js';
|
|
import * as interfaces from './interfaces/index.js';
|
|
import { ConfigHandler } from './tswatch.classes.confighandler.js';
|
|
import { logger } from './tswatch.logging.js';
|
|
|
|
const CONFIG_KEY = '@git.zone/tswatch';
|
|
|
|
/**
|
|
* Interactive init wizard for creating tswatch configuration
|
|
*/
|
|
export class TswatchInit {
|
|
private configHandler: ConfigHandler;
|
|
private smartInteract: plugins.smartinteract.SmartInteract;
|
|
|
|
constructor() {
|
|
this.configHandler = new ConfigHandler();
|
|
this.smartInteract = new plugins.smartinteract.SmartInteract([]);
|
|
}
|
|
|
|
/**
|
|
* Run the interactive init wizard
|
|
*/
|
|
public async run(): Promise<interfaces.ITswatchConfig | null> {
|
|
console.log('\n=== tswatch Configuration Wizard ===\n');
|
|
|
|
// Ask for template choice
|
|
const templateAnswer = await this.smartInteract.askQuestion({
|
|
name: 'template',
|
|
type: 'list',
|
|
message: 'Select a configuration template:',
|
|
default: 'npm',
|
|
choices: [
|
|
{ name: 'npm - Watch ts/ and test/, run npm test', value: 'npm' },
|
|
{ name: 'test - Watch ts/ and test/, run npm run test2', value: 'test' },
|
|
{ name: 'service - Watch ts/, restart npm run startTs', value: 'service' },
|
|
{ name: 'element - Dev server + bundling for web components', value: 'element' },
|
|
{ name: 'website - Full stack: backend + frontend + assets', value: 'website' },
|
|
{ name: 'custom - Configure watchers manually', value: 'custom' },
|
|
],
|
|
});
|
|
|
|
const template = templateAnswer.value as string;
|
|
|
|
let config: interfaces.ITswatchConfig;
|
|
|
|
if (template === 'custom') {
|
|
config = await this.runCustomWizard();
|
|
} else {
|
|
// Get preset config
|
|
const preset = this.configHandler.getPreset(template);
|
|
if (!preset) {
|
|
console.error(`Unknown template: ${template}`);
|
|
return null;
|
|
}
|
|
config = { ...preset, preset: template as interfaces.ITswatchConfig['preset'] };
|
|
}
|
|
|
|
// Save to npmextra.json
|
|
await this.saveConfig(config);
|
|
|
|
console.log('\nConfiguration saved to npmextra.json');
|
|
console.log('Run "tswatch" to start watching.\n');
|
|
|
|
return config;
|
|
}
|
|
|
|
/**
|
|
* Run custom configuration wizard
|
|
*/
|
|
private async runCustomWizard(): Promise<interfaces.ITswatchConfig> {
|
|
const config: interfaces.ITswatchConfig = {};
|
|
|
|
// Ask about server
|
|
const serverAnswer = await this.smartInteract.askQuestion({
|
|
name: 'enableServer',
|
|
type: 'confirm',
|
|
message: 'Enable development server?',
|
|
default: false,
|
|
});
|
|
|
|
if (serverAnswer.value) {
|
|
const portAnswer = await this.smartInteract.askQuestion({
|
|
name: 'port',
|
|
type: 'input',
|
|
message: 'Server port:',
|
|
default: '3002',
|
|
});
|
|
|
|
const serveDirAnswer = await this.smartInteract.askQuestion({
|
|
name: 'serveDir',
|
|
type: 'input',
|
|
message: 'Directory to serve:',
|
|
default: './dist_watch/',
|
|
});
|
|
|
|
config.server = {
|
|
enabled: true,
|
|
port: parseInt(portAnswer.value as string, 10),
|
|
serveDir: serveDirAnswer.value as string,
|
|
liveReload: true,
|
|
};
|
|
}
|
|
|
|
// Add watchers
|
|
config.watchers = [];
|
|
let addMore = true;
|
|
|
|
while (addMore) {
|
|
console.log('\n--- Add a watcher ---');
|
|
|
|
const nameAnswer = await this.smartInteract.askQuestion({
|
|
name: 'name',
|
|
type: 'input',
|
|
message: 'Watcher name:',
|
|
default: `watcher-${config.watchers.length + 1}`,
|
|
});
|
|
|
|
const watchAnswer = await this.smartInteract.askQuestion({
|
|
name: 'watch',
|
|
type: 'input',
|
|
message: 'Glob pattern(s) to watch (comma-separated):',
|
|
default: './ts/**/*',
|
|
});
|
|
|
|
const commandAnswer = await this.smartInteract.askQuestion({
|
|
name: 'command',
|
|
type: 'input',
|
|
message: 'Command to execute:',
|
|
default: 'npm run test',
|
|
});
|
|
|
|
const restartAnswer = await this.smartInteract.askQuestion({
|
|
name: 'restart',
|
|
type: 'confirm',
|
|
message: 'Restart command on each change (vs queue)?',
|
|
default: true,
|
|
});
|
|
|
|
// Parse watch patterns
|
|
const watchPatterns = (watchAnswer.value as string)
|
|
.split(',')
|
|
.map((p) => p.trim())
|
|
.filter((p) => p.length > 0);
|
|
|
|
config.watchers.push({
|
|
name: nameAnswer.value as string,
|
|
watch: watchPatterns.length === 1 ? watchPatterns[0] : watchPatterns,
|
|
command: commandAnswer.value as string,
|
|
restart: restartAnswer.value as boolean,
|
|
debounce: 300,
|
|
runOnStart: true,
|
|
});
|
|
|
|
const moreAnswer = await this.smartInteract.askQuestion({
|
|
name: 'addMore',
|
|
type: 'confirm',
|
|
message: 'Add another watcher?',
|
|
default: false,
|
|
});
|
|
|
|
addMore = moreAnswer.value as boolean;
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
/**
|
|
* Save configuration to npmextra.json
|
|
*/
|
|
private async saveConfig(config: interfaces.ITswatchConfig): Promise<void> {
|
|
const npmextraPath = plugins.path.join(paths.cwd, 'npmextra.json');
|
|
|
|
// Read existing npmextra.json if it exists
|
|
let existingConfig: Record<string, any> = {};
|
|
try {
|
|
const smartfsInstance = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
|
|
const content = await smartfsInstance.file(npmextraPath).encoding('utf8').read() as string;
|
|
existingConfig = JSON.parse(content);
|
|
} catch {
|
|
// File doesn't exist or is invalid, start fresh
|
|
}
|
|
|
|
// Update with new tswatch config
|
|
existingConfig[CONFIG_KEY] = config;
|
|
|
|
// Write back
|
|
const smartfsInstance = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
|
|
await smartfsInstance.file(npmextraPath).encoding('utf8').write(JSON.stringify(existingConfig, null, 2));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run the init wizard
|
|
*/
|
|
export const runInit = async (): Promise<interfaces.ITswatchConfig | null> => {
|
|
const init = new TswatchInit();
|
|
return init.run();
|
|
};
|