juxscript 1.1.369 → 1.1.370

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.
Files changed (2) hide show
  1. package/bin/cli.js +129 -41
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -12,6 +12,135 @@ const PACKAGE_ROOT = path.resolve(__dirname, '..');
12
12
 
13
13
  const [, , command, ...args] = process.argv;
14
14
 
15
+ // ═══════════════════════════════════════════════════════════════
16
+ // UTILITIES (must be defined before commands that use them)
17
+ // ═══════════════════════════════════════════════════════════════
18
+ function copyDirRecursive(src, dest) {
19
+ if (!fs.existsSync(dest)) {
20
+ fs.mkdirSync(dest, { recursive: true });
21
+ }
22
+
23
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
24
+ if (entry.name.startsWith('.')) continue;
25
+
26
+ const srcPath = path.join(src, entry.name);
27
+ const destPath = path.join(dest, entry.name);
28
+
29
+ if (entry.isDirectory()) {
30
+ copyDirRecursive(srcPath, destPath);
31
+ } else {
32
+ fs.copyFileSync(srcPath, destPath);
33
+ }
34
+ }
35
+ }
36
+
37
+ function resolveProjectSrcDir() {
38
+ const projectRoot = process.cwd();
39
+ const configPath = path.join(projectRoot, 'juxconfig.js');
40
+
41
+ if (fs.existsSync(configPath)) {
42
+ try {
43
+ const configContent = fs.readFileSync(configPath, 'utf8');
44
+ const srcDirMatch = configContent.match(/srcDir\s*:\s*['"]([^'"]+)['"]/);
45
+ if (srcDirMatch) {
46
+ return path.resolve(projectRoot, srcDirMatch[1]);
47
+ }
48
+ } catch (_) { }
49
+ }
50
+
51
+ return path.resolve(projectRoot, 'jux');
52
+ }
53
+
54
+ function resolveDestFolderName(parentDir, baseName) {
55
+ const first = path.join(parentDir, baseName);
56
+ if (!fs.existsSync(first)) return baseName;
57
+
58
+ const juxName = baseName + '-jux';
59
+ const second = path.join(parentDir, juxName);
60
+ if (!fs.existsSync(second)) return juxName;
61
+
62
+ for (let i = 1; i <= 99; i++) {
63
+ const numbered = `${baseName}-${i}`;
64
+ if (!fs.existsSync(path.join(parentDir, numbered))) return numbered;
65
+ }
66
+
67
+ return `${baseName}-${Date.now()}`;
68
+ }
69
+
70
+ function listFilesRecursive(dir, base = '') {
71
+ const results = [];
72
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
73
+
74
+ for (const entry of entries) {
75
+ if (entry.name.startsWith('.')) continue;
76
+ const rel = base ? path.join(base, entry.name) : entry.name;
77
+
78
+ if (entry.isDirectory()) {
79
+ results.push(...listFilesRecursive(path.join(dir, entry.name), rel));
80
+ } else {
81
+ results.push(rel);
82
+ }
83
+ }
84
+
85
+ return results;
86
+ }
87
+
88
+ function promptPresetSelection(presets) {
89
+ return new Promise((resolve) => {
90
+ console.log('\n📦 Available component presets:\n');
91
+ presets.forEach((p, i) => {
92
+ const presetDir = path.join(PACKAGE_ROOT, 'presets', p);
93
+ const files = fs.readdirSync(presetDir).filter(f => !f.startsWith('.'));
94
+ console.log(` ${i + 1}) ${p} (${files.join(', ')})`);
95
+ });
96
+ console.log(` 0) Cancel\n`);
97
+
98
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
99
+ rl.question('Select a preset (number or name): ', (answer) => {
100
+ rl.close();
101
+ const trimmed = answer.trim();
102
+
103
+ const num = parseInt(trimmed, 10);
104
+ if (num === 0) return resolve(null);
105
+ if (num >= 1 && num <= presets.length) return resolve(presets[num - 1]);
106
+
107
+ if (presets.includes(trimmed)) return resolve(trimmed);
108
+
109
+ console.error(`❌ Invalid selection: "${trimmed}"`);
110
+ resolve(null);
111
+ });
112
+ });
113
+ }
114
+
115
+ function promptYesNo(question) {
116
+ return new Promise((resolve) => {
117
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
118
+ rl.question(`${question} (y/N): `, (answer) => {
119
+ rl.close();
120
+ resolve(answer.trim().toLowerCase() === 'y');
121
+ });
122
+ });
123
+ }
124
+
125
+ function showHelp() {
126
+ console.log(`
127
+ JUX CLI
128
+
129
+ Usage:
130
+ jux create <name> Create a new JUX project
131
+ jux init Initialize JUX in current directory
132
+ jux build Build for production
133
+ jux serve Start production server
134
+ jux serve --hot Start dev server with hot reload
135
+ jux comp [name] Add a component preset to your project
136
+ jux comp [name] -f Force overwrite (backs up existing files)
137
+
138
+ Options:
139
+ --help, -h Show this help message
140
+ --force, -f Overwrite existing files (creates .bak backups)
141
+ `);
142
+ }
143
+
15
144
  // ═══════════════════════════════════════════════════════════════
16
145
  // COMMAND: create <project-name>
17
146
  // Creates a new JUX project from the template
@@ -256,47 +385,6 @@ function runServe() {
256
385
  child.on('close', (code) => process.exit(code || 0));
257
386
  }
258
387
 
259
- // ═══════════════════════════════════════════════════════════════
260
- // UTILITIES
261
- // ═══════════════════════════════════════════════════════════════
262
- function copyDirRecursive(src, dest) {
263
- if (!fs.existsSync(dest)) {
264
- fs.mkdirSync(dest, { recursive: true });
265
- }
266
-
267
- for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
268
- if (entry.name.startsWith('.')) continue; // Skip hidden files
269
-
270
- const srcPath = path.join(src, entry.name);
271
- const destPath = path.join(dest, entry.name);
272
-
273
- if (entry.isDirectory()) {
274
- copyDirRecursive(srcPath, destPath);
275
- } else {
276
- fs.copyFileSync(srcPath, destPath);
277
- }
278
- }
279
- }
280
-
281
- function showHelp() {
282
- console.log(`
283
- JUX CLI
284
-
285
- Usage:
286
- jux create <name> Create a new JUX project
287
- jux init Initialize JUX in current directory
288
- jux build Build for production
289
- jux serve Start production server
290
- jux serve --hot Start dev server with hot reload
291
- jux comp [name] Add a component preset to your project
292
- jux comp [name] -f Force overwrite (backs up existing files)
293
-
294
- Options:
295
- --help, -h Show this help message
296
- --force, -f Overwrite existing files (creates .bak backups)
297
- `);
298
- }
299
-
300
388
  // ═══════════════════════════════════════════════════════════════
301
389
  // COMMAND: comp [name]
302
390
  // Copies a preset component into the project's jux directory
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.369",
3
+ "version": "1.1.370",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "./dist/lib/index.js",