Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,13 @@ my-org/
package.json
turbo.json / nx.json (if preset chosen)
scripts/
dev-basic.cjs
npx create-polyglot dev
```

### Presets
- **Turborepo**: Generates `turbo.json`, sets root `dev` & `build` scripts for pipeline caching.
- **Nx**: Generates `nx.json` and adjusts scripts accordingly.
- **Basic**: Minimal setup + `scripts/dev-basic.cjs` for simple concurrency.
- **Basic**: Minimal setup + `npx create-polyglot dev` for simple concurrency.

## Development Workflow
1. Scaffold with `init`.
Expand All @@ -228,7 +228,7 @@ my-org/
5. Extend infra / databases inside `compose.yaml`.

### Basic Dev Runner
When no preset is chosen, `npm run dev` uses `scripts/dev-basic.cjs`:
When no preset is chosen, `npm run dev` uses `npx create-polyglot dev`:
1. Detects package manager (pnpm > yarn > bun > npm fallback)
2. Scans `services/` for Node services
3. Runs those with a `dev` script
Expand Down Expand Up @@ -402,16 +402,16 @@ my-org/
package.json
turbo.json / nx.json (if preset chosen)
scripts/
dev-basic.cjs
npx create-polyglot dev
```

### Presets
- Turborepo: Generates `turbo.json`, sets root `dev` & `build` scripts to leverage Turborepo pipelines.
- Nx: Generates `nx.json` and adjusts scripts accordingly.
- Basic: Provides a minimal setup plus `scripts/dev-basic.cjs` for simple concurrency.
- Basic: Provides a minimal setup plus `npx create-polyglot dev` for simple concurrency.

### Basic Dev Runner
When no preset is chosen, `npm run dev` uses `scripts/dev-basic.cjs`:
When no preset is chosen, `npm run dev` uses `npx create-polyglot dev`:
1. Detects package manager (pnpm > yarn > bun > npm fallback)
2. Scans `services/` for Node services
3. Runs those with a `dev` script
Expand Down
32 changes: 11 additions & 21 deletions bin/lib/scaffold.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ export async function scaffoldMonorepo(projectNameArg, options) {
interactiveQuestions.push({
type: 'select',
name: 'preset',
message: 'Preset (optional):',
message: 'Preset:',
choices: [
{ title: 'None', value: '' },
{ title: 'None (basic)', value: '' },
{ title: 'Turborepo', value: 'turborepo' },
{ title: 'Nx', value: 'nx' }
],
Expand Down Expand Up @@ -310,7 +310,7 @@ export async function scaffoldMonorepo(projectNameArg, options) {
], { cwd: dest, stdio: 'inherit' });
usedGenerator = true;
} catch (e) {
console.log(chalk.yellow('⚠️ create-next-app failed, falling back to internal template. Error:'), e.shortMessage || e.message);
console.log(chalk.yellow(`⚠️ create-next-app failed: ${e.message}. Using template.`));
}
}
if (!usedGenerator) {
Expand All @@ -327,10 +327,10 @@ export async function scaffoldMonorepo(projectNameArg, options) {
await fs.writeFile(path.join(dest, 'README.md'), `# ${svcName} service\n\nScaffolded by create-polyglot.`);
}
}

// Initialize logging for the service
initializeServiceLogs(dest);

console.log(chalk.green(`✅ Created ${svcName} (${svcType}) service on port ${svcPort}`));
}

Expand All @@ -341,7 +341,7 @@ export async function scaffoldMonorepo(projectNameArg, options) {
version: '0.1.0',
workspaces: ['services/*', 'packages/*'],
scripts: {
dev: 'node scripts/dev-basic.cjs',
dev: 'npx create-polyglot dev',
'list:services': 'node scripts/list-services.mjs',
format: 'prettier --write .',
lint: 'eslint "services/**/*.{js,jsx,ts,tsx}" --max-warnings 0 || true'
Expand All @@ -366,16 +366,6 @@ export async function scaffoldMonorepo(projectNameArg, options) {
// Always ensure scripts dir exists (needed for list-services script)
const scriptsDir = path.join(projectDir, 'scripts');
await fs.mkdirp(scriptsDir);
if (!options.preset) {
const runnerSrc = path.join(__dirname, '../../scripts/dev-basic.cjs');
try {
if (await fs.pathExists(runnerSrc)) {
await fs.copy(runnerSrc, path.join(scriptsDir, 'dev-basic.cjs'));
}
} catch (e) {
console.log(chalk.yellow('⚠️ Failed to copy dev-basic runner:', e.message));
}
}
// Create list-services script with runtime status detection
const listScriptPath = path.join(scriptsDir, 'list-services.mjs');
await fs.writeFile(listScriptPath, `#!/usr/bin/env node\nimport fs from 'fs';\nimport path from 'path';\nimport net from 'net';\nimport chalk from 'chalk';\nconst cwd = process.cwd();\nconst cfgPath = path.join(cwd, 'polyglot.json');\nif(!fs.existsSync(cfgPath)){ console.error(chalk.red('polyglot.json not found.')); process.exit(1);}\nconst cfg = JSON.parse(fs.readFileSync(cfgPath,'utf-8'));\n\nfunction strip(str){return str.replace(/\\x1B\\[[0-9;]*m/g,'');}\nfunction pad(str,w){const raw=strip(str);return str+' '.repeat(Math.max(0,w-raw.length));}\nfunction table(items){ if(!items.length){console.log(chalk.yellow('No services.'));return;} const cols=[{k:'name',h:'Name'},{k:'type',h:'Type'},{k:'port',h:'Port'},{k:'status',h:'Status'},{k:'path',h:'Path'}]; const widths=cols.map(c=>Math.max(c.h.length,...items.map(i=>strip(i[c.k]).length))+2); const top='┌'+widths.map(w=>'─'.repeat(w)).join('┬')+'┐'; const sep='├'+widths.map(w=>'─'.repeat(w)).join('┼')+'┤'; const bot='└'+widths.map(w=>'─'.repeat(w)).join('┴')+'┘'; console.log(top); console.log('│'+cols.map((c,i)=>pad(chalk.bold.white(c.h),widths[i])).join('│')+'│'); console.log(sep); for(const it of items){ console.log('│'+cols.map((c,i)=>pad(it[c.k],widths[i])).join('│')+'│'); } console.log(bot); console.log(chalk.gray('Total: '+items.length)); }\n\nasync function check(port){ return new Promise(res=>{ const sock=net.createConnection({port,host:'127.0.0.1'},()=>{sock.destroy();res(true);}); sock.setTimeout(350,()=>{sock.destroy();res(false);}); sock.on('error',()=>{res(false);});}); }\nconst promises = cfg.services.map(async s=>{ const up = await check(s.port); return { ...s, _up: up }; });\nconst results = await Promise.all(promises);\nconst rows = results.map(s=>({ name: chalk.cyan(s.name), type: colorType(s.type)(s.type), port: chalk.green(String(s.port)), status: s._up ? chalk.bgGreen.black(' UP ') : chalk.bgRed.white(' DOWN '), path: chalk.dim(s.path) }));\nfunction colorType(t){ switch(t){case 'node': return chalk.green; case 'python': return chalk.yellow; case 'go': return chalk.cyan; case 'java': return chalk.red; case 'frontend': return chalk.blue; default: return chalk.white;} }\nif(process.argv.includes('--json')) { console.log(JSON.stringify(results.map(r=>({name:r.name,type:r.type,port:r.port,up:r._up,path:r.path})),null,2)); } else { console.log(chalk.magentaBright('\nWorkspace Services (runtime status)')); table(rows); }\n`);
Expand Down Expand Up @@ -456,7 +446,7 @@ export async function scaffoldMonorepo(projectNameArg, options) {
await execa('git', ['commit', '-m', 'chore: initial scaffold'], { cwd: projectDir });
console.log(chalk.green('✅ Initialized git repository'));
} catch (e) {
console.log(chalk.yellow('⚠️ Git initialization failed (continuing).'));
console.log(chalk.yellow('⚠️ Failed to initialize git repository:', e.message));
}
}

Expand All @@ -468,7 +458,7 @@ export async function scaffoldMonorepo(projectNameArg, options) {
try {
await execa(pm, installCmd, { cwd: projectDir, stdio: 'inherit' });
} catch (e) {
console.log(chalk.yellow('⚠️ Installing dependencies failed, you can try manually.'));
console.log(chalk.yellow('⚠️ Failed to install dependencies:', e.message));
}
}

Expand All @@ -487,7 +477,7 @@ export async function scaffoldMonorepo(projectNameArg, options) {
console.log(chalk.green('✅ Added GitHub Actions workflow (.github/workflows/ci.yml)'));
}
} catch (e) {
console.log(chalk.yellow('⚠️ Failed to create GitHub Actions workflow:'), e.message);
console.log(chalk.yellow('⚠️ Failed to create GitHub Actions workflow:', e.message));
}
}

Expand Down Expand Up @@ -546,10 +536,10 @@ export async function addService(projectDir, { type, name, port }, options = {})
} else {
await fs.writeFile(path.join(dest, 'README.md'), `# ${name} (${type}) service\n`);
}

// Initialize logging for the service
initializeServiceLogs(dest);

console.log(chalk.green(`✅ Added service '${name}' (${type}) on port ${port}`));
cfg.services.push({ name, type, port, path: `services/${name}` });
await fs.writeJSON(configPath, cfg, { spaces: 2 });
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/presets.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ You can select a preset via `--preset turborepo` or `--preset nx`.

| Preset | Effect |
| ------ | ------ |
| (none) | Adds `scripts/dev-basic.cjs` and uses a simple concurrent runner |
| (none) | Adds `scripts/npx create-polyglot dev` and uses a simple concurrent runner |
| turborepo | Adds `turbo.json` and sets `dev` script to `turbo run dev --parallel` |
| nx | Adds `nx.json` and sets `dev` script to `nx run-many -t dev --all` |

Expand Down
235 changes: 0 additions & 235 deletions scripts/dev-basic.cjs

This file was deleted.

Binary file not shown.
3 changes: 3 additions & 0 deletions templates/spring-boot/target/maven-archiver/pom.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
artifactId=spring-boot-service
groupId=com.example
version=0.0.1-SNAPSHOT
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/Users/I528923/Desktop/create-polyglot/templates/spring-boot/src/main/java/com/example/DemoApplication.java
Binary file not shown.
Binary file not shown.
Loading