create-yeow 0.1.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/bin/index.js ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ import { mkdirSync, writeFileSync, readFileSync, existsSync, cpSync } from 'fs';
3
+ import { resolve, dirname } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const argv = process.argv.slice(2);
8
+ const _flag = (f) => argv.includes(f);
9
+ const _val = (f) => argv.find(a => a.startsWith(f))?.split('=').slice(1).join('=');
10
+
11
+ const yes = _flag('-y') || process.env.CI === 'true';
12
+ const useTs = _flag('--ts');
13
+ const name = yes ? (_val('--name=') || 'my-yeow-plugin') : (argv[0] || 'my-yeow-plugin');
14
+ const author = yes ? (_val('--author=') || '') : '';
15
+
16
+ const c = { r:'\x1b[0m',b:'\x1b[1m',d:'\x1b[2m',g:'\x1b[32m',y:'\x1b[33m',B:'\x1b[34m',C:'\x1b[36m' };
17
+ const _ = (m) => process.stdout.write(m);
18
+ const ok = (m) => _(` ${c.g}✓${c.r} ${m}\n`);
19
+ const step = (m) => _(` ${c.C}→${c.r} ${m}... `);
20
+
21
+ const tpl = resolve(__dirname, '..', 'templates', 'default');
22
+ const dir = resolve(process.cwd(), name);
23
+
24
+ _(`\n ${c.b}${c.B}Yeow v0${c.r} ${c.d}— plugin scaffolding${c.r}\n\n`);
25
+ if (yes) _(` ${c.d}non-interactive mode${c.r}\n`);
26
+ _(` project ${c.b}${name}${c.r}\n`);
27
+ if (author) _(` author ${author}\n`);
28
+ _(` language ${useTs ? 'TypeScript' : 'JavaScript'}\n\n`);
29
+
30
+ if (existsSync(dir)) { console.error(` ${c.y}⚠ ${name} already exists${c.r}\n`); process.exit(1); }
31
+
32
+ step('Creating project'); mkdirSync(dir, { recursive: true }); ok('done');
33
+
34
+ step('Copying template'); cpSync(tpl, dir, { recursive: true }); ok('done');
35
+
36
+ // Write .gitignore
37
+ const gitignore = `node_modules/\ndist/\n.yeow/dev/\n*.log\n`;
38
+ writeFileSync(resolve(dir, '.gitignore'), gitignore);
39
+
40
+ // Update package.json
41
+ const pkg = JSON.parse(readFileSync(resolve(dir, 'package.json'), 'utf-8'));
42
+ pkg.name = name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
43
+ if (author) pkg.author = author;
44
+ writeFileSync(resolve(dir, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
45
+
46
+ // Update yeow.config.json
47
+ const cfg = JSON.parse(readFileSync(resolve(dir, 'yeow.config.json'), 'utf-8'));
48
+ cfg.name = name; if (author) cfg.author = author;
49
+ writeFileSync(resolve(dir, 'yeow.config.json'), JSON.stringify(cfg, null, 4) + '\n');
50
+
51
+ // If JS, rename index.ts → index.js and update build.js
52
+ if (!useTs) {
53
+ const tsFile = resolve(dir, 'src', 'index.ts');
54
+ const jsFile = resolve(dir, 'src', 'index.js');
55
+ if (existsSync(tsFile) && !existsSync(jsFile)) {
56
+ copy(tsFile, jsFile);
57
+ writeFileSync(jsFile, readFileSync(tsFile, 'utf-8').replace(/(:\s*\w+(\[\])?)\s*(?=,|\)|\n|;)/g, ''));
58
+ }
59
+ // Update build.js to use .js entry
60
+ const buildJs = readFileSync(resolve(dir, '.yeow', 'build.js'), 'utf-8')
61
+ .replace("src/index.ts", "src/index.js");
62
+ writeFileSync(resolve(dir, '.yeow', 'build.js'), buildJs);
63
+ }
64
+
65
+ _(`\n ${c.g}✓${c.r} ${c.b}Done!${c.r}\n\n`);
66
+ _(` cd ${name}\n`);
67
+ _(` npm install\n`);
68
+ _(` npm run dev${c.d} # start dev server${c.r}\n`);
69
+ _(_` npm run build${c.d} # build plugin JAR${c.r}\n\n`);
70
+
71
+ function copy(src, dest) { writeFileSync(dest, readFileSync(src)); }
package/package.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "create-yeow",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold a Yeow plugin project",
5
+ "type": "module",
6
+ "bin": { "create-yeow": "./bin/index.js" },
7
+ "files": ["bin/", "templates/"],
8
+ "license": "MIT"
9
+ }
@@ -0,0 +1,39 @@
1
+ import * as esbuild from 'esbuild';
2
+ import { readFileSync, mkdirSync, existsSync, statSync } from 'fs';
3
+ import { resolve } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import AdmZip from 'adm-zip';
6
+
7
+ const root = resolve(fileURLToPath(import.meta.url), '..', '..');
8
+ const cfg = JSON.parse(readFileSync(resolve(root, 'yeow.config.json'), 'utf-8'));
9
+ const { name, version } = cfg;
10
+ const entry = existsSync(resolve(root, 'src', 'index.ts')) ? 'src/index.ts' : 'src/index.js';
11
+
12
+ async function build() {
13
+ console.log(`\n Building ${name} v${version}...\n`);
14
+
15
+ const outDir = resolve(root, 'dist', '.yeow');
16
+ mkdirSync(outDir, { recursive: true });
17
+
18
+ await esbuild.build({
19
+ entryPoints: [resolve(root, entry)],
20
+ outfile: resolve(outDir, 'main.js'),
21
+ bundle: true, format: 'iife', target: 'es2023', platform: 'neutral', treeShaking: true, minify: true,
22
+ });
23
+
24
+ const size = statSync(resolve(outDir, 'main.js')).size;
25
+ console.log(` ✓ Bundled (${(size/1024).toFixed(1)} KB)`);
26
+
27
+ const tmplJar = resolve(root, '.yeow', 'assets', 'yeow-template-0.1.0.jar');
28
+ if (!existsSync(tmplJar)) { console.error(' ✗ Template JAR not found'); process.exit(1); }
29
+
30
+ const zip = new AdmZip(tmplJar);
31
+ zip.updateFile('plugin.yml', Buffer.from(`name: ${name}\nversion: ${version}\nmain: yeow.template.Bootstrap\napi-version: '1.21'\ndepend:\n - Yeow-Runtime\n`));
32
+ zip.addFile('.yeow/main.js', readFileSync(resolve(outDir, 'main.js')));
33
+
34
+ const outJar = resolve(root, 'dist', `${name}-${version}.jar`);
35
+ zip.writeZip(outJar);
36
+ console.log(` ✓ Packaged ${outJar}\n`);
37
+ }
38
+
39
+ build().catch(e => { console.error(e); process.exit(1); });
@@ -0,0 +1,122 @@
1
+ import { existsSync, mkdirSync, copyFileSync, writeFileSync, readFileSync, createWriteStream, statSync } from 'fs';
2
+ import { resolve, dirname, join, basename } from 'path';
3
+ import { spawn, execSync } from 'child_process';
4
+ import { fileURLToPath } from 'url';
5
+ import https from 'https';
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const ROOT = resolve(__dirname, '..');
9
+ const DEVDIR = resolve(ROOT, '.yeow', 'dev');
10
+ const CACHE = resolve(DEVDIR, 'cache');
11
+ const SERVER = resolve(DEVDIR, 'server');
12
+ const PAPER = '1.21.4';
13
+ const BUILD = '232';
14
+ const JAR = `paper-${PAPER}-${BUILD}.jar`;
15
+ const URL = `https://api.papermc.io/v2/projects/paper/versions/${PAPER}/builds/${BUILD}/downloads/${JAR}`;
16
+ const CACHEJAR = resolve(CACHE, JAR);
17
+
18
+ const YES = process.argv.includes('-y') || process.env.CI === 'true';
19
+ const PROXY = process.argv.find(a => a.startsWith('--proxy='))?.split('=').slice(1).join('=');
20
+ const STOP = (() => { const a = process.argv.find(a => a.startsWith('--stop=')); if (!a) return null; const m = a.split('=')[1].match(/^(\d+)(s|m|h)?$/); return m ? parseInt(m[1]) * (m[2]==='m'?60:m[2]==='h'?3600:1) : null; })();
21
+
22
+ const cfg = JSON.parse(readFileSync(resolve(ROOT, 'yeow.config.json'), 'utf-8'));
23
+ const RUNTIME = resolve(ROOT, '.yeow', 'assets', 'yeow-runtime-0.1.0.jar');
24
+
25
+ const c = { r:'\x1b[0m',b:'\x1b[1m',d:'\x1b[2m',g:'\x1b[32m',y:'\x1b[33m',B:'\x1b[34m',C:'\x1b[36m',R:'\x1b[31m', ok: '\x1b[32m✓\x1b[0m', fail: '\x1b[31m✗\x1b[0m', info: '\x1b[36mⓘ\x1b[0m', warn: '\x1b[33m⚠\x1b[0m' };
26
+ const log = (msg, color = '') => console.log(`${c.d}[${new Date().toLocaleTimeString()}]${c.r} ${color}${msg}${c.r}`);
27
+ const ok = msg => log(`${c.ok} ${msg}`, c.g);
28
+ const fail = msg => log(`${c.fail} ${msg}`, c.R);
29
+ const info = msg => log(`${c.info} ${msg}`, c.C);
30
+ const warn = msg => log(`${c.warn} ${msg}`, c.y);
31
+
32
+ function download(url, dest, agent) {
33
+ return new Promise((resolve, reject) => {
34
+ const f = createWriteStream(dest);
35
+ const o = agent ? { agent } : {};
36
+ https.get(url, o, res => {
37
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { f.close(); download(res.headers.location, dest, agent).then(resolve).catch(reject); return; }
38
+ if (res.statusCode !== 200) { f.close(); reject(new Error(`HTTP ${res.statusCode}`)); return; }
39
+ const total = parseInt(res.headers['content-length'], 10);
40
+ let dl = 0;
41
+ res.on('data', c => { dl += c.length; if (total) process.stdout.write(`\r ${c.B}Downloading...${c.r} ${(dl/1024/1024).toFixed(1)}MB / ${(total/1024/1024).toFixed(1)}MB`); });
42
+ res.pipe(f);
43
+ f.on('finish', () => { f.close(); process.stdout.write('\n'); resolve(); });
44
+ }).on('error', e => { f.close(); reject(e); });
45
+ });
46
+ }
47
+
48
+ async function ensurePaper() {
49
+ if (existsSync(CACHEJAR) && statSync(CACHEJAR).size > 1_000_000) { ok('Paper found in cache'); return; }
50
+ mkdirSync(CACHE, { recursive: true });
51
+ let agent = null;
52
+ if (PROXY) { info(`Proxy: ${PROXY}`); try { const { HttpsProxyAgent } = await import('https-proxy-agent'); agent = new HttpsProxyAgent(PROXY); } catch {} }
53
+ info('Downloading Paper...');
54
+ try { await download(URL, CACHEJAR, agent); ok('Paper downloaded'); }
55
+ catch (e) { fail('Download failed: ' + e.message); console.log(' Manually: ' + CACHEJAR); process.exit(1); }
56
+ }
57
+
58
+ function buildPlugin() {
59
+ info('Building plugin...');
60
+ try { execSync('node .yeow/build.js', { cwd: ROOT, stdio: 'inherit' }); ok('Plugin built'); }
61
+ catch (e) { fail('Build failed: ' + e.message); process.exit(1); }
62
+ }
63
+
64
+ function copyToPlugins(src, label) {
65
+ const d = resolve(SERVER, 'plugins'); mkdirSync(d, { recursive: true });
66
+ copyFileSync(src, resolve(d, basename(src))); ok(`${label} copied`);
67
+ }
68
+
69
+ async function initServer() {
70
+ const jar = resolve(SERVER, JAR);
71
+ if (!existsSync(jar)) copyFileSync(CACHEJAR, jar);
72
+ const eula = resolve(SERVER, 'eula.txt');
73
+ if (existsSync(eula) && readFileSync(eula, 'utf-8').includes('eula=true')) return;
74
+
75
+ if (YES) {
76
+ if (!existsSync(resolve(SERVER, 'server.properties'))) {
77
+ info('Initializing...');
78
+ await new Promise(r => { const p = spawn('java', ['-Xmx4G','-Xms4G','-jar',jar,'--nogui'], { cwd: SERVER, stdio: ['pipe','inherit','inherit'] }); setTimeout(() => { p.kill(); r(); }, 120000); p.on('exit', r); p.on('error', r); });
79
+ }
80
+ writeFileSync(eula, 'eula=true\n'); ok('EULA auto-accepted');
81
+ } else {
82
+ console.log(` Press Enter to accept EULA...`);
83
+ await new Promise(r => process.stdin.once('data', () => { writeFileSync(eula, 'eula=true\n'); ok('EULA accepted'); r(); }));
84
+ }
85
+ }
86
+
87
+ function serverProps(port) {
88
+ const f = resolve(SERVER, 'server.properties');
89
+ const m = { 'server-port': String(port), 'online-mode': 'false', 'spawn-protection': '0', 'enable-command-block': 'true', 'max-players': '10', 'difficulty': 'easy', 'motd': cfg.name || 'Yeow Dev' };
90
+ if (existsSync(f)) {
91
+ for (const l of readFileSync(f, 'utf-8').split('\n')) { const eq = l.indexOf('='); if (eq > 0 && !l.startsWith('#')) { const k = l.substring(0, eq).trim(); if (!m[k]) m[k] = l.substring(eq + 1).trim(); } }
92
+ }
93
+ let out = ''; for (const [k, v] of Object.entries(m)) out += `${k}=${v}\n`;
94
+ writeFileSync(f, out);
95
+ }
96
+
97
+ let proc = null;
98
+ function startServer() {
99
+ info(`\nStarting Paper ${PAPER} server...`);
100
+ proc = spawn('java', ['-Xmx4G', '-Xms4G', '-jar', resolve(SERVER, JAR), '--nogui'], { cwd: SERVER, stdio: ['pipe', 'inherit', 'inherit'] });
101
+ proc.on('exit', code => { warn(`Server exited (${code})`); process.exit(0); });
102
+ process.stdin.on('data', d => { if (proc && !proc.killed) proc.stdin.write(d); });
103
+ if (STOP) { info(`Auto-stop in ${STOP}s`); setTimeout(() => { warn('Auto-stop'); if (proc && !proc.killed) proc.stdin.write('stop\n'); setTimeout(() => { if (proc && !proc.killed) proc.kill(); process.exit(0); }, 10000); }, STOP * 1000); }
104
+ }
105
+
106
+ async function main() {
107
+ console.log(`\n${c.b}${c.B} Yeow Dev Server${c.r}\n`);
108
+ if (!existsSync(RUNTIME)) { fail(`Runtime JAR not found: ${RUNTIME}`); process.exit(1); }
109
+
110
+ await ensurePaper();
111
+ mkdirSync(SERVER, { recursive: true });
112
+ await initServer();
113
+ serverProps(cfg.dev?.port || 17367);
114
+ buildPlugin();
115
+ copyToPlugins(resolve(ROOT, 'dist', `${cfg.name}-${cfg.version}.jar`), 'Plugin');
116
+ copyToPlugins(RUNTIME, 'Runtime');
117
+
118
+ startServer();
119
+ }
120
+
121
+ process.on('SIGINT', () => { if (proc) { proc.stdin.write('stop\n'); setTimeout(() => { if (proc && !proc.killed) proc.kill(); process.exit(0); }, 5000); } });
122
+ main().catch(e => { fail(e.message); process.exit(1); });
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "my-yeow-plugin",
3
+ "version": "1.0.0",
4
+ "scripts": {
5
+ "build": "node .yeow/build.js",
6
+ "dev": "node .yeow/dev-server.js"
7
+ },
8
+ "dependencies": {
9
+ "yeow-api": "^0.1.0"
10
+ },
11
+ "devDependencies": {
12
+ "esbuild": "^0.25.0",
13
+ "adm-zip": "^0.5.0",
14
+ "https-proxy-agent": "^9.0.0"
15
+ }
16
+ }
@@ -0,0 +1,32 @@
1
+ import { Player, World, registerCommand, eventOn, broadcastSync, fs, path } from 'yeow-api';
2
+
3
+ // ── Commands ────────────────────────
4
+ registerCommand('hello', {
5
+ description: 'Say hello',
6
+ executor: (p) => p.sender.sendMessage(`Hello, ${p.args[0] || 'World'}!`),
7
+ });
8
+
9
+ registerCommand('ping', {
10
+ description: 'Check your ping',
11
+ executor: (p) => {
12
+ const player = Player.get(p.sender.uuid);
13
+ if (player) p.sender.sendMessage(`Ping: ${player.ping}ms`);
14
+ },
15
+ });
16
+
17
+ // ── Events ──────────────────────────
18
+ eventOn('playerJoin', (e) => {
19
+ const player = Player.get(e.player);
20
+ if (player) player.sendMessageSync(`Welcome, ${player.displayName}!`);
21
+ });
22
+
23
+ eventOn('blockBreak', (e) => {
24
+ if (e.block === 'minecraft:bedrock') e.cancelled = true;
25
+ });
26
+
27
+ // ── Startup ─────────────────────────
28
+ const world = World.get('world');
29
+ if (world) {
30
+ console.log(`[init] World: ${world.name} | Time: ${world.time} | Difficulty: ${world.difficulty}`);
31
+ console.log(`[init] Plugin ready`);
32
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2023",
4
+ "module": "ES2022",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "noEmit": true
10
+ },
11
+ "include": ["src/**/*.ts"]
12
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "my-yeow-plugin",
3
+ "version": "1.0.0",
4
+ "author": "Unknown",
5
+ "description": "A Yeow plugin",
6
+ "dev": {
7
+ "port": 17367,
8
+ "memory": "4G"
9
+ }
10
+ }