juxscript 1.0.88 → 1.0.90
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/cli.js +243 -92
- package/index.js +21 -0
- package/lib/componentsv2/base/BaseEngine.d.ts +10 -0
- package/lib/componentsv2/base/BaseEngine.d.ts.map +1 -1
- package/lib/componentsv2/base/BaseEngine.js +28 -7
- package/lib/componentsv2/base/BaseEngine.js.map +1 -1
- package/lib/componentsv2/base/BaseEngine.ts +29 -0
- package/lib/componentsv2/base/OptionsContract.d.ts +20 -0
- package/lib/componentsv2/base/OptionsContract.d.ts.map +1 -0
- package/lib/componentsv2/base/OptionsContract.js +107 -0
- package/lib/componentsv2/base/OptionsContract.js.map +1 -0
- package/lib/componentsv2/base/OptionsContract.ts +139 -0
- package/lib/componentsv2/element/component.d.ts +22 -0
- package/lib/componentsv2/element/component.d.ts.map +1 -1
- package/lib/componentsv2/element/component.js +22 -0
- package/lib/componentsv2/element/component.js.map +1 -1
- package/lib/componentsv2/element/component.ts +23 -1
- package/lib/componentsv2/element/engine.d.ts +31 -14
- package/lib/componentsv2/element/engine.d.ts.map +1 -1
- package/lib/componentsv2/element/engine.js +74 -23
- package/lib/componentsv2/element/engine.js.map +1 -1
- package/lib/componentsv2/element/engine.ts +86 -29
- package/lib/componentsv2/element/skin.d.ts.map +1 -1
- package/lib/componentsv2/element/skin.js +7 -10
- package/lib/componentsv2/element/skin.js.map +1 -1
- package/lib/componentsv2/element/skin.ts +7 -11
- package/lib/componentsv2/grid/engine.d.ts +48 -3
- package/lib/componentsv2/grid/engine.d.ts.map +1 -1
- package/lib/componentsv2/grid/engine.js +109 -14
- package/lib/componentsv2/grid/engine.js.map +1 -1
- package/lib/componentsv2/grid/engine.ts +120 -16
- package/lib/componentsv2/input/engine.d.ts +48 -5
- package/lib/componentsv2/input/engine.d.ts.map +1 -1
- package/lib/componentsv2/input/engine.js +108 -15
- package/lib/componentsv2/input/engine.js.map +1 -1
- package/lib/componentsv2/input/engine.ts +119 -16
- package/lib/componentsv2/input/skin.d.ts.map +1 -1
- package/lib/componentsv2/input/skin.js +1 -4
- package/lib/componentsv2/input/skin.js.map +1 -1
- package/lib/componentsv2/input/skin.ts +1 -4
- package/lib/componentsv2/list/component.d.ts +28 -6
- package/lib/componentsv2/list/component.d.ts.map +1 -1
- package/lib/componentsv2/list/component.js +28 -6
- package/lib/componentsv2/list/component.js.map +1 -1
- package/lib/componentsv2/list/component.ts +28 -6
- package/lib/componentsv2/list/engine.d.ts +61 -9
- package/lib/componentsv2/list/engine.d.ts.map +1 -1
- package/lib/componentsv2/list/engine.js +156 -95
- package/lib/componentsv2/list/engine.js.map +1 -1
- package/lib/componentsv2/list/engine.ts +175 -108
- package/machinery/build3.js +21 -0
- package/machinery/compiler3.js +638 -0
- package/machinery/serve.js +255 -0
- package/machinery/watcher.js +53 -64
- package/package.json +11 -3
- package/lib/componentsv2/index.d.ts +0 -41
- package/lib/componentsv2/index.d.ts.map +0 -1
- package/lib/componentsv2/index.js +0 -223
- package/lib/componentsv2/index.js.map +0 -1
- package/lib/componentsv2/index.ts +0 -256
- package/lib/componentsv2/juxerror/component.d.ts +0 -28
- package/lib/componentsv2/juxerror/component.d.ts.map +0 -1
- package/lib/componentsv2/juxerror/component.js +0 -101
- package/lib/componentsv2/juxerror/component.js.map +0 -1
- package/lib/componentsv2/juxerror/component.ts +0 -125
- package/lib/componentsv2/juxerror/engine.d.ts +0 -35
- package/lib/componentsv2/juxerror/engine.d.ts.map +0 -1
- package/lib/componentsv2/juxerror/engine.js +0 -190
- package/lib/componentsv2/juxerror/engine.js.map +0 -1
- package/lib/componentsv2/juxerror/engine.ts +0 -241
- package/lib/componentsv2/juxerror/skin.d.ts +0 -11
- package/lib/componentsv2/juxerror/skin.d.ts.map +0 -1
- package/lib/componentsv2/juxerror/skin.js +0 -180
- package/lib/componentsv2/juxerror/skin.js.map +0 -1
- package/lib/componentsv2/juxerror/skin.ts +0 -200
- package/lib/componentsv2/juxerror/structure.css +0 -351
- package/machinery/ast.js +0 -347
- package/machinery/compiler.js +0 -706
- package/machinery/diagnose.js +0 -72
- package/machinery/doc-generator.js +0 -136
- package/machinery/imports.js +0 -155
- package/machinery/jux-module-pattern.md +0 -118
- package/machinery/server.js +0 -86
- package/machinery/ts-shim.js +0 -46
- package/machinery/verifier.js +0 -135
- package/tests/dropdown-test.js +0 -25
- package/tests/juxerrors/bad_syntax.jux +0 -8
- package/tests/juxerrors/ghost_dep.jux +0 -10
- package/tests/server_plugin_test.ts +0 -191
package/bin/cli.js
CHANGED
|
@@ -3,124 +3,275 @@
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
+
import { spawn } from 'child_process';
|
|
6
7
|
|
|
7
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
9
|
const __dirname = path.dirname(__filename);
|
|
9
|
-
const
|
|
10
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
const [, , command, ...args] = process.argv;
|
|
13
|
+
|
|
14
|
+
// ═══════════════════════════════════════════════════════════════
|
|
15
|
+
// COMMAND: create <project-name>
|
|
16
|
+
// Creates a new JUX project from the template
|
|
17
|
+
// ═══════════════════════════════════════════════════════════════
|
|
18
|
+
async function createProject(projectName) {
|
|
19
|
+
if (!projectName) {
|
|
20
|
+
console.error('❌ Usage: jux create <project-name>');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const targetDir = path.join(process.cwd(), projectName);
|
|
25
|
+
|
|
26
|
+
if (fs.existsSync(targetDir)) {
|
|
27
|
+
console.error(`❌ Directory "${projectName}" already exists.`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log(`\n📦 Creating JUX project: ${projectName}\n`);
|
|
32
|
+
|
|
33
|
+
// 1. Create project directory
|
|
34
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
35
|
+
|
|
36
|
+
// 2. Copy template from /create folder
|
|
37
|
+
const templateDir = path.join(PACKAGE_ROOT, 'create');
|
|
38
|
+
if (fs.existsSync(templateDir)) {
|
|
39
|
+
copyDirRecursive(templateDir, path.join(targetDir, 'jux'));
|
|
40
|
+
console.log(' ✓ Copied template files');
|
|
41
|
+
} else {
|
|
42
|
+
// Fallback: create minimal starter
|
|
43
|
+
const juxDir = path.join(targetDir, 'jux');
|
|
44
|
+
fs.mkdirSync(juxDir, { recursive: true });
|
|
45
|
+
fs.writeFileSync(
|
|
46
|
+
path.join(juxDir, 'index.jux'),
|
|
47
|
+
`import { Element } from 'juxscript';\n\nElement('welcome', { tagName: 'h1' })\n .text('Welcome to JUX!')\n .render('app');\n`
|
|
48
|
+
);
|
|
49
|
+
console.log(' ✓ Created starter file');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 3. Copy example config
|
|
53
|
+
const configSrc = path.join(PACKAGE_ROOT, 'juxconfig.example.js');
|
|
54
|
+
const configDest = path.join(targetDir, 'juxconfig.js');
|
|
55
|
+
if (fs.existsSync(configSrc)) {
|
|
56
|
+
fs.copyFileSync(configSrc, configDest);
|
|
57
|
+
console.log(' ✓ Created juxconfig.js');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 4. Create package.json
|
|
61
|
+
const pkg = {
|
|
62
|
+
name: projectName,
|
|
63
|
+
version: '0.1.0',
|
|
64
|
+
type: 'module',
|
|
65
|
+
scripts: {
|
|
66
|
+
dev: 'jux serve --hot',
|
|
67
|
+
build: 'jux build',
|
|
68
|
+
start: 'jux serve'
|
|
69
|
+
},
|
|
70
|
+
dependencies: {
|
|
71
|
+
juxscript: 'latest'
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
fs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify(pkg, null, 2));
|
|
75
|
+
console.log(' ✓ Created package.json');
|
|
76
|
+
|
|
77
|
+
// 5. Create .gitignore
|
|
78
|
+
fs.writeFileSync(
|
|
79
|
+
path.join(targetDir, '.gitignore'),
|
|
80
|
+
`.jux-dist/\nnode_modules/\n.DS_Store\n.env\n*.log\n`
|
|
81
|
+
);
|
|
82
|
+
console.log(' ✓ Created .gitignore');
|
|
83
|
+
|
|
84
|
+
// 6. Install dependencies
|
|
85
|
+
console.log('\n📥 Installing dependencies...\n');
|
|
86
|
+
try {
|
|
87
|
+
const { execSync } = await import('child_process');
|
|
88
|
+
execSync('npm install', { cwd: targetDir, stdio: 'inherit' });
|
|
89
|
+
} catch (err) {
|
|
90
|
+
console.warn('⚠️ npm install failed. Run it manually.');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log(`
|
|
94
|
+
✅ Project created successfully!
|
|
95
|
+
|
|
96
|
+
cd ${projectName}
|
|
97
|
+
npm run dev
|
|
98
|
+
|
|
99
|
+
`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ═══════════════════════════════════════════════════════════════
|
|
103
|
+
// COMMAND: init
|
|
104
|
+
// Initializes JUX in an existing project
|
|
105
|
+
// ═══════════════════════════════════════════════════════════════
|
|
106
|
+
function initProject() {
|
|
107
|
+
const targetDir = process.cwd();
|
|
108
|
+
|
|
109
|
+
console.log('\n📦 Initializing JUX in current directory\n');
|
|
110
|
+
|
|
111
|
+
// 1. Copy template to ./jux
|
|
112
|
+
const templateDir = path.join(PACKAGE_ROOT, 'create');
|
|
12
113
|
const juxDir = path.join(targetDir, 'jux');
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (fs.existsSync(presetDir)) {
|
|
17
|
-
fs.readdirSync(presetDir).forEach(file => {
|
|
18
|
-
if (file.startsWith('.')) return;
|
|
19
|
-
if (fs.statSync(path.join(presetDir, file)).isFile()) {
|
|
20
|
-
fs.copyFileSync(path.join(presetDir, file), path.join(juxDir, file));
|
|
21
|
-
copied++;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
114
|
+
|
|
115
|
+
if (!fs.existsSync(juxDir)) {
|
|
116
|
+
fs.mkdirSync(juxDir, { recursive: true });
|
|
24
117
|
}
|
|
25
|
-
|
|
26
|
-
|
|
118
|
+
|
|
119
|
+
if (fs.existsSync(templateDir)) {
|
|
120
|
+
copyDirRecursive(templateDir, juxDir);
|
|
121
|
+
console.log(' ✓ Copied template files to ./jux');
|
|
122
|
+
} else {
|
|
123
|
+
fs.writeFileSync(
|
|
124
|
+
path.join(juxDir, 'index.jux'),
|
|
125
|
+
`import { Element } from 'juxscript';\n\nElement('welcome', { tagName: 'h1' })\n .text('Welcome to JUX!')\n .render('app');\n`
|
|
126
|
+
);
|
|
127
|
+
console.log(' ✓ Created starter file');
|
|
27
128
|
}
|
|
28
|
-
|
|
129
|
+
|
|
130
|
+
// 2. Copy config if not exists
|
|
29
131
|
const configDest = path.join(targetDir, 'juxconfig.js');
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
132
|
+
if (!fs.existsSync(configDest)) {
|
|
133
|
+
const configSrc = path.join(PACKAGE_ROOT, 'juxconfig.example.js');
|
|
134
|
+
if (fs.existsSync(configSrc)) {
|
|
135
|
+
fs.copyFileSync(configSrc, configDest);
|
|
136
|
+
console.log(' ✓ Created juxconfig.js');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 3. Update package.json scripts if exists
|
|
33
141
|
const pkgPath = path.join(targetDir, 'package.json');
|
|
34
142
|
if (fs.existsSync(pkgPath)) {
|
|
35
143
|
try {
|
|
36
144
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
37
145
|
pkg.scripts = pkg.scripts || {};
|
|
38
146
|
let modified = false;
|
|
39
|
-
|
|
147
|
+
|
|
148
|
+
if (!pkg.scripts.dev) { pkg.scripts.dev = 'jux serve --hot'; modified = true; }
|
|
40
149
|
if (!pkg.scripts.build) { pkg.scripts.build = 'jux build'; modified = true; }
|
|
41
|
-
if (
|
|
42
|
-
|
|
150
|
+
if (!pkg.scripts.start) { pkg.scripts.start = 'jux serve'; modified = true; }
|
|
151
|
+
|
|
152
|
+
if (modified) {
|
|
153
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
154
|
+
console.log(' ✓ Updated package.json scripts');
|
|
155
|
+
}
|
|
156
|
+
} catch (e) {
|
|
157
|
+
console.warn(' ⚠️ Could not update package.json');
|
|
158
|
+
}
|
|
43
159
|
}
|
|
160
|
+
|
|
161
|
+
console.log('\n✅ Initialized. Run: npm run dev\n');
|
|
44
162
|
}
|
|
45
163
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
164
|
+
// ═══════════════════════════════════════════════════════════════
|
|
165
|
+
// COMMAND: build
|
|
166
|
+
// Delegates to machinery/build3.js
|
|
167
|
+
// ═══════════════════════════════════════════════════════════════
|
|
168
|
+
function runBuild() {
|
|
169
|
+
const buildScript = path.join(PACKAGE_ROOT, 'machinery', 'build3.js');
|
|
170
|
+
|
|
171
|
+
if (!fs.existsSync(buildScript)) {
|
|
172
|
+
console.error('❌ Build script not found:', buildScript);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const child = spawn('node', [buildScript, ...args], {
|
|
177
|
+
cwd: process.cwd(),
|
|
178
|
+
stdio: 'inherit',
|
|
179
|
+
env: process.env
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
child.on('close', (code) => process.exit(code || 0));
|
|
62
183
|
}
|
|
63
184
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
185
|
+
// ═══════════════════════════════════════════════════════════════
|
|
186
|
+
// COMMAND: serve [--hot]
|
|
187
|
+
// Delegates to machinery/serve.js
|
|
188
|
+
// ═══════════════════════════════════════════════════════════════
|
|
189
|
+
function runServe() {
|
|
190
|
+
const serveScript = path.join(PACKAGE_ROOT, 'machinery', 'serve.js');
|
|
191
|
+
|
|
192
|
+
if (!fs.existsSync(serveScript)) {
|
|
193
|
+
console.error('❌ Serve script not found:', serveScript);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Pass through all args (including --hot)
|
|
198
|
+
const child = spawn('node', [serveScript, ...args], {
|
|
199
|
+
cwd: process.cwd(),
|
|
200
|
+
stdio: 'inherit',
|
|
201
|
+
env: process.env
|
|
202
|
+
});
|
|
68
203
|
|
|
69
|
-
|
|
70
|
-
const configPath = path.join(projectRoot, 'juxconfig.js');
|
|
71
|
-
let rawConfig = {};
|
|
72
|
-
if (fs.existsSync(configPath)) { try { const module = await import(configPath); rawConfig = module.default || module.config || {}; } catch (err) { } }
|
|
73
|
-
return resolveConfig(rawConfig, projectRoot);
|
|
204
|
+
child.on('close', (code) => process.exit(code || 0));
|
|
74
205
|
}
|
|
75
206
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
get juxLib() { return path.resolve(this.packageRoot, 'lib'); },
|
|
84
|
-
get frontendDist() { return path.join(this.projectRoot, config.directories?.distribution || '.jux-dist'); }
|
|
85
|
-
};
|
|
207
|
+
// ═══════════════════════════════════════════════════════════════
|
|
208
|
+
// UTILITIES
|
|
209
|
+
// ═══════════════════════════════════════════════════════════════
|
|
210
|
+
function copyDirRecursive(src, dest) {
|
|
211
|
+
if (!fs.existsSync(dest)) {
|
|
212
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
213
|
+
}
|
|
86
214
|
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
if (fs.existsSync(PATHS.frontendDist)) fs.rmSync(PATHS.frontendDist, { recursive: true, force: true });
|
|
90
|
-
fs.mkdirSync(PATHS.frontendDist, { recursive: true });
|
|
215
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
216
|
+
if (entry.name.startsWith('.')) continue; // Skip hidden files
|
|
91
217
|
|
|
92
|
-
|
|
93
|
-
|
|
218
|
+
const srcPath = path.join(src, entry.name);
|
|
219
|
+
const destPath = path.join(dest, entry.name);
|
|
94
220
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
await transpileProjectTypeScript(PATHS.juxSource, PATHS.frontendDist);
|
|
100
|
-
const bundleResult = await bundleJuxFilesToRouter(PATHS.juxSource, PATHS.frontendDist, { routePrefix: '', config });
|
|
101
|
-
generateIndexHtml(PATHS.frontendDist, bundleResult, { isDev: isServe, wsPort: isServe ? wsPort : undefined });
|
|
102
|
-
if (!verifyStaticBuild(PATHS.frontendDist)) { console.error('🛑 Critical Build Failure.'); process.exit(1); }
|
|
103
|
-
|
|
104
|
-
const fileCount = fs.readdirSync(PATHS.juxSource).filter(f => f.endsWith('.jux')).length; // Approximate check
|
|
105
|
-
console.log(`✅ Done. (${fileCount} files, ${(fs.statSync(path.join(PATHS.frontendDist, 'main.js')).size / 1024).toFixed(1)}KB)`);
|
|
106
|
-
} catch (err) {
|
|
107
|
-
console.log('❌ Failed.');
|
|
108
|
-
console.error(err.message);
|
|
109
|
-
process.exit(1);
|
|
221
|
+
if (entry.isDirectory()) {
|
|
222
|
+
copyDirRecursive(srcPath, destPath);
|
|
223
|
+
} else {
|
|
224
|
+
fs.copyFileSync(srcPath, destPath);
|
|
110
225
|
}
|
|
111
226
|
}
|
|
227
|
+
}
|
|
112
228
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
229
|
+
function showHelp() {
|
|
230
|
+
console.log(`
|
|
231
|
+
JUX CLI
|
|
232
|
+
|
|
233
|
+
Usage:
|
|
234
|
+
jux create <name> Create a new JUX project
|
|
235
|
+
jux init Initialize JUX in current directory
|
|
236
|
+
jux build Build for production
|
|
237
|
+
jux serve Start production server
|
|
238
|
+
jux serve --hot Start dev server with hot reload
|
|
239
|
+
|
|
240
|
+
Options:
|
|
241
|
+
--help, -h Show this help message
|
|
242
|
+
`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ═══════════════════════════════════════════════════════════════
|
|
246
|
+
// MAIN ROUTER
|
|
247
|
+
// ═══════════════════════════════════════════════════════════════
|
|
248
|
+
switch (command) {
|
|
249
|
+
case 'create':
|
|
250
|
+
createProject(args[0]);
|
|
251
|
+
break;
|
|
252
|
+
|
|
253
|
+
case 'init':
|
|
254
|
+
case 'install':
|
|
255
|
+
initProject();
|
|
256
|
+
break;
|
|
257
|
+
|
|
258
|
+
case 'build':
|
|
259
|
+
runBuild();
|
|
260
|
+
break;
|
|
261
|
+
|
|
262
|
+
case 'serve':
|
|
263
|
+
case 'dev':
|
|
264
|
+
runServe();
|
|
265
|
+
break;
|
|
266
|
+
|
|
267
|
+
case '--help':
|
|
268
|
+
case '-h':
|
|
269
|
+
case undefined:
|
|
270
|
+
showHelp();
|
|
271
|
+
break;
|
|
272
|
+
|
|
273
|
+
default:
|
|
274
|
+
console.error(`❌ Unknown command: ${command}`);
|
|
275
|
+
showHelp();
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JUX - JavaScript UX Authorship Platform
|
|
3
|
+
*
|
|
4
|
+
* Main entry point for the juxscript package.
|
|
5
|
+
* Re-exports all public components and utilities.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Core Components
|
|
9
|
+
export { Element } from './lib/componentsv2/element/component.js';
|
|
10
|
+
export { Grid } from './lib/componentsv2/grid/component.js';
|
|
11
|
+
export { Input } from './lib/componentsv2/input/component.js';
|
|
12
|
+
export { List } from './lib/componentsv2/list/component.js';
|
|
13
|
+
|
|
14
|
+
// Base Classes (for extension)
|
|
15
|
+
export { BaseEngine, BaseState } from './lib/componentsv2/base/BaseEngine.js';
|
|
16
|
+
export { BaseSkin } from './lib/componentsv2/base/BaseSkin.js';
|
|
17
|
+
export { State } from './lib/componentsv2/base/State.js';
|
|
18
|
+
export { GlobalBus } from './lib/componentsv2/base/GlobalBus.js';
|
|
19
|
+
|
|
20
|
+
// Utilities
|
|
21
|
+
export { validateOptions } from './lib/componentsv2/base/OptionsContract.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OptionsContractSchema, ValidationResult } from './OptionsContract.js';
|
|
1
2
|
export interface JuxServiceContract<TEngine = any> {
|
|
2
3
|
name: string;
|
|
3
4
|
version?: string;
|
|
@@ -24,6 +25,15 @@ type EventListener<T = any> = (data: T) => void;
|
|
|
24
25
|
export declare abstract class BaseEngine<TState extends BaseState, TOptions = any> {
|
|
25
26
|
#private;
|
|
26
27
|
constructor(id: string, options: TOptions);
|
|
28
|
+
/**
|
|
29
|
+
* CONTRACT: Override to define the valid options schema for this engine.
|
|
30
|
+
* Enables option validation with helpful error messages.
|
|
31
|
+
*/
|
|
32
|
+
protected get optionsSchema(): OptionsContractSchema | null;
|
|
33
|
+
/**
|
|
34
|
+
* Access validation results (warnings, errors, normalized options)
|
|
35
|
+
*/
|
|
36
|
+
get validation(): ValidationResult | null;
|
|
27
37
|
/**
|
|
28
38
|
* CONTRACT: Must transform input options into the initial State.
|
|
29
39
|
* This separates "mapping logic" from "construction/startup logic".
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseEngine.d.ts","sourceRoot":"","sources":["BaseEngine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BaseEngine.d.ts","sourceRoot":"","sources":["BaseEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
1
6
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
7
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
8
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
11
|
};
|
|
7
|
-
var
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _BaseEngine_state, _BaseEngine_listeners, _BaseEngine_cleanupListeners, _BaseEngine_plugins, _BaseEngine_emitHistory, _BaseEngine_debugMode;
|
|
12
|
+
var _BaseEngine_state, _BaseEngine_listeners, _BaseEngine_cleanupListeners, _BaseEngine_plugins, _BaseEngine_emitHistory, _BaseEngine_debugMode, _BaseEngine_validationResult;
|
|
13
13
|
import { State } from './State.js';
|
|
14
14
|
import { GlobalBus } from './GlobalBus.js';
|
|
15
|
+
import { validateOptions } from './OptionsContract.js';
|
|
15
16
|
/**
|
|
16
17
|
* THE ENGINE AGREEMENT
|
|
17
18
|
*
|
|
@@ -27,10 +28,30 @@ export class BaseEngine {
|
|
|
27
28
|
_BaseEngine_plugins.set(this, new Map());
|
|
28
29
|
_BaseEngine_emitHistory.set(this, []);
|
|
29
30
|
_BaseEngine_debugMode.set(this, false);
|
|
31
|
+
_BaseEngine_validationResult.set(this, null);
|
|
32
|
+
// Validate options if schema is defined
|
|
33
|
+
const schema = this.optionsSchema;
|
|
34
|
+
if (schema) {
|
|
35
|
+
__classPrivateFieldSet(this, _BaseEngine_validationResult, validateOptions(this.constructor.name, options, schema, __classPrivateFieldGet(this, _BaseEngine_debugMode, "f")), "f");
|
|
36
|
+
options = __classPrivateFieldGet(this, _BaseEngine_validationResult, "f").normalized;
|
|
37
|
+
}
|
|
30
38
|
// Enforce the Contract: Child must define how state is born from options
|
|
31
39
|
const initialState = this.prepareState(id, options);
|
|
32
40
|
__classPrivateFieldSet(this, _BaseEngine_state, new State(initialState), "f");
|
|
33
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* CONTRACT: Override to define the valid options schema for this engine.
|
|
44
|
+
* Enables option validation with helpful error messages.
|
|
45
|
+
*/
|
|
46
|
+
get optionsSchema() {
|
|
47
|
+
return null; // Override in child classes
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Access validation results (warnings, errors, normalized options)
|
|
51
|
+
*/
|
|
52
|
+
get validation() {
|
|
53
|
+
return __classPrivateFieldGet(this, _BaseEngine_validationResult, "f");
|
|
54
|
+
}
|
|
34
55
|
get state() {
|
|
35
56
|
return __classPrivateFieldGet(this, _BaseEngine_state, "f").value;
|
|
36
57
|
}
|
|
@@ -254,5 +275,5 @@ export class BaseEngine {
|
|
|
254
275
|
return this;
|
|
255
276
|
}
|
|
256
277
|
}
|
|
257
|
-
_BaseEngine_state = new WeakMap(), _BaseEngine_listeners = new WeakMap(), _BaseEngine_cleanupListeners = new WeakMap(), _BaseEngine_plugins = new WeakMap(), _BaseEngine_emitHistory = new WeakMap(), _BaseEngine_debugMode = new WeakMap();
|
|
278
|
+
_BaseEngine_state = new WeakMap(), _BaseEngine_listeners = new WeakMap(), _BaseEngine_cleanupListeners = new WeakMap(), _BaseEngine_plugins = new WeakMap(), _BaseEngine_emitHistory = new WeakMap(), _BaseEngine_debugMode = new WeakMap(), _BaseEngine_validationResult = new WeakMap();
|
|
258
279
|
//# sourceMappingURL=BaseEngine.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseEngine.js","sourceRoot":"","sources":["BaseEngine.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"BaseEngine.js","sourceRoot":"","sources":["BaseEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { State } from './State.js';
|
|
2
2
|
import { GlobalBus } from './GlobalBus.js';
|
|
3
|
+
import { validateOptions, OptionsContractSchema, ValidationResult } from './OptionsContract.js';
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
export interface JuxServiceContract<TEngine = any> {
|
|
@@ -35,13 +36,41 @@ export abstract class BaseEngine<TState extends BaseState, TOptions = any> {
|
|
|
35
36
|
#plugins = new Map<string, JuxServiceContract>();
|
|
36
37
|
#emitHistory: string[] = [];
|
|
37
38
|
#debugMode = false;
|
|
39
|
+
#validationResult: ValidationResult | null = null;
|
|
38
40
|
|
|
39
41
|
constructor(id: string, options: TOptions) {
|
|
42
|
+
// Validate options if schema is defined
|
|
43
|
+
const schema = this.optionsSchema;
|
|
44
|
+
if (schema) {
|
|
45
|
+
this.#validationResult = validateOptions(
|
|
46
|
+
this.constructor.name,
|
|
47
|
+
options as Record<string, any>,
|
|
48
|
+
schema,
|
|
49
|
+
this.#debugMode
|
|
50
|
+
);
|
|
51
|
+
options = this.#validationResult.normalized as TOptions;
|
|
52
|
+
}
|
|
53
|
+
|
|
40
54
|
// Enforce the Contract: Child must define how state is born from options
|
|
41
55
|
const initialState = this.prepareState(id, options);
|
|
42
56
|
this.#state = new State(initialState);
|
|
43
57
|
}
|
|
44
58
|
|
|
59
|
+
/**
|
|
60
|
+
* CONTRACT: Override to define the valid options schema for this engine.
|
|
61
|
+
* Enables option validation with helpful error messages.
|
|
62
|
+
*/
|
|
63
|
+
protected get optionsSchema(): OptionsContractSchema | null {
|
|
64
|
+
return null; // Override in child classes
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Access validation results (warnings, errors, normalized options)
|
|
69
|
+
*/
|
|
70
|
+
get validation(): ValidationResult | null {
|
|
71
|
+
return this.#validationResult;
|
|
72
|
+
}
|
|
73
|
+
|
|
45
74
|
/**
|
|
46
75
|
* CONTRACT: Must transform input options into the initial State.
|
|
47
76
|
* This separates "mapping logic" from "construction/startup logic".
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface OptionDefinition {
|
|
2
|
+
type: 'string' | 'number' | 'boolean' | 'array' | 'object' | 'function';
|
|
3
|
+
required?: boolean;
|
|
4
|
+
default?: any;
|
|
5
|
+
description?: string;
|
|
6
|
+
aliases?: string[];
|
|
7
|
+
}
|
|
8
|
+
export type OptionsContractSchema = Record<string, OptionDefinition>;
|
|
9
|
+
export interface ValidationResult {
|
|
10
|
+
valid: boolean;
|
|
11
|
+
warnings: string[];
|
|
12
|
+
errors: string[];
|
|
13
|
+
normalized: Record<string, any>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Validates user-provided options against a defined contract schema.
|
|
17
|
+
* Emits warnings for unknown/misnamed options and errors for type mismatches.
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateOptions<T extends Record<string, any>>(componentName: string, userOptions: Record<string, any>, schema: OptionsContractSchema, debugMode?: boolean): ValidationResult;
|
|
20
|
+
//# sourceMappingURL=OptionsContract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OptionsContract.d.ts","sourceRoot":"","sources":["OptionsContract.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;IACxE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAErE,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzD,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,MAAM,EAAE,qBAAqB,EAC7B,SAAS,GAAE,OAAe,GAC3B,gBAAgB,CAqElB"}
|