diff --git a/README.md b/README.md index ecdaa01..769eb4c 100644 --- a/README.md +++ b/README.md @@ -114,8 +114,8 @@ For detailed information about the project: ### 🌐 Documentation in Other Languages -- **[🇧🇷 Português (Brasil)](docs/pt-BR/)** - Documentação em português _(em desenvolvimento)_ -- **[🇪🇸 Español](docs/es/)** - Documentación en español _(en desarrollo)_ +- **[🇧🇷 Português (Brasil)](docs/pt-BR/)** - Documentação em português +- **[🇪🇸 Español](docs/es/)** - Documentación en español _Want to help translate the documentation? Check our [contribution guide](docs/CONTRIBUTING.md#internationalization)!_ diff --git a/docs/README.md b/docs/README.md index 49a5848..f106143 100644 --- a/docs/README.md +++ b/docs/README.md @@ -21,8 +21,8 @@ Welcome to the StackCode documentation hub! This directory contains comprehensiv ### 🌐 **Translations** -- **[🇧🇷 Português (Brasil)](pt-BR/)** - Documentação em português _(em desenvolvimento)_ -- **[🇪🇸 Español](es/)** - Documentación en español _(en desarrollo)_ +- **[🇧🇷 Português (Brasil)](pt-BR/)** - Documentação em português +- **[🇪🇸 Español](es/)** - Documentación en español ## 🎯 **Documentation by Audience** diff --git a/docs/SELF_HOSTING_GUIDE.md b/docs/SELF_HOSTING_GUIDE.md index 04a2079..64a0851 100644 --- a/docs/SELF_HOSTING_GUIDE.md +++ b/docs/SELF_HOSTING_GUIDE.md @@ -114,27 +114,22 @@ docker run -it your-org/stackcode init export type SupportedStack = "node-js" | "react" | "your-custom-stack"; // Add your stack ``` -### Configuration Customization +### Basic Configuration -1. **Default Configuration** +StackCode supports a simple `.stackcoderc.json` configuration file to set project defaults: - ```json - // Create .stackcoderc in your users' home directories - { - "defaultAuthor": "Your Organization", - "defaultLicense": "Proprietary", - "organizationTemplates": true, - "privateRegistry": "https://your-npm-registry.com" - } - ``` +```json +// .stackcoderc.json (in project root) +{ + "features": { + "commitValidation": true + } +} +``` -2. **Environment Variables** - ```bash - # Set organization defaults - export STACKCODE_DEFAULT_AUTHOR="Your Organization" - export STACKCODE_PRIVATE_REGISTRY="https://your-npm-registry.com" - export STACKCODE_TEMPLATE_PATH="/path/to/custom/templates" - ``` +This configuration currently supports: + +- `commitValidation`: Enable/disable conventional commit validation ### Internationalization @@ -154,62 +149,6 @@ echo '{"welcome": "Willkommen"}' > packages/i18n/src/locales/de.json 2. **Dependency Scanning**: Regularly scan dependencies for vulnerabilities 3. **Access Control**: Restrict who can modify templates and configurations -### Network Security - -1. **Private Registries**: Use private NPM registries for internal packages -2. **VPN Access**: Require VPN for accessing internal StackCode instances -3. **Audit Logging**: Log all template generations and modifications - -### Template Security - -1. **Sanitize Inputs**: Validate all user inputs in templates -2. **Restrict File Access**: Limit template file system access -3. **Code Review Templates**: Review all custom templates for security issues - -## 🔄 Update Management - -### Versioning Strategy - -1. **Semantic Versioning**: Follow semver for your organization's version -2. **Release Notes**: Maintain detailed changelog for internal releases -3. **Testing Pipeline**: Test all changes before deploying to teams - -### Update Process - -```bash -# Update from upstream -git remote add upstream https://github.com/YagoBorba/StackCode.git -git fetch upstream -git merge upstream/develop - -# Review changes and test -npm test -npm run build - -# Deploy to your organization -npm publish --registry https://your-npm-registry.com -``` - -## 🏗️ Architecture for Organizations - -### Centralized Configuration - -``` -Organization Setup: -├── stackcode-config/ -│ ├── templates/ # Custom organization templates -│ ├── configs/ # Default configurations -│ └── policies/ # Development policies -├── private-registry/ # Internal NPM registry -└── deployment/ # Deployment scripts -``` - -### Team Integration - -1. **Team Templates**: Create templates specific to different teams -2. **Approval Workflows**: Implement approval processes for new templates -3. **Usage Analytics**: Track template usage across teams - ## 🛠️ Troubleshooting ### Common Issues @@ -232,33 +171,24 @@ Organization Setup: ls packages/core/dist/templates/ ``` -3. **Registry Issues** +3. **Build Issues** ```bash - # Check registry configuration - npm config get registry + # Check if templates are properly copied + npm run build + ls packages/core/dist/templates/ - # Test registry connectivity - npm ping --registry https://your-registry.com + # Verify build output + npm test ``` -### Support and Maintenance - -1. **Internal Documentation**: Maintain organization-specific documentation -2. **Support Channels**: Set up internal support channels for StackCode issues -3. **Regular Updates**: Schedule regular updates from the upstream repository - ## 📋 Deployment Checklist - [ ] Repository forked and customized - [ ] Custom templates created and tested -- [ ] Configuration files distributed to teams -- [ ] Private registry configured (if applicable) -- [ ] Security review completed -- [ ] Team training conducted -- [ ] Monitoring and logging set up -- [ ] Update process documented -- [ ] Support process established +- [ ] Build process completed successfully +- [ ] Tests passing +- [ ] Documentation updated for customizations ## 🤝 Contributing Back diff --git a/docs/es/SELF_HOSTING_GUIDE.md b/docs/es/SELF_HOSTING_GUIDE.md index 8ce6f62..9f21c3e 100644 --- a/docs/es/SELF_HOSTING_GUIDE.md +++ b/docs/es/SELF_HOSTING_GUIDE.md @@ -146,71 +146,7 @@ echo '{"welcome": "Bienvenido"}' > packages/i18n/src/locales/es.json echo '{"welcome": "Willkommen"}' > packages/i18n/src/locales/de.json ``` -## 🔒 Security Considerations - -### Code Review Process - -1. **Fork and Review**: Always fork the repository and review changes -2. **Dependency Scanning**: Regularly scan dependencies for vulnerabilities -3. **Access Control**: Restrict who can modify templates and configurations - -### Network Security - -1. **Private Registries**: Use private NPM registries for internal packages -2. **VPN Access**: Require VPN for accessing internal StackCode instances -3. **Audit Logging**: Log all template generations and modifications - -### Template Security - -1. **Sanitize Inputs**: Validate all user inputs in templates -2. **Restrict File Access**: Limit template file system access -3. **Code Review Templates**: Review all custom templates for security issues - -## 🔄 Update Management - -### Versioning Strategy - -1. **Semantic Versioning**: Follow semver for your organization's version -2. **Release Notes**: Maintain detailed changelog for internal releases -3. **Testing Pipeline**: Test all changes before deploying to teams - -### Update Process - -```bash -# Update from upstream -git remote add upstream https://github.com/YagoBorba/StackCode.git -git fetch upstream -git merge upstream/develop - -# Review changes and test -npm test -npm run build - -# Deploy to your organization -npm publish --registry https://your-npm-registry.com -``` - -## 🏗️ Architecture for Organizations - -### Centralized Configuration - -``` -Organization Setup: -├── stackcode-config/ -│ ├── templates/ # Custom organization templates -│ ├── configs/ # Default configurations -│ └── policies/ # Development policies -├── private-registry/ # Internal NPM registry -└── deployment/ # Deployment scripts -``` - -### Team Integration - -1. **Team Templates**: Create templates specific to different teams -2. **Approval Workflows**: Implement approval processes for new templates -3. **Usage Analytics**: Track template usage across teams - -## 🛠️ Troubleshooting +## ️ Troubleshooting ### Common Issues diff --git a/docs/pt-BR/SELF_HOSTING_GUIDE.md b/docs/pt-BR/SELF_HOSTING_GUIDE.md index 4666264..2393ad8 100644 --- a/docs/pt-BR/SELF_HOSTING_GUIDE.md +++ b/docs/pt-BR/SELF_HOSTING_GUIDE.md @@ -114,28 +114,6 @@ docker run -it sua-org/stackcode init export type SupportedStack = "node-js" | "react" | "seu-stack-personalizado"; // Adicionar seu stack ``` -### Personalização de Configuração - -1. **Configuração Padrão** - - ```json - // Criar .stackcoderc nos diretórios home dos usuários - { - "defaultAuthor": "Sua Organização", - "defaultLicense": "Proprietário", - "organizationTemplates": true, - "privateRegistry": "https://seu-registro-npm.com" - } - ``` - -2. **Variáveis de Ambiente** - ```bash - # Definir padrões da organização - export STACKCODE_DEFAULT_AUTHOR="Sua Organização" - export STACKCODE_PRIVATE_REGISTRY="https://seu-registro-npm.com" - export STACKCODE_TEMPLATE_PATH="/caminho/para/templates/personalizados" - ``` - ### Internacionalização Adicione suporte para os idiomas da sua organização: @@ -190,26 +168,6 @@ npm run build npm publish --registry https://seu-registro-npm.com ``` -## 🏗️ Arquitetura para Organizações - -### Configuração Centralizada - -``` -Configuração da Organização: -├── stackcode-config/ -│ ├── templates/ # Templates personalizados da organização -│ ├── configs/ # Configurações padrão -│ └── policies/ # Políticas de desenvolvimento -├── private-registry/ # Registro NPM interno -└── deployment/ # Scripts de implantação -``` - -### Integração de Equipes - -1. **Templates de Equipe**: Criar templates específicos para diferentes equipes -2. **Fluxos de Aprovação**: Implementar processos de aprovação para novos templates -3. **Analytics de Uso**: Rastrear uso de templates entre equipes - ## 🛠️ Solução de Problemas ### Problemas Comuns @@ -366,28 +324,6 @@ docker run -it your-org/stackcode init export type SupportedStack = "node-js" | "react" | "your-custom-stack"; // Add your stack ``` -### Configuration Customization - -1. **Default Configuration** - - ```json - // Create .stackcoderc in your users' home directories - { - "defaultAuthor": "Your Organization", - "defaultLicense": "Proprietary", - "organizationTemplates": true, - "privateRegistry": "https://your-npm-registry.com" - } - ``` - -2. **Environment Variables** - ```bash - # Set organization defaults - export STACKCODE_DEFAULT_AUTHOR="Your Organization" - export STACKCODE_PRIVATE_REGISTRY="https://your-npm-registry.com" - export STACKCODE_TEMPLATE_PATH="/path/to/custom/templates" - ``` - ### Internationalization Add support for your organization's languages: @@ -398,71 +334,7 @@ echo '{"welcome": "Bienvenido"}' > packages/i18n/src/locales/es.json echo '{"welcome": "Willkommen"}' > packages/i18n/src/locales/de.json ``` -## 🔒 Security Considerations - -### Code Review Process - -1. **Fork and Review**: Always fork the repository and review changes -2. **Dependency Scanning**: Regularly scan dependencies for vulnerabilities -3. **Access Control**: Restrict who can modify templates and configurations - -### Network Security - -1. **Private Registries**: Use private NPM registries for internal packages -2. **VPN Access**: Require VPN for accessing internal StackCode instances -3. **Audit Logging**: Log all template generations and modifications - -### Template Security - -1. **Sanitize Inputs**: Validate all user inputs in templates -2. **Restrict File Access**: Limit template file system access -3. **Code Review Templates**: Review all custom templates for security issues - -## 🔄 Update Management - -### Versioning Strategy - -1. **Semantic Versioning**: Follow semver for your organization's version -2. **Release Notes**: Maintain detailed changelog for internal releases -3. **Testing Pipeline**: Test all changes before deploying to teams - -### Update Process - -```bash -# Update from upstream -git remote add upstream https://github.com/YagoBorba/StackCode.git -git fetch upstream -git merge upstream/develop - -# Review changes and test -npm test -npm run build - -# Deploy to your organization -npm publish --registry https://your-npm-registry.com -``` - -## 🏗️ Architecture for Organizations - -### Centralized Configuration - -``` -Organization Setup: -├── stackcode-config/ -│ ├── templates/ # Custom organization templates -│ ├── configs/ # Default configurations -│ └── policies/ # Development policies -├── private-registry/ # Internal NPM registry -└── deployment/ # Deployment scripts -``` - -### Team Integration - -1. **Team Templates**: Create templates specific to different teams -2. **Approval Workflows**: Implement approval processes for new templates -3. **Usage Analytics**: Track template usage across teams - -## 🛠️ Troubleshooting +## ️ Troubleshooting ### Common Issues @@ -494,23 +366,13 @@ Organization Setup: npm ping --registry https://your-registry.com ``` -### Support and Maintenance - -1. **Internal Documentation**: Maintain organization-specific documentation -2. **Support Channels**: Set up internal support channels for StackCode issues -3. **Regular Updates**: Schedule regular updates from the upstream repository - ## 📋 Deployment Checklist - [ ] Repository forked and customized - [ ] Custom templates created and tested -- [ ] Configuration files distributed to teams -- [ ] Private registry configured (if applicable) -- [ ] Security review completed -- [ ] Team training conducted -- [ ] Monitoring and logging set up -- [ ] Update process documented -- [ ] Support process established +- [ ] Build process completed successfully +- [ ] Tests passing +- [ ] Documentation updated for customizations ## 🤝 Contributing Back diff --git a/packages/cli/dist/commands/config.js b/packages/cli/dist/commands/config.js index 9a7b7c2..f5f13d5 100644 --- a/packages/cli/dist/commands/config.js +++ b/packages/cli/dist/commands/config.js @@ -1,6 +1,7 @@ import Configstore from "configstore"; import fs from "fs/promises"; import path from "path"; +import { loadStackCodeConfig, saveStackCodeConfig, } from "@stackcode/core"; import { t } from "@stackcode/i18n"; import * as ui from "./ui.js"; const globalConfig = new Configstore("@stackcode/cli"); @@ -48,23 +49,26 @@ export async function runInteractiveMode() { ui.log.error(t("config.error.not_in_project")); return; } - const localConfigPath = path.join(projectRoot, ".stackcoderc.json"); try { - await fs.access(localConfigPath); + const localConfig = await loadStackCodeConfig(projectRoot); + const enable = await ui.promptToEnableValidation(); + const updatedConfig = { + ...localConfig, + features: { + ...localConfig.features, + commitValidation: enable, + }, + }; + await saveStackCodeConfig(projectRoot, updatedConfig); + const status = enable + ? t("config.status.enabled") + : t("config.status.disabled"); + ui.log.success(t("config.success.set_validation", { status })); } catch { ui.log.error(t("config.error.no_stackcoderc")); return; } - const enable = await ui.promptToEnableValidation(); - const localConfigContent = await fs.readFile(localConfigPath, "utf-8"); - const localConfig = JSON.parse(localConfigContent); - localConfig.features.commitValidation = enable; - await fs.writeFile(localConfigPath, JSON.stringify(localConfig, null, 2)); - const status = enable - ? t("config.status.enabled") - : t("config.status.disabled"); - ui.log.success(t("config.success.set_validation", { status })); } } export const getConfigCommand = () => ({ diff --git a/packages/cli/dist/commands/init.js b/packages/cli/dist/commands/init.js index bb795b7..6a55be0 100644 --- a/packages/cli/dist/commands/init.js +++ b/packages/cli/dist/commands/init.js @@ -1,8 +1,13 @@ import fs from "fs/promises"; import path from "path"; -import { scaffoldProject, setupHusky, generateReadmeContent, generateGitignoreContent, runCommand, validateStackDependencies, } from "@stackcode/core"; +import { scaffoldProject, setupHusky, generateReadmeContent, generateGitignoreContent, runCommand, validateStackDependencies, saveStackCodeConfig, } from "@stackcode/core"; import { t } from "@stackcode/i18n"; import * as ui from "./ui.js"; +/** + * Creates and returns the init command configuration for yargs. + * This command initializes a new project with the selected stack and configurations. + * @returns The yargs command module for the init command. + */ export const getInitCommand = () => ({ command: "init", describe: t("init.command_description"), @@ -21,7 +26,7 @@ export const getInitCommand = () => ({ } } catch { - // Intentionally ignored + // Directory doesn't exist - proceed with creation } ui.log.divider(); ui.log.success(t("init.setup_start")); @@ -41,10 +46,11 @@ export const getInitCommand = () => ({ if (answers.features.includes("husky") && answers.commitValidation !== undefined) { const config = { - stack: answers.stack, + defaultAuthor: answers.authorName, + defaultLicense: "MIT", // Default license, could be prompted in future features: { commitValidation: answers.commitValidation }, }; - await fs.writeFile(path.join(projectPath, ".stackcoderc.json"), JSON.stringify(config, null, 2)); + await saveStackCodeConfig(projectPath, config); } ui.log.info(` ${t("init.step.readme")}`); const readmeContent = await generateReadmeContent(); @@ -58,22 +64,20 @@ export const getInitCommand = () => ({ } ui.log.info(` ${t("init.step.git")}`); await runCommand("git", ["init"], { cwd: projectPath }); - // Validate dependencies before attempting to install them ui.log.info(` ${t("init.step.validate_deps")}`); const dependencyValidation = await validateStackDependencies(answers.stack); if (!dependencyValidation.isValid) { ui.log.warning(t("init.dependencies.missing", { stack: answers.stack })); - dependencyValidation.missingDependencies.forEach(dep => { + dependencyValidation.missingDependencies.forEach((dep) => { ui.log.raw(t("init.dependencies.missing_detail", { command: dep })); }); ui.log.raw("\n" + t("init.dependencies.install_instructions")); - dependencyValidation.missingDependencies.forEach(dep => { + dependencyValidation.missingDependencies.forEach((dep) => { const installKey = `init.dependencies.install_${dep}`; try { ui.log.raw(t(installKey)); } catch { - // If no specific install instruction exists, show generic message ui.log.raw(` - ${dep}: Check the official documentation for installation instructions`); } }); @@ -107,7 +111,7 @@ export const getInitCommand = () => ({ } catch (error) { ui.log.error(`\n${t("init.error.deps_install_failed", { - error: error instanceof Error ? error.message : String(error) + error: error instanceof Error ? error.message : String(error), })}`); ui.log.warning(t("init.error.deps_install_manual")); ui.log.info(t("init.error.suggested_command")); diff --git a/packages/cli/src/commands/config.ts b/packages/cli/src/commands/config.ts index 7689a3d..dfce25c 100644 --- a/packages/cli/src/commands/config.ts +++ b/packages/cli/src/commands/config.ts @@ -2,6 +2,11 @@ import type { CommandModule, Argv, Arguments } from "yargs"; import Configstore from "configstore"; import fs from "fs/promises"; import path from "path"; +import { + loadStackCodeConfig, + saveStackCodeConfig, + type StackCodeConfig, +} from "@stackcode/core"; import { t } from "@stackcode/i18n"; import * as ui from "./ui.js"; @@ -59,26 +64,28 @@ export async function runInteractiveMode() { return; } - const localConfigPath = path.join(projectRoot, ".stackcoderc.json"); - try { - await fs.access(localConfigPath); + const localConfig = await loadStackCodeConfig(projectRoot); + const enable = await ui.promptToEnableValidation(); + + const updatedConfig: StackCodeConfig = { + ...localConfig, + features: { + ...localConfig.features, + commitValidation: enable, + }, + }; + + await saveStackCodeConfig(projectRoot, updatedConfig); + + const status = enable + ? t("config.status.enabled") + : t("config.status.disabled"); + ui.log.success(t("config.success.set_validation", { status })); } catch { ui.log.error(t("config.error.no_stackcoderc")); return; } - - const enable = await ui.promptToEnableValidation(); - - const localConfigContent = await fs.readFile(localConfigPath, "utf-8"); - const localConfig = JSON.parse(localConfigContent); - localConfig.features.commitValidation = enable; - await fs.writeFile(localConfigPath, JSON.stringify(localConfig, null, 2)); - - const status = enable - ? t("config.status.enabled") - : t("config.status.disabled"); - ui.log.success(t("config.success.set_validation", { status })); } } diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 2e0bf0f..86e1f23 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -8,7 +8,9 @@ import { generateGitignoreContent, runCommand, validateStackDependencies, + saveStackCodeConfig, type ProjectOptions, + type StackCodeConfig, } from "@stackcode/core"; import { t } from "@stackcode/i18n"; import * as ui from "./ui.js"; @@ -63,14 +65,12 @@ export const getInitCommand = (): CommandModule => ({ answers.features.includes("husky") && answers.commitValidation !== undefined ) { - const config = { - stack: answers.stack, + const config: StackCodeConfig = { + defaultAuthor: answers.authorName, + defaultLicense: "MIT", // Default license, could be prompted in future features: { commitValidation: answers.commitValidation }, }; - await fs.writeFile( - path.join(projectPath, ".stackcoderc.json"), - JSON.stringify(config, null, 2), - ); + await saveStackCodeConfig(projectPath, config); } ui.log.info(` ${t("init.step.readme")}`); diff --git a/packages/cli/test/commands/init.test.ts b/packages/cli/test/commands/init.test.ts index 3f33356..70fe535 100644 --- a/packages/cli/test/commands/init.test.ts +++ b/packages/cli/test/commands/init.test.ts @@ -8,6 +8,7 @@ import { generateGitignoreContent, runCommand, validateStackDependencies, + saveStackCodeConfig, } from "@stackcode/core"; import { getInitCommand } from "../../src/commands/init"; @@ -18,6 +19,7 @@ vi.mock("@stackcode/core", () => ({ generateGitignoreContent: vi.fn(), runCommand: vi.fn(), validateStackDependencies: vi.fn(), + saveStackCodeConfig: vi.fn(), })); vi.mock("inquirer"); @@ -33,6 +35,7 @@ const mockedCore = { generateGitignoreContent: vi.mocked(generateGitignoreContent), runCommand: vi.mocked(runCommand), validateStackDependencies: vi.mocked(validateStackDependencies), + saveStackCodeConfig: vi.mocked(saveStackCodeConfig), }; describe("Init Command", () => { @@ -78,17 +81,21 @@ describe("Init Command", () => { }, }); - expect(mockedFs.writeFile).toHaveBeenCalledWith( - expect.stringContaining(".stackcoderc.json"), - expect.stringContaining('"commitValidation": true'), + expect(mockedCore.saveStackCodeConfig).toHaveBeenCalledWith( + projectPath, + expect.objectContaining({ + defaultAuthor: mockAnswers.authorName, + defaultLicense: "MIT", + features: { commitValidation: true }, + }), ); expect(mockedFs.writeFile).toHaveBeenCalledWith( - projectPath, + expect.stringContaining("README.md"), "# Test Project", ); expect(mockedFs.writeFile).toHaveBeenCalledWith( - projectPath, + expect.stringContaining(".gitignore"), "node_modules", ); diff --git a/packages/core/dist/index.d.ts b/packages/core/dist/index.d.ts index 8ccb278..5726549 100644 --- a/packages/core/dist/index.d.ts +++ b/packages/core/dist/index.d.ts @@ -2,9 +2,9 @@ * @fileoverview Main entry point for the @stackcode/core package. * It exports all the public-facing functions and types. */ -export { runCommand, getCommandOutput, getErrorMessage, isCommandAvailable, getStackDependencies, validateStackDependencies } from "./utils.js"; +export { runCommand, getCommandOutput, getErrorMessage, isCommandAvailable, getStackDependencies, validateStackDependencies, loadStackCodeConfig, saveStackCodeConfig, } from "./utils.js"; export { generateGitignoreContent, generateReadmeContent, } from "./generators.js"; -export { scaffoldProject, setupHusky, type ProjectOptions, } from "./scaffold.js"; +export { scaffoldProject, setupHusky, } from "./scaffold.js"; export { validateCommitMessage } from "./validator.js"; export * from "./github.js"; export * from "./types.js"; diff --git a/packages/core/dist/index.js b/packages/core/dist/index.js index 232f512..38476f7 100644 --- a/packages/core/dist/index.js +++ b/packages/core/dist/index.js @@ -2,7 +2,7 @@ * @fileoverview Main entry point for the @stackcode/core package. * It exports all the public-facing functions and types. */ -export { runCommand, getCommandOutput, getErrorMessage, isCommandAvailable, getStackDependencies, validateStackDependencies } from "./utils.js"; +export { runCommand, getCommandOutput, getErrorMessage, isCommandAvailable, getStackDependencies, validateStackDependencies, loadStackCodeConfig, saveStackCodeConfig, } from "./utils.js"; export { generateGitignoreContent, generateReadmeContent, } from "./generators.js"; export { scaffoldProject, setupHusky, } from "./scaffold.js"; export { validateCommitMessage } from "./validator.js"; diff --git a/packages/core/dist/scaffold.d.ts b/packages/core/dist/scaffold.d.ts index 8d2eec2..b6a960a 100644 --- a/packages/core/dist/scaffold.d.ts +++ b/packages/core/dist/scaffold.d.ts @@ -1,8 +1,3 @@ -export interface ProjectOptions { - projectPath: string; - stack: "node-js" | "node-ts" | "react" | "vue" | "python" | "java" | "go" | "php"; - features: ("docker" | "husky")[]; - replacements: Record; -} +import { ProjectOptions } from "./types.js"; export declare function scaffoldProject(options: ProjectOptions): Promise; export declare function setupHusky(projectPath: string): Promise; diff --git a/packages/core/dist/types.d.ts b/packages/core/dist/types.d.ts index 99c94c4..e7f958a 100644 --- a/packages/core/dist/types.d.ts +++ b/packages/core/dist/types.d.ts @@ -22,3 +22,24 @@ export interface GitHubReleaseOptions { releaseNotes: string; token: string; } +export interface StackCodeConfig { + defaultAuthor?: string; + defaultLicense?: string; + defaultDescription?: string; + features?: { + commitValidation?: boolean; + husky?: boolean; + docker?: boolean; + }; +} +export interface ProjectOptions { + projectPath: string; + stack: SupportedStack; + features: ("docker" | "husky")[]; + replacements: { + projectName: string; + description: string; + authorName: string; + }; +} +export type SupportedStack = "node-js" | "node-ts" | "react" | "vue" | "angular" | "svelte" | "python" | "java" | "go" | "php"; diff --git a/packages/core/dist/utils.d.ts b/packages/core/dist/utils.d.ts index 55186ad..6fdd8a6 100644 --- a/packages/core/dist/utils.d.ts +++ b/packages/core/dist/utils.d.ts @@ -1,3 +1,4 @@ +import { StackCodeConfig } from "./types.js"; interface RunCommandOptions { cwd: string; } @@ -41,5 +42,22 @@ export declare function validateStackDependencies(stack: string): Promise<{ missingDependencies: string[]; availableDependencies: string[]; }>; +/** + * Extracts a readable error message from various error types. + * @param error - The error object to extract message from. + * @returns A human-readable error message string. + */ export declare function getErrorMessage(error: unknown): string; +/** + * Loads StackCode configuration from .stackcoderc.json file. + * @param projectPath - The project path to look for configuration. + * @returns A promise that resolves to the configuration object. + */ +export declare function loadStackCodeConfig(projectPath: string): Promise; +/** + * Saves StackCode configuration to .stackcoderc.json file. + * @param projectPath - The project path to save configuration. + * @param config - The configuration object to save. + */ +export declare function saveStackCodeConfig(projectPath: string, config: StackCodeConfig): Promise; export {}; diff --git a/packages/core/dist/utils.js b/packages/core/dist/utils.js index d899525..fab5c34 100644 --- a/packages/core/dist/utils.js +++ b/packages/core/dist/utils.js @@ -3,6 +3,8 @@ * @module core/utils */ import { spawn } from "child_process"; +import fs from "fs/promises"; +import path from "path"; /** * Executes a shell command and streams its output. * Ideal for long-running processes like 'npm install' where the user needs to see the output live. @@ -92,7 +94,6 @@ export function getStackDependencies(stack) { php: ["composer", "php"], java: ["mvn", "java"], python: ["pip", "python"], - // Node.js stacks use npm which should be available if Node.js is installed "node-js": ["npm"], "node-ts": ["npm"], react: ["npm"], @@ -114,17 +115,22 @@ export async function validateStackDependencies(stack) { available: await isCommandAvailable(dep), }))); const missingDependencies = results - .filter(result => !result.available) - .map(result => result.command); + .filter((result) => !result.available) + .map((result) => result.command); const availableDependencies = results - .filter(result => result.available) - .map(result => result.command); + .filter((result) => result.available) + .map((result) => result.command); return { isValid: missingDependencies.length === 0, missingDependencies, availableDependencies, }; } +/** + * Extracts a readable error message from various error types. + * @param error - The error object to extract message from. + * @returns A human-readable error message string. + */ export function getErrorMessage(error) { if (typeof error === "object" && error !== null && @@ -137,4 +143,35 @@ export function getErrorMessage(error) { } return String(error); } +/** + * Loads StackCode configuration from .stackcoderc.json file. + * @param projectPath - The project path to look for configuration. + * @returns A promise that resolves to the configuration object. + */ +export async function loadStackCodeConfig(projectPath) { + const configPath = path.join(projectPath, ".stackcoderc.json"); + try { + const configContent = await fs.readFile(configPath, "utf8"); + return JSON.parse(configContent); + } + catch { + // Return default configuration if file doesn't exist or is invalid + return { + features: { + commitValidation: false, + husky: false, + docker: false, + }, + }; + } +} +/** + * Saves StackCode configuration to .stackcoderc.json file. + * @param projectPath - The project path to save configuration. + * @param config - The configuration object to save. + */ +export async function saveStackCodeConfig(projectPath, config) { + const configPath = path.join(projectPath, ".stackcoderc.json"); + await fs.writeFile(configPath, JSON.stringify(config, null, 2)); +} //# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json b/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json index 5a2f515..4da5880 100644 --- a/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +++ b/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json @@ -1 +1 @@ -{"version":"3.2.4","results":[[":test/release.test.ts",{"duration":5.826772000000005,"failed":false}],[":test/github.test.ts",{"duration":5.507145000000037,"failed":false}],[":test/validator.test.ts",{"duration":3.6768339999999853,"failed":false}]]} \ No newline at end of file +{"version":"3.2.4","results":[[":test/release.test.ts",{"duration":6.112851999999975,"failed":false}],[":test/github.test.ts",{"duration":5.35608400000001,"failed":false}],[":test/validator.test.ts",{"duration":7.7960860000000025,"failed":false}]]} \ No newline at end of file diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 41d6dfc..199adab 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -10,16 +10,14 @@ export { isCommandAvailable, getStackDependencies, validateStackDependencies, + loadStackCodeConfig, + saveStackCodeConfig, } from "./utils.js"; export { generateGitignoreContent, generateReadmeContent, } from "./generators.js"; -export { - scaffoldProject, - setupHusky, - type ProjectOptions, -} from "./scaffold.js"; +export { scaffoldProject, setupHusky } from "./scaffold.js"; export { validateCommitMessage } from "./validator.js"; export * from "./github.js"; diff --git a/packages/core/src/scaffold.ts b/packages/core/src/scaffold.ts index b8b74a5..d5cb481 100644 --- a/packages/core/src/scaffold.ts +++ b/packages/core/src/scaffold.ts @@ -1,6 +1,7 @@ import fs from "fs/promises"; import path from "path"; import { fileURLToPath } from "url"; +import { ProjectOptions } from "./types.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -37,21 +38,6 @@ async function copyTemplateFiles( } } -export interface ProjectOptions { - projectPath: string; - stack: - | "node-js" - | "node-ts" - | "react" - | "vue" - | "python" - | "java" - | "go" - | "php"; - features: ("docker" | "husky")[]; - replacements: Record; -} - export async function scaffoldProject(options: ProjectOptions): Promise { const { projectPath, stack, features, replacements } = options; await fs.mkdir(projectPath, { recursive: true }); diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index bf06965..7ec3ef6 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -26,3 +26,37 @@ export interface GitHubReleaseOptions { releaseNotes: string; token: string; } + +export interface StackCodeConfig { + defaultAuthor?: string; + defaultLicense?: string; + defaultDescription?: string; + features?: { + commitValidation?: boolean; + husky?: boolean; + docker?: boolean; + }; +} + +export interface ProjectOptions { + projectPath: string; + stack: SupportedStack; + features: ("docker" | "husky")[]; + replacements: { + projectName: string; + description: string; + authorName: string; + }; +} + +export type SupportedStack = + | "node-js" + | "node-ts" + | "react" + | "vue" + | "angular" + | "svelte" + | "python" + | "java" + | "go" + | "php"; diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index 63842fd..e1299a5 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -3,6 +3,9 @@ * @module core/utils */ import { spawn } from "child_process"; +import fs from "fs/promises"; +import path from "path"; +import { StackCodeConfig } from "./types.js"; interface RunCommandOptions { cwd: string; @@ -177,3 +180,40 @@ export function getErrorMessage(error: unknown): string { return String(error); } + +/** + * Loads StackCode configuration from .stackcoderc.json file. + * @param projectPath - The project path to look for configuration. + * @returns A promise that resolves to the configuration object. + */ +export async function loadStackCodeConfig( + projectPath: string, +): Promise { + const configPath = path.join(projectPath, ".stackcoderc.json"); + + try { + const configContent = await fs.readFile(configPath, "utf8"); + return JSON.parse(configContent) as StackCodeConfig; + } catch { + return { + features: { + commitValidation: false, + husky: false, + docker: false, + }, + }; + } +} + +/** + * Saves StackCode configuration to .stackcoderc.json file. + * @param projectPath - The project path to save configuration. + * @param config - The configuration object to save. + */ +export async function saveStackCodeConfig( + projectPath: string, + config: StackCodeConfig, +): Promise { + const configPath = path.join(projectPath, ".stackcoderc.json"); + await fs.writeFile(configPath, JSON.stringify(config, null, 2)); +}