cbs-block 1.0.5 → 1.0.7
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/cbs-block.js +61 -33
- package/package.json +1 -1
- package/templates/README.md +18 -0
- package/templates/tutorial.html +54 -0
package/bin/cbs-block.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const chalk = require('chalk');
|
|
6
|
-
const { execSync } = require('child_process');
|
|
6
|
+
const { execSync, exec } = require('child_process');
|
|
7
7
|
|
|
8
8
|
async function main() {
|
|
9
9
|
const { default: inquirer } = await import('inquirer');
|
|
@@ -14,13 +14,15 @@ async function main() {
|
|
|
14
14
|
|
|
15
15
|
if (command === 'create') {
|
|
16
16
|
const answers = await inquirer.prompt([
|
|
17
|
-
{ type: 'input', name: 'name', message: '
|
|
17
|
+
{ type: 'input', name: 'name', message: 'Internal ID (no spaces):', default: target || 'my-block' },
|
|
18
|
+
{ type: 'input', name: 'displayName', message: 'Display Name:', default: (a) => a.name },
|
|
19
|
+
{ type: 'input', name: 'publisher', message: 'Publisher:', default: 'cbs-creator' },
|
|
18
20
|
{ type: 'list', name: 'category', message: 'Category:', choices: ['Math', 'Logic', 'Control', 'Input', 'Output', 'Data', 'Custom'] },
|
|
19
21
|
{ type: 'input', name: 'color', message: 'Hex Color:', default: (a) => {
|
|
20
22
|
const colors = { 'Math': '#4A90E2', 'Logic': '#F5A623', 'Control': '#FFCC00', 'Custom': '#4CAF50' };
|
|
21
23
|
return colors[a.category] || '#4CAF50';
|
|
22
24
|
}},
|
|
23
|
-
{ type: 'confirm', name: 'useDir', message: 'Create as directory (
|
|
25
|
+
{ type: 'confirm', name: 'useDir', message: 'Create as directory (Professional Extension Mode)?', default: true },
|
|
24
26
|
{ type: 'list', name: 'lang', message: 'Primary Language:', choices: ['JavaScript', 'TypeScript'] }
|
|
25
27
|
]);
|
|
26
28
|
|
|
@@ -54,14 +56,28 @@ async function main() {
|
|
|
54
56
|
fs.writeFileSync(path.join(dirName, answers.lang === 'TypeScript' ? 'index.ts' : 'index.js'), logicStr);
|
|
55
57
|
fs.writeFileSync(path.join(dirName, 'package.json'), JSON.stringify({
|
|
56
58
|
name: dirName,
|
|
59
|
+
displayName: answers.displayName,
|
|
60
|
+
publisher: answers.publisher,
|
|
57
61
|
version: "1.0.0",
|
|
58
62
|
main: "index.js",
|
|
63
|
+
engines: { "cbs": ">=1.1.0" },
|
|
59
64
|
dependencies: {}
|
|
60
65
|
}, null, 2));
|
|
61
66
|
|
|
67
|
+
// NEW: Copy templates
|
|
68
|
+
const templateDir = path.join(__dirname, '../templates');
|
|
69
|
+
if (fs.existsSync(templateDir)) {
|
|
70
|
+
['tutorial.html', 'README.md'].forEach(file => {
|
|
71
|
+
let content = fs.readFileSync(path.join(templateDir, file), 'utf8');
|
|
72
|
+
content = content.replace(/{BLOCK_NAME}/g, answers.name);
|
|
73
|
+
fs.writeFileSync(path.join(dirName, file), content);
|
|
74
|
+
});
|
|
75
|
+
fs.writeFileSync(path.join(dirName, 'LICENSE'), `MIT License\n\nCopyright (c) 2026 ${answers.name} Author`);
|
|
76
|
+
}
|
|
77
|
+
|
|
62
78
|
console.log(chalk.green(`\n✔ Created code-first block directory: ${chalk.bold(dirName)}`));
|
|
63
79
|
console.log(chalk.cyan(` → cd ${dirName}`));
|
|
64
|
-
console.log(chalk.cyan(` →
|
|
80
|
+
console.log(chalk.cyan(` → cbs-block tutorial (View the guide!)`));
|
|
65
81
|
console.log(chalk.cyan(` → cbs-block build`));
|
|
66
82
|
|
|
67
83
|
} else {
|
|
@@ -106,7 +122,9 @@ async function main() {
|
|
|
106
122
|
// Simple bundle logic: find imports and Warn for now (Premium feature for Phase 15.1)
|
|
107
123
|
// For now, we wrap it into a compatible run function for the engine
|
|
108
124
|
if (logic.includes('export function run')) {
|
|
109
|
-
logic = logic.replace(
|
|
125
|
+
logic = logic.replace(/export\s+function\s+run/g, 'function run');
|
|
126
|
+
} else if (logic.includes('export const run')) {
|
|
127
|
+
logic = logic.replace(/export\s+const\s+run\s*=\s*/g, 'function run');
|
|
110
128
|
}
|
|
111
129
|
|
|
112
130
|
metadata.logic = logic;
|
|
@@ -134,31 +152,29 @@ async function main() {
|
|
|
134
152
|
console.log(chalk.green(`\n✔ Project ${chalk.bold(answers.projName)} initialized!`));
|
|
135
153
|
|
|
136
154
|
} else if (command === 'pack') {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
155
|
+
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
156
|
+
if (!fs.existsSync(pkgPath)) {
|
|
157
|
+
// Legacy/Single-file packing (keeping for compatibility)
|
|
158
|
+
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
159
|
+
const pack = { package: path.basename(process.cwd()), version: "1.0.4", blocks: files.map(f => JSON.parse(fs.readFileSync(f, 'utf8'))) };
|
|
160
|
+
fs.writeFileSync(`${pack.package}.cbspak`, JSON.stringify(pack, null, 2));
|
|
161
|
+
return console.log(chalk.green(`\n✔ Legacy pack created: ${pack.package}.cbspak`));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
165
|
+
const packName = `${pkg.name}-${pkg.version}.cbsext`;
|
|
166
|
+
console.log(chalk.yellow(`Bundling professional extension: ${chalk.bold(packName)}...`));
|
|
141
167
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
];
|
|
153
|
-
|
|
154
|
-
const pack = {
|
|
155
|
-
package: path.basename(process.cwd()),
|
|
156
|
-
version: "1.0.0",
|
|
157
|
-
blocks: packedBlocks
|
|
158
|
-
};
|
|
159
|
-
const packName = `${pack.package}.cbspak`;
|
|
160
|
-
fs.writeFileSync(packName, JSON.stringify(pack, null, 2));
|
|
161
|
-
console.log(chalk.green(`\n✔ Packed ${packedBlocks.length} blocks into ${chalk.bold(packName)}`));
|
|
168
|
+
try {
|
|
169
|
+
// Use tar to create a ZIP (Cross-platform)
|
|
170
|
+
// -a (auto-compress based on extension), -c (create), -f (file)
|
|
171
|
+
// We include everything except node_modules (build command already bundled what's needed)
|
|
172
|
+
execSync(`tar -a -c -f ${packName} --exclude=node_modules .`);
|
|
173
|
+
console.log(chalk.green(`\n✔ Extension packed successfully: ${chalk.bold(packName)}`));
|
|
174
|
+
console.log(chalk.dim(`This file is ready for Marketplace installation.`));
|
|
175
|
+
} catch (e) {
|
|
176
|
+
console.error(chalk.red(`\n✘ Packing failed: ${e.message}`));
|
|
177
|
+
}
|
|
162
178
|
|
|
163
179
|
} else if (command === 'doc' && target) {
|
|
164
180
|
if (!fs.existsSync(target)) return console.error(chalk.red(`Error: File ${target} not found.`));
|
|
@@ -206,13 +222,24 @@ async function main() {
|
|
|
206
222
|
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
207
223
|
console.log(chalk.yellow(`Testing logic for: ${block.name}...`));
|
|
208
224
|
try {
|
|
209
|
-
const run = new Function('inputs',
|
|
225
|
+
const run = new Function('inputs', block.logic + '\nreturn run(inputs);');
|
|
210
226
|
const testResult = run({ input1: "Test Input" });
|
|
211
227
|
console.log(chalk.green(`\n✔ Test Passed! Output: ${testResult}`));
|
|
212
228
|
} catch (e) {
|
|
213
229
|
console.error(chalk.red(`\n✘ Test Failed: ${e.message}`));
|
|
214
230
|
}
|
|
215
231
|
|
|
232
|
+
} else if (command === 'tutorial') {
|
|
233
|
+
const tutorialPath = path.join(process.cwd(), 'tutorial.html');
|
|
234
|
+
if (fs.existsSync(tutorialPath)) {
|
|
235
|
+
console.log(chalk.cyan(`Opening Developer Guide...`));
|
|
236
|
+
const start = process.platform === 'win32' ? 'start' : process.platform === 'darwin' ? 'open' : 'xdg-open';
|
|
237
|
+
exec(`${start} ${tutorialPath}`);
|
|
238
|
+
} else {
|
|
239
|
+
console.error(chalk.red(`Error: tutorial.html not found in current directory.`));
|
|
240
|
+
console.log(chalk.dim(`Try running 'cbs-block create' to generate a project with a tutorial.`));
|
|
241
|
+
}
|
|
242
|
+
|
|
216
243
|
} else if (command === 'publish' && target) {
|
|
217
244
|
if (!fs.existsSync(target)) return console.error(chalk.red(`Error: File ${target} not found.`));
|
|
218
245
|
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
@@ -232,7 +259,7 @@ async function main() {
|
|
|
232
259
|
console.log(chalk.cyan(`\n[CHANGE] Re-testing ${target}...`));
|
|
233
260
|
try {
|
|
234
261
|
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
235
|
-
const run = new Function('inputs',
|
|
262
|
+
const run = new Function('inputs', block.logic + '\nreturn run(inputs);');
|
|
236
263
|
const result = run({ input1: "Watch Input" });
|
|
237
264
|
console.log(chalk.green(`✔ Test Passed: ${result}`));
|
|
238
265
|
} catch (e) {
|
|
@@ -260,7 +287,7 @@ async function main() {
|
|
|
260
287
|
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
261
288
|
console.log(chalk.yellow(`Benchmarking: ${block.name} (100,000 iterations)...`));
|
|
262
289
|
try {
|
|
263
|
-
const run = new Function('inputs',
|
|
290
|
+
const run = new Function('inputs', block.logic + '\nreturn run(inputs);');
|
|
264
291
|
const start = performance.now();
|
|
265
292
|
for(let i=0; i<100000; i++) run({ input1: "bench" });
|
|
266
293
|
const end = performance.now();
|
|
@@ -291,13 +318,14 @@ async function main() {
|
|
|
291
318
|
console.log(chalk.white(`Available commands:`));
|
|
292
319
|
console.log(` ${chalk.bold('create [name]')} - Create a new block (file or directory)`);
|
|
293
320
|
console.log(` ${chalk.bold('build [dir]')} - Build a directory block into a .cbsblock`);
|
|
294
|
-
console.log(` ${chalk.bold('pack')} - Bundle
|
|
321
|
+
console.log(` ${chalk.bold('pack')} - Bundle workspace into professional .cbsext`);
|
|
295
322
|
console.log(` ${chalk.bold('init [name]')} - Initialize a new block project`);
|
|
296
323
|
console.log(` ${chalk.bold('test <file>')} - Run unit tests on a block`);
|
|
297
324
|
console.log(` ${chalk.bold('dev <file>')} - Watch for changes and re-test`);
|
|
298
325
|
console.log(` ${chalk.bold('search <query>')} - Search Marketplace from CLI`);
|
|
299
326
|
console.log(` ${chalk.bold('bench <file>')} - Benchmark block performance`);
|
|
300
327
|
console.log(` ${chalk.bold('site')} - Generate documentation website`);
|
|
328
|
+
console.log(` ${chalk.bold('tutorial')} - Open integrated developer guide`);
|
|
301
329
|
console.log(` ${chalk.bold('publish <file>')} - Publish block to CodeBlock Marketplace`);
|
|
302
330
|
console.log(` ${chalk.bold('version --bump')} - Bump patch version of package`);
|
|
303
331
|
console.log(` ${chalk.bold('doc <file>')} - Generate markdown documentation`);
|
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# {BLOCK_NAME} Extension
|
|
2
|
+
|
|
3
|
+
This is a professional CodeBlock Studio block extension.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
1. Customize the logic in `index.js`.
|
|
7
|
+
2. Update block metadata in `metadata.json`.
|
|
8
|
+
3. Build the block: `cbs-block build`.
|
|
9
|
+
4. Test the block: `cbs-block test`.
|
|
10
|
+
|
|
11
|
+
## Components
|
|
12
|
+
- `index.js`: The execution logic for your block.
|
|
13
|
+
- `metadata.json`: Defines the block's UI (color, ports, category).
|
|
14
|
+
- `package.json`: NPM manifest for dependencies.
|
|
15
|
+
- `tutorial.html`: Integrated developer guide.
|
|
16
|
+
|
|
17
|
+
## Publishing
|
|
18
|
+
When ready, run `cbs-block publish` to share your block on the CodeBlock Marketplace.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Developer Guide - {BLOCK_NAME}</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
|
8
|
+
<style>
|
|
9
|
+
:root { --primary: #4caf50; --accent: #1ed760; --bg: #0a0a0c; }
|
|
10
|
+
body { background: var(--bg); color: #e0e0e0; font-family: 'Outfit', sans-serif; line-height: 1.6; margin: 0; }
|
|
11
|
+
.container { max-width: 800px; margin: 4rem auto; padding: 0 2rem; }
|
|
12
|
+
.glass { background: rgba(255, 255, 255, 0.03); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 24px; padding: 2rem; box-shadow: 0 20px 40px rgba(0,0,0,0.4); }
|
|
13
|
+
h1 { font-size: 2.5rem; background: linear-gradient(45deg, var(--primary), var(--accent)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 0.5rem; }
|
|
14
|
+
.badge { display: inline-block; padding: 0.2rem 0.6rem; border-radius: 6px; background: var(--primary); color: #000; font-weight: 800; font-size: 0.7rem; text-transform: uppercase; margin-bottom: 2rem; }
|
|
15
|
+
pre { background: #000; padding: 1.2rem; border-radius: 12px; border: 1px solid rgba(255,255,255,0.1); overflow-x: auto; font-family: 'JetBrains Mono', monospace; font-size: 0.9rem; }
|
|
16
|
+
code { color: var(--accent); }
|
|
17
|
+
.step { margin-bottom: 2rem; }
|
|
18
|
+
.tip { padding: 1rem; background: rgba(76, 175, 80, 0.1); border-radius: 12px; border-left: 4px solid var(--primary); margin: 1rem 0; }
|
|
19
|
+
</style>
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<div class="container">
|
|
23
|
+
<div class="glass">
|
|
24
|
+
<div class="badge">Developer Guide</div>
|
|
25
|
+
<h1>Building {BLOCK_NAME}</h1>
|
|
26
|
+
<p>Welcome to your new CodeBlock Studio extension! This guide will help you build and test your block logic.</p>
|
|
27
|
+
|
|
28
|
+
<div class="step">
|
|
29
|
+
<h2>1. Writing Logic</h2>
|
|
30
|
+
<p>Open <code>index.js</code> and edit the <code>run</code> function. This function receives data from your block's input ports.</p>
|
|
31
|
+
<pre><code>function run(inputs) {
|
|
32
|
+
// Your logic here
|
|
33
|
+
return inputs.input1;
|
|
34
|
+
}</code></pre>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="step">
|
|
38
|
+
<h2>2. Building & Testing</h2>
|
|
39
|
+
<p>Run these commands in your terminal to see your changes in action:</p>
|
|
40
|
+
<pre><code>cbs-block build
|
|
41
|
+
cbs-block test myblock.cbsblock</code></pre>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="tip">
|
|
45
|
+
<strong>💡 PRO TIP:</strong> You can run <code>npm install <package></code> in this folder and use external libraries in your block logic!
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<footer style="margin-top: 4rem; opacity: 0.4; font-size: 0.8rem; text-align: center;">
|
|
49
|
+
© 2026 CodeBlock Studio SDK. Created with passion.
|
|
50
|
+
</footer>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</body>
|
|
54
|
+
</html>
|