cbs-block 1.0.1 → 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/bin/cbs-block.js +116 -76
- package/index.js +17 -2
- package/myblock.md +13 -0
- package/package.json +6 -2
package/bin/cbs-block.js
CHANGED
|
@@ -2,86 +2,126 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const inquirer = require('inquirer');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
const
|
|
9
|
+
async function main() {
|
|
10
|
+
const command = process.argv[2];
|
|
11
|
+
const target = process.argv[3];
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
console.log(chalk.cyan.bold(`\n--- CodeBlock Studio SDK v1.1.0 ---\n`));
|
|
10
14
|
|
|
11
|
-
if (command === 'create'
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{ name:
|
|
20
|
-
|
|
21
|
-
],
|
|
22
|
-
codeTemplates: {
|
|
23
|
-
python: "print({input1})",
|
|
24
|
-
web: "console.log({input1})"
|
|
25
|
-
},
|
|
26
|
-
logic: "function run(inputs) { return inputs.input1; }"
|
|
27
|
-
};
|
|
15
|
+
if (command === 'create') {
|
|
16
|
+
const answers = await inquirer.prompt([
|
|
17
|
+
{ type: 'input', name: 'name', message: 'Block name:', default: target || 'MyBlock' },
|
|
18
|
+
{ type: 'list', name: 'category', message: 'Category:', choices: ['Math', 'Logic', 'Control', 'Input', 'Output', 'Data', 'Custom'] },
|
|
19
|
+
{ type: 'input', name: 'color', message: 'Hex Color:', default: (a) => {
|
|
20
|
+
const colors = { 'Math': '#4A90E2', 'Logic': '#F5A623', 'Control': '#FFCC00', 'Custom': '#4CAF50' };
|
|
21
|
+
return colors[a.category] || '#4CAF50';
|
|
22
|
+
}},
|
|
23
|
+
{ type: 'confirm', name: 'hasFlow', message: 'Include flow ports?', default: true }
|
|
24
|
+
]);
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
26
|
+
const template = {
|
|
27
|
+
name: answers.name,
|
|
28
|
+
category: answers.category,
|
|
29
|
+
color: answers.color,
|
|
30
|
+
ports: [
|
|
31
|
+
...(answers.hasFlow ? [{ name: "flowIn", type: "FlowIn" }, { name: "flowOut", type: "FlowOut" }] : []),
|
|
32
|
+
{ name: "input1", type: "Input", dataType: "string" },
|
|
33
|
+
{ name: "output1", type: "Output", dataType: "string" }
|
|
34
|
+
],
|
|
35
|
+
codeTemplates: {
|
|
36
|
+
python: "print({input1})",
|
|
37
|
+
web: "console.log({input1})",
|
|
38
|
+
javascript: "console.log({input1})"
|
|
39
|
+
},
|
|
40
|
+
logic: "function run(inputs) { return inputs.input1; }"
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const fileName = `${answers.name.toLowerCase().replace(/\s+/g, '_')}.cbsblock`;
|
|
44
|
+
fs.writeFileSync(fileName, JSON.stringify(template, null, 2));
|
|
45
|
+
console.log(chalk.green(`\n✔ Successfully created block: ${chalk.bold(fileName)}`));
|
|
46
|
+
|
|
47
|
+
} else if (command === 'init') {
|
|
48
|
+
const answers = await inquirer.prompt([
|
|
49
|
+
{ type: 'input', name: 'projName', message: 'Project Name:', default: target || 'my-block-pack' },
|
|
50
|
+
{ type: 'input', name: 'description', message: 'Description:', default: 'A new CBS block package' }
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
fs.mkdirSync(answers.projName, { recursive: true });
|
|
54
|
+
const pkgPath = path.join(answers.projName, 'package.json');
|
|
55
|
+
fs.writeFileSync(pkgPath, JSON.stringify({
|
|
56
|
+
name: answers.projName,
|
|
57
|
+
version: "1.0.0",
|
|
58
|
+
description: answers.description,
|
|
59
|
+
dependencies: { "cbs-block": "latest" }
|
|
60
|
+
}, null, 2));
|
|
61
|
+
fs.mkdirSync(path.join(answers.projName, 'blocks'), { recursive: true });
|
|
62
|
+
console.log(chalk.green(`\n✔ Project ${chalk.bold(answers.projName)} initialized!`));
|
|
63
|
+
|
|
64
|
+
} else if (command === 'pack' || command === 'build') {
|
|
65
|
+
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
66
|
+
const pack = {
|
|
67
|
+
package: path.basename(process.cwd()),
|
|
68
|
+
version: "1.0.0",
|
|
69
|
+
blocks: files.map(f => JSON.parse(fs.readFileSync(f, 'utf8')))
|
|
70
|
+
};
|
|
71
|
+
const packName = `${pack.package}.cbspak`;
|
|
72
|
+
fs.writeFileSync(packName, JSON.stringify(pack, null, 2));
|
|
73
|
+
console.log(chalk.green(`\n✔ Packed ${files.length} blocks into ${chalk.bold(packName)}`));
|
|
74
|
+
|
|
75
|
+
} else if (command === 'doc' && target) {
|
|
76
|
+
if (!fs.existsSync(target)) return console.error(chalk.red(`Error: File ${target} not found.`));
|
|
77
|
+
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
78
|
+
const doc = `# Block: ${block.name}\n\n**Category**: ${block.category}\n**Color**: \`${block.color}\`\n\n## Ports\n${block.ports.map(p => `- **${p.name}** (${p.type})`).join('\n')}\n\n## Code Templates\n\`\`\`python\n${block.codeTemplates.python}\n\`\`\``;
|
|
79
|
+
const outName = target.replace('.cbsblock', '.md');
|
|
80
|
+
fs.writeFileSync(outName, doc);
|
|
81
|
+
console.log(chalk.green(`\n✔ Generated documentation: ${chalk.bold(outName)}`));
|
|
82
|
+
|
|
83
|
+
} else if (command === 'link') {
|
|
84
|
+
const mainAppPath = path.resolve('../../../codebl/blocks');
|
|
85
|
+
if (fs.existsSync(mainAppPath)) {
|
|
86
|
+
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
87
|
+
files.forEach(f => {
|
|
88
|
+
fs.copyFileSync(f, path.join(mainAppPath, f));
|
|
89
|
+
});
|
|
90
|
+
console.log(chalk.green(`\n✔ Linked ${files.length} blocks to main app at ${mainAppPath}`));
|
|
91
|
+
} else {
|
|
92
|
+
console.error(chalk.red(`Error: Could not find main app blocks directory at ${mainAppPath}`));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
} else if (command === 'status') {
|
|
96
|
+
console.log(chalk.yellow(`Current Project: ${path.basename(process.cwd())}`));
|
|
97
|
+
const blocks = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock')).length;
|
|
98
|
+
console.log(`Blocks found: ${blocks}`);
|
|
99
|
+
try {
|
|
100
|
+
const qtV = execSync('qmake -v').toString().split('\n')[0];
|
|
101
|
+
console.log(chalk.green(`[PASS] Environment: ${qtV}`));
|
|
102
|
+
} catch {
|
|
103
|
+
console.log(chalk.red(`[FAIL] Qt/qmake not found in PATH`));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
} else if (command === 'lint') {
|
|
107
|
+
const sdk = require('../index.js');
|
|
108
|
+
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
109
|
+
files.forEach(f => {
|
|
110
|
+
const data = JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
111
|
+
const result = sdk.validate(data);
|
|
112
|
+
if (result.valid) console.log(chalk.green(`${f}: VALID`));
|
|
113
|
+
else console.error(chalk.red(`${f}: INVALID - ${result.error}`));
|
|
114
|
+
});
|
|
54
115
|
} else {
|
|
55
|
-
console.log(
|
|
116
|
+
console.log(chalk.white(`Available commands:`));
|
|
117
|
+
console.log(` ${chalk.bold('create [name]')} - Create a new block interactively`);
|
|
118
|
+
console.log(` ${chalk.bold('init [name]')} - Initialize a new project`);
|
|
119
|
+
console.log(` ${chalk.bold('pack')} - Build a .cbspak package`);
|
|
120
|
+
console.log(` ${chalk.bold('doc <file>')} - Generate markdown documentation`);
|
|
121
|
+
console.log(` ${chalk.bold('link')} - Link blocks to main CodeBlock Studio app`);
|
|
122
|
+
console.log(` ${chalk.bold('lint')} - Validate block definitions`);
|
|
123
|
+
console.log(` ${chalk.bold('status')} - Show SDK & environment status`);
|
|
56
124
|
}
|
|
57
|
-
} else if (command === 'init' && name) {
|
|
58
|
-
fs.mkdirSync(name);
|
|
59
|
-
process.chdir(name);
|
|
60
|
-
fs.writeFileSync('package.json', JSON.stringify({ name, version: "1.0.0", dependencies: { "cbs-block": "latest" } }, null, 2));
|
|
61
|
-
fs.mkdirSync('blocks');
|
|
62
|
-
console.log(`Project ${name} initialized!`);
|
|
63
|
-
} else if (command === 'lint') {
|
|
64
|
-
const sdk = require('../index.js');
|
|
65
|
-
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
66
|
-
files.forEach(f => {
|
|
67
|
-
const data = JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
68
|
-
if (sdk.validate(data)) console.log(`${f}: VALID`);
|
|
69
|
-
else console.error(`${f}: INVALID (Missing required fields)`);
|
|
70
|
-
});
|
|
71
|
-
} else if (command === 'serve') {
|
|
72
|
-
const http = require('http');
|
|
73
|
-
const server = http.createServer((req, res) => {
|
|
74
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
75
|
-
const blocks = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
76
|
-
res.end(JSON.stringify(blocks.map(f => JSON.parse(fs.readFileSync(f, 'utf8')))));
|
|
77
|
-
});
|
|
78
|
-
server.listen(8080, () => console.log("Dev server running at http://localhost:8080"));
|
|
79
|
-
} else {
|
|
80
|
-
console.log("Usage:");
|
|
81
|
-
console.log(" cbs-block init <ProjectName>");
|
|
82
|
-
console.log(" cbs-block create <BlockName>");
|
|
83
|
-
console.log(" cbs-block lint");
|
|
84
|
-
console.log(" cbs-block pack");
|
|
85
|
-
console.log(" cbs-block publish");
|
|
86
|
-
console.log(" cbs-block serve");
|
|
87
125
|
}
|
|
126
|
+
|
|
127
|
+
main().catch(err => console.error(chalk.red(`Error: ${err.message}`)));
|
package/index.js
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
validate: function(block) {
|
|
3
|
-
|
|
3
|
+
const hasRequired = block.name && block.logic && block.codeTemplates && Array.isArray(block.ports);
|
|
4
|
+
if (!hasRequired) return { valid: false, error: "Missing required fields (name, logic, codeTemplates, ports)" };
|
|
5
|
+
|
|
6
|
+
// Color validation
|
|
7
|
+
if (block.color && !/^#[0-9A-F]{6}$/i.test(block.color)) {
|
|
8
|
+
return { valid: false, error: "Invalid hex color format" };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Port validation
|
|
12
|
+
const portNames = new Set();
|
|
13
|
+
for (const p of block.ports) {
|
|
14
|
+
if (portNames.has(p.name)) return { valid: false, error: `Duplicate port name: ${p.name}` };
|
|
15
|
+
portNames.add(p.name);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return { valid: true };
|
|
4
19
|
},
|
|
5
|
-
version: "1.
|
|
20
|
+
version: "1.1.0"
|
|
6
21
|
};
|
package/myblock.md
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cbs-block",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "SDK for creating CodeBlock Studio blocks",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -15,5 +15,9 @@
|
|
|
15
15
|
"visual-programming"
|
|
16
16
|
],
|
|
17
17
|
"author": "CBS Team",
|
|
18
|
-
"license": "MIT"
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"chalk": "^4.1.2",
|
|
21
|
+
"inquirer": "^13.3.2"
|
|
22
|
+
}
|
|
19
23
|
}
|