juxscript 1.0.0 ā 1.0.2
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/README.md +13 -1
- package/bin/cli.js +161 -34
- package/lib/components/docs-data.json +1 -1
- package/lib/templates/index.juxt +33 -0
- package/machinery/doc-generator.js +12 -36
- package/machinery/server.js +12 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,19 @@ Have you ever considered the energy requirements to ship chunks of HTML markup l
|
|
|
21
21
|
|
|
22
22
|
## GETTING STARTED
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
```bash
|
|
25
|
+
# New project
|
|
26
|
+
mkdir my-project
|
|
27
|
+
cd my-project
|
|
28
|
+
npm init -y
|
|
29
|
+
npm install juxscript
|
|
30
|
+
|
|
31
|
+
# Initialize (creates jux/ directory)
|
|
32
|
+
npx jux init
|
|
33
|
+
|
|
34
|
+
# Builds jux-dist and serves index.jux
|
|
35
|
+
npx jux serve
|
|
36
|
+
```
|
|
25
37
|
> install
|
|
26
38
|
`npm i juxscript`
|
|
27
39
|
|
package/bin/cli.js
CHANGED
|
@@ -10,11 +10,42 @@ import { fileURLToPath } from 'url';
|
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
11
|
const __dirname = path.dirname(__filename);
|
|
12
12
|
|
|
13
|
+
// CLEAR PATH CONTRACT - CONVENTIONS
|
|
14
|
+
const PATHS = {
|
|
15
|
+
// Where jux package is installed (in node_modules/juxscript or local dev)
|
|
16
|
+
packageRoot: path.resolve(__dirname, '..'),
|
|
17
|
+
|
|
18
|
+
// Where the user's project root is (where they run `npx jux`)
|
|
19
|
+
projectRoot: process.cwd(),
|
|
20
|
+
|
|
21
|
+
// Where user's .jux source files live (CONVENTION: ./jux/)
|
|
22
|
+
get juxSource() {
|
|
23
|
+
return path.join(this.projectRoot, 'jux');
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// Where jux lib files are (components, layouts, etc.)
|
|
27
|
+
get juxLib() {
|
|
28
|
+
return path.join(this.packageRoot, 'lib');
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// Where frontend build output goes (CONVENTION: ./jux-dist/)
|
|
32
|
+
get frontendDist() {
|
|
33
|
+
return path.join(this.projectRoot, 'jux-dist');
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
console.log('š JUX Paths:');
|
|
38
|
+
console.log(` Package: ${PATHS.packageRoot}`);
|
|
39
|
+
console.log(` Project: ${PATHS.projectRoot}`);
|
|
40
|
+
console.log(` Source: ${PATHS.juxSource}`);
|
|
41
|
+
console.log(` Output: ${PATHS.frontendDist}`);
|
|
42
|
+
console.log(` Lib: ${PATHS.juxLib}\n`);
|
|
43
|
+
|
|
13
44
|
const command = process.argv[2];
|
|
14
|
-
const projectRoot = process.cwd();
|
|
15
|
-
const distDir = path.join(projectRoot, 'dist');
|
|
16
45
|
|
|
17
46
|
function findJuxFiles(dir, fileList = []) {
|
|
47
|
+
if (!fs.existsSync(dir)) return fileList;
|
|
48
|
+
|
|
18
49
|
const files = fs.readdirSync(dir);
|
|
19
50
|
|
|
20
51
|
files.forEach(file => {
|
|
@@ -22,7 +53,7 @@ function findJuxFiles(dir, fileList = []) {
|
|
|
22
53
|
const stat = fs.statSync(filePath);
|
|
23
54
|
|
|
24
55
|
if (stat.isDirectory()) {
|
|
25
|
-
if (file !== 'node_modules' && file !== 'dist' && file !== '.git') {
|
|
56
|
+
if (file !== 'node_modules' && file !== 'jux-dist' && file !== '.git' && file !== 'server') {
|
|
26
57
|
findJuxFiles(filePath, fileList);
|
|
27
58
|
}
|
|
28
59
|
} else if (file.endsWith('.jux')) {
|
|
@@ -34,7 +65,7 @@ function findJuxFiles(dir, fileList = []) {
|
|
|
34
65
|
}
|
|
35
66
|
|
|
36
67
|
async function loadConfig() {
|
|
37
|
-
const configPath = path.join(projectRoot, 'jux.config.js');
|
|
68
|
+
const configPath = path.join(PATHS.projectRoot, 'jux.config.js');
|
|
38
69
|
|
|
39
70
|
if (fs.existsSync(configPath)) {
|
|
40
71
|
try {
|
|
@@ -50,44 +81,55 @@ async function loadConfig() {
|
|
|
50
81
|
}
|
|
51
82
|
|
|
52
83
|
async function buildProject(isServe = false) {
|
|
53
|
-
console.log('šØ Building JUX
|
|
84
|
+
console.log('šØ Building JUX frontend...\n');
|
|
54
85
|
|
|
55
86
|
try {
|
|
56
|
-
|
|
57
|
-
|
|
87
|
+
// Verify jux source directory exists
|
|
88
|
+
if (!fs.existsSync(PATHS.juxSource)) {
|
|
89
|
+
console.error(`ā Source directory not found: ${PATHS.juxSource}`);
|
|
90
|
+
console.error(` Please create a 'jux/' directory with your .jux files`);
|
|
91
|
+
process.exit(1);
|
|
58
92
|
}
|
|
59
|
-
fs.mkdirSync(distDir, { recursive: true });
|
|
60
93
|
|
|
61
|
-
//
|
|
94
|
+
// Clean and create frontend dist
|
|
95
|
+
if (fs.existsSync(PATHS.frontendDist)) {
|
|
96
|
+
fs.rmSync(PATHS.frontendDist, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
fs.mkdirSync(PATHS.frontendDist, { recursive: true });
|
|
99
|
+
|
|
100
|
+
// Step 1: Generate documentation from jux lib
|
|
62
101
|
console.log('š Generating documentation...');
|
|
63
102
|
try {
|
|
64
|
-
await generateDocs(
|
|
103
|
+
await generateDocs(PATHS.juxLib);
|
|
65
104
|
console.log('ā
Documentation generated\n');
|
|
66
105
|
} catch (error) {
|
|
67
106
|
console.warn('ā ļø Failed to generate docs:', error.message);
|
|
68
107
|
}
|
|
69
108
|
|
|
70
|
-
// Step 2: Copy lib
|
|
71
|
-
await copyLibToOutput(
|
|
109
|
+
// Step 2: Copy jux lib to frontend dist
|
|
110
|
+
await copyLibToOutput(PATHS.juxLib, PATHS.frontendDist);
|
|
72
111
|
|
|
73
|
-
// Step 3: Copy project assets (CSS, JS)
|
|
74
|
-
await copyProjectAssets(
|
|
112
|
+
// Step 3: Copy project assets from jux/ (CSS, JS, images)
|
|
113
|
+
await copyProjectAssets(PATHS.juxSource, PATHS.frontendDist);
|
|
75
114
|
|
|
76
|
-
// Step 4:
|
|
77
|
-
const projectJuxFiles = findJuxFiles(
|
|
78
|
-
console.log(`Found ${projectJuxFiles.length}
|
|
115
|
+
// Step 4: Compile .jux files from jux/ directory ONLY
|
|
116
|
+
const projectJuxFiles = findJuxFiles(PATHS.juxSource);
|
|
117
|
+
console.log(`Found ${projectJuxFiles.length} .jux file(s) in /jux\n`);
|
|
79
118
|
|
|
80
119
|
for (const file of projectJuxFiles) {
|
|
81
120
|
try {
|
|
82
|
-
await compileJuxFile(file, {
|
|
121
|
+
await compileJuxFile(file, {
|
|
122
|
+
distDir: PATHS.frontendDist,
|
|
123
|
+
projectRoot: PATHS.juxSource,
|
|
124
|
+
isServe
|
|
125
|
+
});
|
|
83
126
|
} catch (err) {
|
|
84
127
|
console.error(`Error compiling ${file}:`, err.message);
|
|
85
128
|
}
|
|
86
129
|
}
|
|
87
130
|
|
|
88
|
-
// Step 5:
|
|
89
|
-
const
|
|
90
|
-
const layoutsDir = path.join(libRoot, 'layouts');
|
|
131
|
+
// Step 5: Compile vendor layouts
|
|
132
|
+
const layoutsDir = path.join(PATHS.juxLib, 'layouts');
|
|
91
133
|
|
|
92
134
|
if (fs.existsSync(layoutsDir)) {
|
|
93
135
|
console.log('\nš Compiling vendor layouts...');
|
|
@@ -96,11 +138,11 @@ async function buildProject(isServe = false) {
|
|
|
96
138
|
|
|
97
139
|
for (const file of vendorJuxFiles) {
|
|
98
140
|
try {
|
|
99
|
-
const relPath = path.relative(
|
|
141
|
+
const relPath = path.relative(PATHS.juxLib, file);
|
|
100
142
|
|
|
101
143
|
await compileJuxFile(file, {
|
|
102
|
-
distDir: path.join(
|
|
103
|
-
projectRoot:
|
|
144
|
+
distDir: path.join(PATHS.frontendDist, 'lib'),
|
|
145
|
+
projectRoot: PATHS.juxLib,
|
|
104
146
|
isServe
|
|
105
147
|
});
|
|
106
148
|
|
|
@@ -111,38 +153,123 @@ async function buildProject(isServe = false) {
|
|
|
111
153
|
}
|
|
112
154
|
}
|
|
113
155
|
|
|
114
|
-
console.log(`\nā
Built ${projectJuxFiles.length}
|
|
156
|
+
console.log(`\nā
Built ${projectJuxFiles.length} file(s) ā ${PATHS.frontendDist}\n`);
|
|
157
|
+
|
|
158
|
+
// Show backend integration examples
|
|
159
|
+
console.log('š¦ Serve from your backend:');
|
|
160
|
+
console.log(` Express: app.use(express.static('jux-dist'))`);
|
|
161
|
+
console.log(` Flask: app = Flask(__name__, static_folder='jux-dist')`);
|
|
162
|
+
console.log(` FastAPI: app.mount("/", StaticFiles(directory="jux-dist"), name="static")`);
|
|
163
|
+
console.log(` Laravel: Route::view('/', 'jux-dist/index.html')`);
|
|
164
|
+
console.log('');
|
|
165
|
+
|
|
115
166
|
} catch (err) {
|
|
116
167
|
console.error('ā Build error:', err.message);
|
|
168
|
+
console.error(err.stack);
|
|
117
169
|
process.exit(1);
|
|
118
170
|
}
|
|
119
171
|
}
|
|
120
172
|
|
|
121
173
|
(async () => {
|
|
122
|
-
if (command === '
|
|
174
|
+
if (command === 'init') {
|
|
175
|
+
console.log('šØ Initializing JUX project...\n');
|
|
176
|
+
|
|
177
|
+
const juxDir = PATHS.juxSource;
|
|
178
|
+
|
|
179
|
+
if (fs.existsSync(juxDir)) {
|
|
180
|
+
console.error('ā jux/ directory already exists');
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Create structure
|
|
185
|
+
fs.mkdirSync(juxDir, { recursive: true });
|
|
186
|
+
|
|
187
|
+
// Copy template file from lib/templates/index.juxt
|
|
188
|
+
const templatePath = path.join(PATHS.packageRoot, 'lib', 'templates', 'index.juxt');
|
|
189
|
+
const targetPath = path.join(juxDir, 'index.jux');
|
|
190
|
+
|
|
191
|
+
if (fs.existsSync(templatePath)) {
|
|
192
|
+
fs.copyFileSync(templatePath, targetPath);
|
|
193
|
+
console.log('ā
Created jux/index.jux from template');
|
|
194
|
+
} else {
|
|
195
|
+
// Fallback if template doesn't exist
|
|
196
|
+
console.warn('ā ļø Template not found, creating basic index.jux');
|
|
197
|
+
const fallbackContent = `// Welcome to JUX!
|
|
198
|
+
import { jux } from '/lib/jux.js';
|
|
199
|
+
|
|
200
|
+
jux.style('/lib/layouts/default.css');
|
|
201
|
+
jux.theme('light');
|
|
202
|
+
|
|
203
|
+
const header = jux.header('header').render("#app");
|
|
204
|
+
const main = jux.main('main').render("#app");
|
|
205
|
+
const footer = jux.footer('footer').render("#app");
|
|
206
|
+
|
|
207
|
+
jux.hero('hero1', {
|
|
208
|
+
title: 'Welcome to JUX',
|
|
209
|
+
subtitle: 'A JavaScript UX authorship platform'
|
|
210
|
+
}).render('#main');
|
|
211
|
+
`;
|
|
212
|
+
fs.writeFileSync(targetPath, fallbackContent);
|
|
213
|
+
console.log('ā
Created jux/index.jux');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Create .gitignore
|
|
217
|
+
const gitignorePath = path.join(PATHS.projectRoot, '.gitignore');
|
|
218
|
+
const gitignoreContent = `jux-dist/
|
|
219
|
+
node_modules/
|
|
220
|
+
.DS_Store
|
|
221
|
+
`;
|
|
222
|
+
|
|
223
|
+
if (!fs.existsSync(gitignorePath)) {
|
|
224
|
+
fs.writeFileSync(gitignorePath, gitignoreContent);
|
|
225
|
+
console.log('ā
Created .gitignore');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
console.log('ā
Created jux/ directory\n');
|
|
229
|
+
console.log('Next steps:');
|
|
230
|
+
console.log(' 1. Edit jux/index.jux');
|
|
231
|
+
console.log(' 2. Run: npx jux build');
|
|
232
|
+
console.log(' 3. Serve jux-dist/ from your backend\n');
|
|
233
|
+
|
|
234
|
+
} else if (command === 'build') {
|
|
123
235
|
await buildProject(false);
|
|
124
|
-
console.log(`ā
Build complete: ${
|
|
236
|
+
console.log(`ā
Build complete: ${PATHS.frontendDist}`);
|
|
125
237
|
|
|
126
238
|
} else if (command === 'serve') {
|
|
127
|
-
|
|
128
|
-
await buildProject(true); // isServe = true
|
|
239
|
+
await buildProject(true);
|
|
129
240
|
|
|
130
|
-
// Start server with watcher
|
|
131
241
|
const config = await loadConfig();
|
|
132
|
-
|
|
242
|
+
config.distDir = PATHS.frontendDist; // Pass the correct dist directory
|
|
243
|
+
|
|
244
|
+
const port = parseInt(process.argv[3]) || 3000;
|
|
245
|
+
await start(port, config);
|
|
133
246
|
|
|
134
247
|
} else {
|
|
135
248
|
console.log(`
|
|
136
249
|
JUX CLI - A JavaScript UX authorship platform
|
|
137
250
|
|
|
138
251
|
Usage:
|
|
139
|
-
npx jux
|
|
252
|
+
npx jux init Initialize a new JUX project
|
|
253
|
+
npx jux build Compile .jux files from ./jux/ to ./jux-dist/
|
|
140
254
|
npx jux serve [port] Start dev server with hot reload (default: 3000)
|
|
141
|
-
|
|
255
|
+
|
|
256
|
+
Project Structure (Convention):
|
|
257
|
+
my-project/
|
|
258
|
+
āāā jux/ # Your .jux source files (REQUIRED)
|
|
259
|
+
ā āāā index.jux
|
|
260
|
+
ā āāā pages/
|
|
261
|
+
āāā jux-dist/ # Build output (generated, git-ignore this)
|
|
262
|
+
āāā server/ # Your backend (untouched by jux)
|
|
263
|
+
āāā package.json
|
|
264
|
+
|
|
265
|
+
Getting Started:
|
|
266
|
+
1. npx jux init # Create jux/ directory
|
|
267
|
+
2. npx jux build # Build to jux-dist/
|
|
268
|
+
3. Serve jux-dist/ from your backend
|
|
142
269
|
|
|
143
270
|
Examples:
|
|
144
271
|
npx jux build Build for production
|
|
145
|
-
npx jux serve Start dev server
|
|
272
|
+
npx jux serve Start dev server
|
|
146
273
|
npx jux serve 8080 Start on port 8080
|
|
147
274
|
`);
|
|
148
275
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Welcome to JUX!
|
|
2
|
+
import { code } from '/lib/components/code.js';
|
|
3
|
+
import { jux } from '/lib/jux.js';
|
|
4
|
+
|
|
5
|
+
jux.style('/lib/layouts/notion.css');
|
|
6
|
+
jux.theme('light');
|
|
7
|
+
|
|
8
|
+
const appheader = jux.header('appheader', {}).render("#app");
|
|
9
|
+
const appsubheader = jux.header('appsubheader', {}).render("#app");
|
|
10
|
+
const appsidebar = jux.sidebar('appsidebar', {}).render("#app");
|
|
11
|
+
const appmain = jux.main('appmain', {}).render("#app");
|
|
12
|
+
const appaside = jux.sidebar('appaside', {}).render("#app");
|
|
13
|
+
const appfooter = jux.footer('appfooter', {}).render("#app");
|
|
14
|
+
const appmodal = jux.modal('appmodal', {}).render("#app");
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
await jux.hero('hero1', {
|
|
18
|
+
title: 'Welcome to JUX',
|
|
19
|
+
subtitle: 'A JavaScript UX authorship platform'
|
|
20
|
+
}).render();
|
|
21
|
+
|
|
22
|
+
const code1 = code('code1').code(`Serve from your backend:
|
|
23
|
+
Express: app.use(express.static('jux-dist'))
|
|
24
|
+
Flask: app = Flask(__name__, static_folder='jux-dist')
|
|
25
|
+
FastAPI: app.mount("/", StaticFiles(directory="jux-dist"), name="static")
|
|
26
|
+
Laravel: Route::view('/', 'jux-dist/index.html')`)
|
|
27
|
+
.language('bash');
|
|
28
|
+
|
|
29
|
+
code1.render();
|
|
30
|
+
|
|
31
|
+
// note
|
|
32
|
+
// render()
|
|
33
|
+
// renderTo()
|
|
@@ -4,10 +4,15 @@ import { glob } from 'glob';
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Generate documentation from TypeScript component files
|
|
7
|
+
*
|
|
8
|
+
* @param {string} juxLibPath - Absolute path to jux/lib directory
|
|
7
9
|
*/
|
|
8
|
-
export async function generateDocs(
|
|
9
|
-
const
|
|
10
|
-
|
|
10
|
+
export async function generateDocs(juxLibPath) {
|
|
11
|
+
const componentsDir = path.join(juxLibPath, 'components');
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(componentsDir)) {
|
|
14
|
+
throw new Error(`Components directory not found: ${componentsDir}`);
|
|
15
|
+
}
|
|
11
16
|
|
|
12
17
|
console.log(` Scanning: ${componentsDir}`);
|
|
13
18
|
|
|
@@ -15,7 +20,7 @@ export async function generateDocs(projectRoot) {
|
|
|
15
20
|
const componentFiles = glob.sync('*.ts', {
|
|
16
21
|
cwd: componentsDir,
|
|
17
22
|
absolute: true,
|
|
18
|
-
ignore: ['reactivity.
|
|
23
|
+
ignore: ['reactivity.ts', 'error-handler.ts']
|
|
19
24
|
});
|
|
20
25
|
|
|
21
26
|
console.log(` Found ${componentFiles.length} component files`);
|
|
@@ -62,23 +67,14 @@ function parseComponentFile(content, filePath) {
|
|
|
62
67
|
const fileName = path.basename(filePath, '.ts');
|
|
63
68
|
const className = fileName.charAt(0).toUpperCase() + fileName.slice(1);
|
|
64
69
|
|
|
65
|
-
// Extract category from file content or infer
|
|
66
70
|
const category = inferCategory(className, content);
|
|
67
|
-
|
|
68
|
-
// Extract description from class JSDoc
|
|
69
71
|
const descMatch = content.match(/\/\*\*\s*\n\s*\*\s*([^\n*]+)/);
|
|
70
72
|
const description = descMatch ? descMatch[1].trim() : `${className} component`;
|
|
71
|
-
|
|
72
|
-
// Extract constructor/factory pattern
|
|
73
73
|
const factoryMatch = content.match(/export function\s+\w+\(([^)]*)\)/);
|
|
74
74
|
const constructorSig = factoryMatch
|
|
75
75
|
? `jux.${fileName}(${factoryMatch[1]})`
|
|
76
76
|
: `new ${className}()`;
|
|
77
|
-
|
|
78
|
-
// Extract fluent methods
|
|
79
77
|
const fluentMethods = extractFluentMethods(content, className);
|
|
80
|
-
|
|
81
|
-
// Extract usage example from JSDoc
|
|
82
78
|
const exampleMatch = content.match(/\*\s+Usage:\s*\n\s*\*\s+(.+?)(?:\n|$)/);
|
|
83
79
|
let example = exampleMatch
|
|
84
80
|
? exampleMatch[1].trim()
|
|
@@ -99,28 +95,14 @@ function parseComponentFile(content, filePath) {
|
|
|
99
95
|
*/
|
|
100
96
|
function extractFluentMethods(content, className) {
|
|
101
97
|
const methods = [];
|
|
102
|
-
|
|
103
|
-
// Match method patterns: methodName(params): this
|
|
104
98
|
const methodRegex = /^\s*(\w+)\(([^)]*)\):\s*this\s*\{/gm;
|
|
105
99
|
let match;
|
|
106
100
|
|
|
107
101
|
while ((match = methodRegex.exec(content)) !== null) {
|
|
108
102
|
const methodName = match[1];
|
|
109
103
|
const params = match[2];
|
|
110
|
-
|
|
111
|
-
// Skip private methods and constructor
|
|
112
104
|
if (methodName.startsWith('_') || methodName === 'constructor') continue;
|
|
113
|
-
|
|
114
|
-
// Clean up params
|
|
115
|
-
const cleanParams = params
|
|
116
|
-
.split(',')
|
|
117
|
-
.map(p => {
|
|
118
|
-
const parts = p.trim().split(':');
|
|
119
|
-
return parts[0].trim();
|
|
120
|
-
})
|
|
121
|
-
.filter(p => p)
|
|
122
|
-
.join(', ');
|
|
123
|
-
|
|
105
|
+
const cleanParams = params.split(',').map(p => p.trim().split(':')[0].trim()).filter(p => p).join(', ');
|
|
124
106
|
methods.push({
|
|
125
107
|
name: methodName,
|
|
126
108
|
params: cleanParams ? `(${cleanParams})` : '()',
|
|
@@ -129,7 +111,6 @@ function extractFluentMethods(content, className) {
|
|
|
129
111
|
});
|
|
130
112
|
}
|
|
131
113
|
|
|
132
|
-
// Also look for render methods
|
|
133
114
|
const renderMatch = content.match(/^\s*render\(([^)]*)\):\s*(\w+)/m);
|
|
134
115
|
if (renderMatch && !methods.find(m => m.name === 'render')) {
|
|
135
116
|
methods.push({
|
|
@@ -149,12 +130,7 @@ function extractFluentMethods(content, className) {
|
|
|
149
130
|
function inferCategory(name, content) {
|
|
150
131
|
const dataComponents = ['Table', 'List', 'Chart', 'Data'];
|
|
151
132
|
const coreComponents = ['App', 'Layout', 'Theme', 'Style', 'Script', 'Import'];
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
return 'Data Components';
|
|
155
|
-
}
|
|
156
|
-
if (coreComponents.includes(name)) {
|
|
157
|
-
return 'Core';
|
|
158
|
-
}
|
|
133
|
+
if (dataComponents.some(dc => name.includes(dc))) return 'Data Components';
|
|
134
|
+
if (coreComponents.includes(name)) return 'Core';
|
|
159
135
|
return 'UI Components';
|
|
160
136
|
}
|
package/machinery/server.js
CHANGED
|
@@ -12,7 +12,7 @@ const __dirname = path.dirname(__filename);
|
|
|
12
12
|
|
|
13
13
|
let db = null;
|
|
14
14
|
|
|
15
|
-
async function serve(port = 3000, distDir = './dist') {
|
|
15
|
+
async function serve(port = 3000, distDir = './jux-dist') { // Changed default
|
|
16
16
|
const app = express();
|
|
17
17
|
const absoluteDistDir = path.resolve(distDir);
|
|
18
18
|
const projectRoot = path.resolve('.');
|
|
@@ -20,8 +20,8 @@ async function serve(port = 3000, distDir = './dist') {
|
|
|
20
20
|
app.use(express.json());
|
|
21
21
|
|
|
22
22
|
if (!fs.existsSync(absoluteDistDir)) {
|
|
23
|
-
console.error(
|
|
24
|
-
console.
|
|
23
|
+
console.error(`ā Error: ${path.basename(distDir)}/ directory not found at ${absoluteDistDir}`);
|
|
24
|
+
console.error(' Run: npx jux build\n');
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -146,16 +146,23 @@ async function serve(port = 3000, distDir = './dist') {
|
|
|
146
146
|
// Start HTTP server
|
|
147
147
|
server.listen(port, () => {
|
|
148
148
|
console.log(`š JUX dev server running at http://localhost:${port}`);
|
|
149
|
+
console.log(` Serving: ${absoluteDistDir}`);
|
|
150
|
+
console.log(` Press Ctrl+C to stop\n`);
|
|
149
151
|
});
|
|
150
152
|
|
|
151
153
|
// Start file watcher
|
|
152
|
-
|
|
154
|
+
const juxSource = path.join(projectRoot, 'jux');
|
|
155
|
+
if (fs.existsSync(juxSource)) {
|
|
156
|
+
console.log(`š Watching: ${juxSource}\n`);
|
|
157
|
+
startWatcher(juxSource, absoluteDistDir, clients);
|
|
158
|
+
}
|
|
153
159
|
|
|
154
160
|
// Graceful shutdown
|
|
155
161
|
const shutdown = async () => {
|
|
156
162
|
console.log('\n\nš Shutting down server...');
|
|
157
163
|
wss.close();
|
|
158
164
|
server.close();
|
|
165
|
+
if (db) db = null;
|
|
159
166
|
process.exit(0);
|
|
160
167
|
};
|
|
161
168
|
|
|
@@ -181,5 +188,5 @@ async function initDatabase() {
|
|
|
181
188
|
|
|
182
189
|
export async function start(port = 3000, config = {}) {
|
|
183
190
|
await initDatabase();
|
|
184
|
-
return serve(port, config.distDir || './dist');
|
|
191
|
+
return serve(port, config.distDir || './jux-dist'); // Changed default
|
|
185
192
|
}
|