tweaks 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/cli.js ADDED
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ import { createServer } from 'http';
3
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
4
+ import { extname, join, dirname } from 'path';
5
+ import { exec } from 'child_process';
6
+
7
+ const args = process.argv.slice(2);
8
+ const noOpen = args.includes('--no-open');
9
+ const filteredArgs = args.filter(a => !a.startsWith('--'));
10
+ const firstArg = filteredArgs[0]; // First arg: if it's a number, it's the port. Otherwise it's the tweaks path.
11
+ const isPort = firstArg && /^\d+$/.test(firstArg);
12
+ const DEFAULT_PORT = 47471;
13
+ const PORT = isPort ? Number(firstArg) : DEFAULT_PORT;
14
+ const TWEAKS_PATH = isPort ? (filteredArgs[1] || './tweaks.js') : (firstArg || './tweaks.js');
15
+ const WEB_PATH = '/' + TWEAKS_PATH.replace(/^\.\//, '');
16
+ const DIR = dirname(TWEAKS_PATH);
17
+ const TWEAKS_TEMPLATE = `/** @type {{ __path__: string, data: Object }} */
18
+ export const tweaks = `;
19
+
20
+ if (!existsSync(TWEAKS_PATH)) {
21
+ writeFileSync(TWEAKS_PATH, `${TWEAKS_TEMPLATE}{\n __path__: '${WEB_PATH}',\n data: {},\n};\n`);
22
+ console.log(`Created ${TWEAKS_PATH}`);
23
+ }
24
+
25
+ /** @type {Record<string, string>} */
26
+ const MIME = { '.html': 'text/html', '.js': 'application/javascript', '.css': 'text/css', '.json': 'application/json' };
27
+
28
+ createServer((req, res) => {
29
+ res.setHeader('Access-Control-Allow-Origin', '*');
30
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
31
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
32
+ if (req.method === 'OPTIONS') return res.writeHead(204).end();
33
+ if (req.url === '/__tweaks__/ping') return res.writeHead(200).end('ok');
34
+ if (req.url === '/__tweaks__/save' && req.method === 'POST') {
35
+ let body = '';
36
+ req.on('data', c => body += c);
37
+ req.on('end', () => {
38
+ try {
39
+ const data = JSON.parse(body);
40
+ const filePath = '.' + data.__path__;
41
+ writeFileSync(filePath, `${TWEAKS_TEMPLATE}${JSON.stringify(data, null, 2)};\n`);
42
+ console.log(`Saved ${filePath}`);
43
+ res.writeHead(200).end('ok');
44
+ } catch (e) {
45
+ console.error('Save failed:', /** @type {Error} */(e).message);
46
+ res.writeHead(400).end('Invalid JSON');
47
+ }
48
+ });
49
+ return;
50
+ }
51
+ let path = req.url || '/';
52
+ if (path.endsWith('/')) path += 'index.html';
53
+ if (!extname(path)) path += '/index.html';
54
+ try {
55
+ const content = readFileSync(join('.', path));
56
+ res.writeHead(200, { 'Content-Type': MIME[extname(path)] || 'text/plain' }).end(content);
57
+ } catch {
58
+ res.writeHead(404).end('Not found');
59
+ }
60
+ }).on('error', (/** @type {NodeJS.ErrnoException} */ err) => {
61
+ if (err.code === 'EADDRINUSE') {
62
+ const url = `http://localhost:${PORT}/${DIR}/`;
63
+ // Check if it's already a tweaks server
64
+ fetch(`http://localhost:${PORT}/__tweaks__/ping`)
65
+ .then(res => {
66
+ if (res.ok) {
67
+ console.log(`Server already running at ${url}`);
68
+ if (!noOpen) {
69
+ const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
70
+ exec(`${cmd} ${url}`);
71
+ }
72
+ } else {
73
+ console.error(`Port ${PORT} is in use by another application`);
74
+ }
75
+ process.exit(0);
76
+ })
77
+ .catch(() => {
78
+ console.error(`Port ${PORT} is in use by another application`);
79
+ process.exit(1);
80
+ });
81
+ } else {
82
+ console.error('Server error:', err.message);
83
+ process.exit(1);
84
+ }
85
+ }).listen(PORT, () => {
86
+ const url = `http://localhost:${PORT}/${DIR}/`;
87
+ console.log(url);
88
+ if (!noOpen) {
89
+ const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
90
+ exec(`${cmd} ${url}`);
91
+ }
92
+ });