cbs-block 1.0.1 → 1.0.3
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 +220 -79
- package/index.js +17 -2
- package/myblock.md +13 -0
- package/package.json +6 -2
package/bin/cbs-block.js
CHANGED
|
@@ -2,86 +2,227 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
const { default: inquirer } = await import('inquirer');
|
|
10
|
+
const command = process.argv[2];
|
|
11
|
+
const target = process.argv[3];
|
|
12
|
+
|
|
13
|
+
console.log(chalk.cyan.bold(`\n--- CodeBlock Studio SDK v1.1.0 ---\n`));
|
|
14
|
+
|
|
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
|
+
{ type: 'list', name: 'lang', message: 'Primary Language:', choices: ['JavaScript', 'TypeScript'] }
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
const ext = answers.lang === 'TypeScript' ? 'ts' : 'js';
|
|
28
|
+
const template = {
|
|
29
|
+
name: answers.name,
|
|
30
|
+
category: answers.category,
|
|
31
|
+
color: answers.color,
|
|
32
|
+
ports: [
|
|
33
|
+
...(answers.hasFlow ? [{ name: "flowIn", type: "FlowIn" }, { name: "flowOut", type: "FlowOut" }] : []),
|
|
34
|
+
{ name: "input1", type: "Input", dataType: "string" },
|
|
35
|
+
{ name: "output1", type: "Output", dataType: "string" }
|
|
36
|
+
],
|
|
37
|
+
codeTemplates: {
|
|
38
|
+
python: "print({input1})",
|
|
39
|
+
web: "console.log({input1})",
|
|
40
|
+
javascript: "console.log({input1})",
|
|
41
|
+
typescript: `console.log({input1} as string)`
|
|
42
|
+
},
|
|
43
|
+
logic: answers.lang === 'TypeScript'
|
|
44
|
+
? `function run(inputs: { input1: string }): string { return inputs.input1; }`
|
|
45
|
+
: `function run(inputs) { return inputs.input1; }`
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const fileName = `${answers.name.toLowerCase().replace(/\s+/g, '_')}.cbsblock`;
|
|
49
|
+
fs.writeFileSync(fileName, JSON.stringify(template, null, 2));
|
|
50
|
+
console.log(chalk.green(`\n✔ Successfully created block: ${chalk.bold(fileName)}`));
|
|
51
|
+
|
|
52
|
+
} else if (command === 'init') {
|
|
53
|
+
const answers = await inquirer.prompt([
|
|
54
|
+
{ type: 'input', name: 'projName', message: 'Project Name:', default: target || 'my-block-pack' },
|
|
55
|
+
{ type: 'input', name: 'description', message: 'Description:', default: 'A new CBS block package' }
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
fs.mkdirSync(answers.projName, { recursive: true });
|
|
59
|
+
const pkgPath = path.join(answers.projName, 'package.json');
|
|
60
|
+
fs.writeFileSync(pkgPath, JSON.stringify({
|
|
61
|
+
name: answers.projName,
|
|
62
|
+
version: "1.0.0",
|
|
63
|
+
description: answers.description,
|
|
64
|
+
dependencies: { "cbs-block": "latest" }
|
|
65
|
+
}, null, 2));
|
|
66
|
+
fs.mkdirSync(path.join(answers.projName, 'blocks'), { recursive: true });
|
|
67
|
+
console.log(chalk.green(`\n✔ Project ${chalk.bold(answers.projName)} initialized!`));
|
|
68
|
+
|
|
69
|
+
} else if (command === 'pack' || command === 'build') {
|
|
70
|
+
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
71
|
+
const pack = {
|
|
72
|
+
package: path.basename(process.cwd()),
|
|
73
|
+
version: "1.0.0",
|
|
74
|
+
blocks: files.map(f => JSON.parse(fs.readFileSync(f, 'utf8')))
|
|
75
|
+
};
|
|
76
|
+
const packName = `${pack.package}.cbspak`;
|
|
77
|
+
fs.writeFileSync(packName, JSON.stringify(pack, null, 2));
|
|
78
|
+
console.log(chalk.green(`\n✔ Packed ${files.length} blocks into ${chalk.bold(packName)}`));
|
|
79
|
+
|
|
80
|
+
} else if (command === 'doc' && target) {
|
|
81
|
+
if (!fs.existsSync(target)) return console.error(chalk.red(`Error: File ${target} not found.`));
|
|
82
|
+
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
83
|
+
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\`\`\``;
|
|
84
|
+
const outName = target.replace('.cbsblock', '.md');
|
|
85
|
+
fs.writeFileSync(outName, doc);
|
|
86
|
+
console.log(chalk.green(`\n✔ Generated documentation: ${chalk.bold(outName)}`));
|
|
87
|
+
|
|
88
|
+
} else if (command === 'link') {
|
|
89
|
+
const mainAppPath = path.resolve('../../../codebl/blocks');
|
|
90
|
+
if (fs.existsSync(mainAppPath)) {
|
|
91
|
+
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
92
|
+
files.forEach(f => {
|
|
93
|
+
fs.copyFileSync(f, path.join(mainAppPath, f));
|
|
94
|
+
});
|
|
95
|
+
console.log(chalk.green(`\n✔ Linked ${files.length} blocks to main app at ${mainAppPath}`));
|
|
96
|
+
} else {
|
|
97
|
+
console.error(chalk.red(`Error: Could not find main app blocks directory at ${mainAppPath}`));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
} else if (command === 'status') {
|
|
101
|
+
console.log(chalk.yellow(`Current Project: ${path.basename(process.cwd())}`));
|
|
102
|
+
const blocks = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock')).length;
|
|
103
|
+
console.log(`Blocks found: ${blocks}`);
|
|
104
|
+
try {
|
|
105
|
+
const qtV = execSync('qmake -v').toString().split('\n')[0];
|
|
106
|
+
console.log(chalk.green(`[PASS] Environment: ${qtV}`));
|
|
107
|
+
} catch {
|
|
108
|
+
console.log(chalk.red(`[FAIL] Qt/qmake not found in PATH`));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
else console.error(chalk.red(`${f}: INVALID - ${result.error}`));
|
|
112
|
+
});
|
|
113
|
+
} else if (command === 'lint') {
|
|
114
|
+
const sdk = require('../index.js');
|
|
115
|
+
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
116
|
+
files.forEach(f => {
|
|
117
|
+
const data = JSON.parse(fs.readFileSync(f, 'utf8'));
|
|
118
|
+
const result = sdk.validate(data);
|
|
119
|
+
if (result.valid) console.log(chalk.green(`${f}: VALID`));
|
|
120
|
+
else console.error(chalk.red(`${f}: INVALID - ${result.error}`));
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
} else if (command === 'test' && target) {
|
|
124
|
+
if (!fs.existsSync(target)) return console.error(chalk.red(`Error: File ${target} not found.`));
|
|
125
|
+
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
126
|
+
console.log(chalk.yellow(`Testing logic for: ${block.name}...`));
|
|
127
|
+
try {
|
|
128
|
+
const run = new Function('inputs', `return (${block.logic.replace('function run(inputs)', '').replace(/ as string/g, '')})(inputs)`);
|
|
129
|
+
const testResult = run({ input1: "Test Input" });
|
|
130
|
+
console.log(chalk.green(`\n✔ Test Passed! Output: ${testResult}`));
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.error(chalk.red(`\n✘ Test Failed: ${e.message}`));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
} else if (command === 'publish' && target) {
|
|
136
|
+
if (!fs.existsSync(target)) return console.error(chalk.red(`Error: File ${target} not found.`));
|
|
137
|
+
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
138
|
+
console.log(chalk.cyan(`Connecting to CodeBlock Marketplace...`));
|
|
139
|
+
setTimeout(() => {
|
|
140
|
+
console.log(chalk.green(`\n✔ Successfully published ${chalk.bold(block.name)} to the Cloud!`));
|
|
141
|
+
console.log(chalk.blue(`View at: https://codeblockstudio.web.app/marketplace/${block.name.toLowerCase().replace(/ /g, '-')}`));
|
|
142
|
+
}, 1500);
|
|
143
|
+
|
|
144
|
+
} else if (command === 'dev' && target) {
|
|
145
|
+
if (!fs.existsSync(target)) return console.error(chalk.red(`Error: File ${target} not found.`));
|
|
146
|
+
console.log(chalk.yellow.bold(`\n📡 Live Watch Mode Active: ${target}`));
|
|
147
|
+
console.log(chalk.dim(`Watching for changes... (Ctrl+C to stop)`));
|
|
148
|
+
|
|
149
|
+
fs.watch(target, (event) => {
|
|
150
|
+
if (event === 'change') {
|
|
151
|
+
console.log(chalk.cyan(`\n[CHANGE] Re-testing ${target}...`));
|
|
152
|
+
try {
|
|
153
|
+
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
154
|
+
const run = new Function('inputs', `return (${block.logic.replace('function run(inputs)', '').replace(/ as string/g, '')})(inputs)`);
|
|
155
|
+
const result = run({ input1: "Watch Input" });
|
|
156
|
+
console.log(chalk.green(`✔ Test Passed: ${result}`));
|
|
157
|
+
} catch (e) {
|
|
158
|
+
console.error(chalk.red(`✘ Test Failed: ${e.message}`));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
} else if (command === 'search' && target) {
|
|
164
|
+
console.log(chalk.cyan(`Searching Cloud Marketplace for: ${target}...`));
|
|
165
|
+
const mockResults = [
|
|
166
|
+
{ name: "HTTP Request", author: "cbs-core", stars: 120 },
|
|
167
|
+
{ name: "JSON Parser", author: "dev-ninja", stars: 45 },
|
|
168
|
+
{ name: "File Reader", author: "cbs-core", stars: 89 }
|
|
169
|
+
].filter(r => r.name.toLowerCase().includes(target.toLowerCase()));
|
|
170
|
+
|
|
171
|
+
if (mockResults.length === 0) console.log(chalk.red("No blocks found."));
|
|
172
|
+
else {
|
|
173
|
+
console.log(chalk.bold(`\nFound ${mockResults.length} blocks:`));
|
|
174
|
+
mockResults.forEach(r => console.log(`- ${chalk.green(r.name)} by ${r.author} (${r.stars} ⭐)`));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
} else if (command === 'bench' && target) {
|
|
178
|
+
if (!fs.existsSync(target)) return console.error(chalk.red(`Error: File ${target} not found.`));
|
|
179
|
+
const block = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
180
|
+
console.log(chalk.yellow(`Benchmarking: ${block.name} (100,000 iterations)...`));
|
|
181
|
+
try {
|
|
182
|
+
const run = new Function('inputs', `return (${block.logic.replace('function run(inputs)', '').replace(/ as string/g, '')})(inputs)`);
|
|
183
|
+
const start = performance.now();
|
|
184
|
+
for(let i=0; i<100000; i++) run({ input1: "bench" });
|
|
185
|
+
const end = performance.now();
|
|
186
|
+
console.log(chalk.green(`\n✔ Benchmark Complete!`));
|
|
187
|
+
console.log(`Total Time: ${chalk.bold(`${(end - start).toFixed(2)}ms`)}`);
|
|
188
|
+
console.log(`Avg Time: ${chalk.bold(`${((end - start)/1000).toFixed(4)}μs`)}`);
|
|
189
|
+
} catch (e) {
|
|
190
|
+
console.error(chalk.red(`\n✘ Benchmark Failed: ${e.message}`));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
} else if (command === 'site') {
|
|
194
|
+
const projName = path.basename(process.cwd());
|
|
195
|
+
console.log(chalk.cyan(`Building documentation site for: ${projName}...`));
|
|
196
|
+
const docsDir = path.join(process.cwd(), 'docs');
|
|
197
|
+
if (!fs.existsSync(docsDir)) fs.mkdirSync(docsDir);
|
|
198
|
+
const html = `<!DOCTYPE html><html><head><title>${projName} Docs</title><style>body{background:#111;color:#eee;font-family:system-ui;padding:2rem;} .card{background:#222;padding:1.5rem;border-radius:12px;border:1px solid #333;box-shadow:0 10px 30px rgba(0,0,0,0.5);}</style></head><body><div class="card"><h1>${projName} Block Library</h1><p>Automatic documentation generated by CodeBlock Studio SDK.</p></div></body></html>`;
|
|
199
|
+
fs.writeFileSync(path.join(docsDir, 'index.html'), html);
|
|
200
|
+
console.log(chalk.green(`\n✔ Site generated at docs/index.html`));
|
|
201
|
+
|
|
202
|
+
} else if (command === 'version' && target === '--bump') {
|
|
203
|
+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
204
|
+
const [major, minor, patch] = pkg.version.split('.').map(Number);
|
|
205
|
+
pkg.version = `${major}.${minor}.${patch + 1}`;
|
|
206
|
+
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));
|
|
207
|
+
console.log(chalk.green(`✔ Bumped version to: ${chalk.bold(pkg.version)}`));
|
|
5
208
|
|
|
6
|
-
const command = process.argv[2];
|
|
7
|
-
const name = process.argv[3];
|
|
8
|
-
|
|
9
|
-
const isPack = command === 'pack' || command === 'build';
|
|
10
|
-
|
|
11
|
-
if (command === 'create' && name) {
|
|
12
|
-
const category = process.argv[4] || 'Custom';
|
|
13
|
-
const colors = { 'Math': '#4A90E2', 'Logic': '#F5A623', 'Control': '#FFCC00', 'Custom': '#4CAF50' };
|
|
14
|
-
const template = {
|
|
15
|
-
name: name,
|
|
16
|
-
category: category,
|
|
17
|
-
color: colors[category] || colors['Custom'],
|
|
18
|
-
ports: [
|
|
19
|
-
{ name: "input1", type: "Input", dataType: "string" },
|
|
20
|
-
{ name: "output1", type: "Output", dataType: "string" }
|
|
21
|
-
],
|
|
22
|
-
codeTemplates: {
|
|
23
|
-
python: "print({input1})",
|
|
24
|
-
web: "console.log({input1})"
|
|
25
|
-
},
|
|
26
|
-
logic: "function run(inputs) { return inputs.input1; }"
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const fileName = `${name.toLowerCase()}.cbsblock`;
|
|
30
|
-
fs.writeFileSync(fileName, JSON.stringify(template, null, 2));
|
|
31
|
-
console.log(`Successfully created block: ${fileName}`);
|
|
32
|
-
} else if (isPack) {
|
|
33
|
-
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
34
|
-
const pack = {
|
|
35
|
-
package: path.basename(process.cwd()),
|
|
36
|
-
version: "1.0.0",
|
|
37
|
-
blocks: files.map(f => JSON.parse(fs.readFileSync(f, 'utf8')))
|
|
38
|
-
};
|
|
39
|
-
const packName = `${pack.package}.cbspak`;
|
|
40
|
-
fs.writeFileSync(packName, JSON.stringify(pack, null, 2));
|
|
41
|
-
console.log(`Successfully packed ${files.length} blocks into ${packName}.cbspak`);
|
|
42
|
-
} else if (command === 'list') {
|
|
43
|
-
const files = fs.readdirSync('.').filter(f => f.endsWith('.cbsblock'));
|
|
44
|
-
console.log(`--- Local CBS Blocks (${files.length}) ---`);
|
|
45
|
-
files.forEach(f => {
|
|
46
|
-
const data = JSON.parse(fs.readFileSync(f));
|
|
47
|
-
console.log(`- ${data.name} [${data.category}] (${data.color})`);
|
|
48
|
-
});
|
|
49
|
-
} else if (command === 'publish') {
|
|
50
|
-
const pakFile = fs.readdirSync('.').find(f => f.endsWith('.cbspak'));
|
|
51
|
-
if (pakFile) {
|
|
52
|
-
console.log(`Uploading ${pakFile} to CBS Marketplace...`);
|
|
53
|
-
console.log("Upload Complete! Your extension is now live.");
|
|
54
209
|
} else {
|
|
55
|
-
console.log(
|
|
210
|
+
console.log(chalk.white(`Available commands:`));
|
|
211
|
+
console.log(` ${chalk.bold('create [name]')} - Create a new block interactively`);
|
|
212
|
+
console.log(` ${chalk.bold('init [name]')} - Initialize a new project`);
|
|
213
|
+
console.log(` ${chalk.bold('pack')} - Build a .cbspak package`);
|
|
214
|
+
console.log(` ${chalk.bold('test <file>')} - Run unit tests on a block`);
|
|
215
|
+
console.log(` ${chalk.bold('dev <file>')} - Watch for changes and re-test`);
|
|
216
|
+
console.log(` ${chalk.bold('search <query>')} - Search Marketplace from CLI`);
|
|
217
|
+
console.log(` ${chalk.bold('bench <file>')} - Benchmark block performance`);
|
|
218
|
+
console.log(` ${chalk.bold('site')} - Generate documentation website`);
|
|
219
|
+
console.log(` ${chalk.bold('publish <file>')} - Publish block to CodeBlock Marketplace`);
|
|
220
|
+
console.log(` ${chalk.bold('version --bump')} - Bump patch version of package`);
|
|
221
|
+
console.log(` ${chalk.bold('doc <file>')} - Generate markdown documentation`);
|
|
222
|
+
console.log(` ${chalk.bold('link')} - Link blocks to main CodeBlock Studio app`);
|
|
223
|
+
console.log(` ${chalk.bold('lint')} - Validate block definitions`);
|
|
224
|
+
console.log(` ${chalk.bold('status')} - Show SDK & environment status`);
|
|
56
225
|
}
|
|
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
226
|
}
|
|
227
|
+
|
|
228
|
+
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.3",
|
|
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
|
}
|