@bsb/base 9.0.0
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/LICENSE +665 -0
- package/LICENSE.commercial +32 -0
- package/README.md +263 -0
- package/bsb-plugin.json +62 -0
- package/lib/base/BSBConfig.d.ts +130 -0
- package/lib/base/BSBConfig.js +95 -0
- package/lib/base/BSBConfig.js.map +1 -0
- package/lib/base/BSBEvents.d.ts +207 -0
- package/lib/base/BSBEvents.js +101 -0
- package/lib/base/BSBEvents.js.map +1 -0
- package/lib/base/BSBObservable.d.ts +178 -0
- package/lib/base/BSBObservable.js +91 -0
- package/lib/base/BSBObservable.js.map +1 -0
- package/lib/base/BSBService.d.ts +277 -0
- package/lib/base/BSBService.js +366 -0
- package/lib/base/BSBService.js.map +1 -0
- package/lib/base/BSBServiceClient.d.ts +135 -0
- package/lib/base/BSBServiceClient.js +130 -0
- package/lib/base/BSBServiceClient.js.map +1 -0
- package/lib/base/EventValidator.d.ts +137 -0
- package/lib/base/EventValidator.js +210 -0
- package/lib/base/EventValidator.js.map +1 -0
- package/lib/base/ObservableBackend.d.ts +281 -0
- package/lib/base/ObservableBackend.js +515 -0
- package/lib/base/ObservableBackend.js.map +1 -0
- package/lib/base/PluginConfig.d.ts +196 -0
- package/lib/base/PluginConfig.js +96 -0
- package/lib/base/PluginConfig.js.map +1 -0
- package/lib/base/PluginEvents.d.ts +140 -0
- package/lib/base/PluginEvents.js +268 -0
- package/lib/base/PluginEvents.js.map +1 -0
- package/lib/base/PluginObservable.d.ts +196 -0
- package/lib/base/PluginObservable.js +250 -0
- package/lib/base/PluginObservable.js.map +1 -0
- package/lib/base/ResourceContext.d.ts +70 -0
- package/lib/base/ResourceContext.js +54 -0
- package/lib/base/ResourceContext.js.map +1 -0
- package/lib/base/base.d.ts +264 -0
- package/lib/base/base.js +182 -0
- package/lib/base/base.js.map +1 -0
- package/lib/base/errorMessages.d.ts +56 -0
- package/lib/base/errorMessages.js +70 -0
- package/lib/base/errorMessages.js.map +1 -0
- package/lib/base/factory.d.ts +58 -0
- package/lib/base/factory.js +167 -0
- package/lib/base/factory.js.map +1 -0
- package/lib/base/functions.d.ts +117 -0
- package/lib/base/functions.js +152 -0
- package/lib/base/functions.js.map +1 -0
- package/lib/base/index.d.ts +44 -0
- package/lib/base/index.js +64 -0
- package/lib/base/index.js.map +1 -0
- package/lib/base/logFormatter.d.ts +50 -0
- package/lib/base/logFormatter.js +105 -0
- package/lib/base/logFormatter.js.map +1 -0
- package/lib/base/tools.d.ts +316 -0
- package/lib/base/tools.js +666 -0
- package/lib/base/tools.js.map +1 -0
- package/lib/cli.d.ts +28 -0
- package/lib/cli.js +254 -0
- package/lib/cli.js.map +1 -0
- package/lib/dev.d.ts +27 -0
- package/lib/dev.js +200 -0
- package/lib/dev.js.map +1 -0
- package/lib/index.d.ts +32 -0
- package/lib/index.js +49 -0
- package/lib/index.js.map +1 -0
- package/lib/interfaces/events.d.ts +67 -0
- package/lib/interfaces/events.js +44 -0
- package/lib/interfaces/events.js.map +1 -0
- package/lib/interfaces/index.d.ts +38 -0
- package/lib/interfaces/index.js +59 -0
- package/lib/interfaces/index.js.map +1 -0
- package/lib/interfaces/logging.d.ts +106 -0
- package/lib/interfaces/logging.js +39 -0
- package/lib/interfaces/logging.js.map +1 -0
- package/lib/interfaces/metrics.d.ts +365 -0
- package/lib/interfaces/metrics.js +46 -0
- package/lib/interfaces/metrics.js.map +1 -0
- package/lib/interfaces/observable-types.d.ts +63 -0
- package/lib/interfaces/observable-types.js +49 -0
- package/lib/interfaces/observable-types.js.map +1 -0
- package/lib/interfaces/observable.d.ts +297 -0
- package/lib/interfaces/observable.js +29 -0
- package/lib/interfaces/observable.js.map +1 -0
- package/lib/interfaces/options.d.ts +164 -0
- package/lib/interfaces/options.js +56 -0
- package/lib/interfaces/options.js.map +1 -0
- package/lib/interfaces/plugins.d.ts +143 -0
- package/lib/interfaces/plugins.js +45 -0
- package/lib/interfaces/plugins.js.map +1 -0
- package/lib/interfaces/result.d.ts +129 -0
- package/lib/interfaces/result.js +162 -0
- package/lib/interfaces/result.js.map +1 -0
- package/lib/interfaces/schema-events.d.ts +378 -0
- package/lib/interfaces/schema-events.js +247 -0
- package/lib/interfaces/schema-events.js.map +1 -0
- package/lib/interfaces/schema-types.d.ts +407 -0
- package/lib/interfaces/schema-types.js +581 -0
- package/lib/interfaces/schema-types.js.map +1 -0
- package/lib/interfaces/service.d.ts +48 -0
- package/lib/interfaces/service.js +29 -0
- package/lib/interfaces/service.js.map +1 -0
- package/lib/interfaces/tools.d.ts +65 -0
- package/lib/interfaces/tools.js +50 -0
- package/lib/interfaces/tools.js.map +1 -0
- package/lib/plugins/config-default/index.d.ts +59 -0
- package/lib/plugins/config-default/index.js +197 -0
- package/lib/plugins/config-default/index.js.map +1 -0
- package/lib/plugins/config-default/interfaces.d.ts +92 -0
- package/lib/plugins/config-default/interfaces.js +36 -0
- package/lib/plugins/config-default/interfaces.js.map +1 -0
- package/lib/plugins/events-default/events/broadcast.d.ts +36 -0
- package/lib/plugins/events-default/events/broadcast.js +85 -0
- package/lib/plugins/events-default/events/broadcast.js.map +1 -0
- package/lib/plugins/events-default/events/emit.d.ts +38 -0
- package/lib/plugins/events-default/events/emit.js +104 -0
- package/lib/plugins/events-default/events/emit.js.map +1 -0
- package/lib/plugins/events-default/events/emitAndReturn.d.ts +36 -0
- package/lib/plugins/events-default/events/emitAndReturn.js +100 -0
- package/lib/plugins/events-default/events/emitAndReturn.js.map +1 -0
- package/lib/plugins/events-default/events/emitStreamAndReceiveStream.d.ts +38 -0
- package/lib/plugins/events-default/events/emitStreamAndReceiveStream.js +134 -0
- package/lib/plugins/events-default/events/emitStreamAndReceiveStream.js.map +1 -0
- package/lib/plugins/events-default/events/index.d.ts +30 -0
- package/lib/plugins/events-default/events/index.js +38 -0
- package/lib/plugins/events-default/events/index.js.map +1 -0
- package/lib/plugins/events-default/index.d.ts +57 -0
- package/lib/plugins/events-default/index.js +86 -0
- package/lib/plugins/events-default/index.js.map +1 -0
- package/lib/plugins/observable-default/index.d.ts +43 -0
- package/lib/plugins/observable-default/index.js +151 -0
- package/lib/plugins/observable-default/index.js.map +1 -0
- package/lib/schemas/config-default.json +34 -0
- package/lib/schemas/config-default.plugin.json +36 -0
- package/lib/schemas/events-default.json +18 -0
- package/lib/schemas/events-default.plugin.json +17 -0
- package/lib/schemas/observable-default.json +33 -0
- package/lib/schemas/observable-default.plugin.json +24 -0
- package/lib/scripts/bsb-client-cli.d.ts +21 -0
- package/lib/scripts/bsb-client-cli.js +701 -0
- package/lib/scripts/bsb-client-cli.js.map +1 -0
- package/lib/scripts/bsb-plugin-cli.d.ts +15 -0
- package/lib/scripts/bsb-plugin-cli.js +547 -0
- package/lib/scripts/bsb-plugin-cli.js.map +1 -0
- package/lib/scripts/export-schemas.d.ts +17 -0
- package/lib/scripts/export-schemas.js +205 -0
- package/lib/scripts/export-schemas.js.map +1 -0
- package/lib/scripts/extract-schemas-from-source.d.ts +23 -0
- package/lib/scripts/extract-schemas-from-source.js +604 -0
- package/lib/scripts/extract-schemas-from-source.js.map +1 -0
- package/lib/scripts/generate-client-types.d.ts +22 -0
- package/lib/scripts/generate-client-types.js +537 -0
- package/lib/scripts/generate-client-types.js.map +1 -0
- package/lib/scripts/generate-plugin-json.d.ts +17 -0
- package/lib/scripts/generate-plugin-json.js +219 -0
- package/lib/scripts/generate-plugin-json.js.map +1 -0
- package/lib/serviceBase/config.d.ts +83 -0
- package/lib/serviceBase/config.js +236 -0
- package/lib/serviceBase/config.js.map +1 -0
- package/lib/serviceBase/events.d.ts +91 -0
- package/lib/serviceBase/events.js +519 -0
- package/lib/serviceBase/events.js.map +1 -0
- package/lib/serviceBase/index.d.ts +33 -0
- package/lib/serviceBase/index.js +50 -0
- package/lib/serviceBase/index.js.map +1 -0
- package/lib/serviceBase/observable.d.ts +249 -0
- package/lib/serviceBase/observable.js +551 -0
- package/lib/serviceBase/observable.js.map +1 -0
- package/lib/serviceBase/plugins.d.ts +48 -0
- package/lib/serviceBase/plugins.js +184 -0
- package/lib/serviceBase/plugins.js.map +1 -0
- package/lib/serviceBase/serviceBase.d.ts +228 -0
- package/lib/serviceBase/serviceBase.js +420 -0
- package/lib/serviceBase/serviceBase.js.map +1 -0
- package/lib/serviceBase/services.d.ts +63 -0
- package/lib/serviceBase/services.js +346 -0
- package/lib/serviceBase/services.js.map +1 -0
- package/lib/tests.d.ts +27 -0
- package/lib/tests.js +44 -0
- package/lib/tests.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,701 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* BSB Client CLI
|
|
5
|
+
*
|
|
6
|
+
* Commands for interacting with BSB Registry.
|
|
7
|
+
* Provides plugin publishing, searching, and discovery.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* bsb-client list - List all plugins from registry
|
|
11
|
+
* bsb-client search <query> - Search plugins
|
|
12
|
+
* bsb-client publish - Publish current plugin(s) to registry
|
|
13
|
+
* bsb-client schema <name> - Get plugin event schema
|
|
14
|
+
* bsb-client info <name> - Get plugin details
|
|
15
|
+
* bsb-client install <name> - Download schema and generate types
|
|
16
|
+
* bsb-client token generate - Generate a new API token
|
|
17
|
+
*
|
|
18
|
+
* Environment:
|
|
19
|
+
* BSB_REGISTRY_URL - Registry URL (default: https://registry.bsbcode.dev)
|
|
20
|
+
* BSB_REGISTRY_TOKEN - API token for authentication
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
const fs = require("fs");
|
|
24
|
+
const path = require("path");
|
|
25
|
+
const https = require("https");
|
|
26
|
+
const http = require("http");
|
|
27
|
+
// Colors for terminal output
|
|
28
|
+
const colors = {
|
|
29
|
+
reset: '\x1b[0m',
|
|
30
|
+
bright: '\x1b[1m',
|
|
31
|
+
red: '\x1b[31m',
|
|
32
|
+
green: '\x1b[32m',
|
|
33
|
+
yellow: '\x1b[33m',
|
|
34
|
+
blue: '\x1b[34m',
|
|
35
|
+
cyan: '\x1b[36m',
|
|
36
|
+
};
|
|
37
|
+
function log(message, color = 'reset') {
|
|
38
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
39
|
+
}
|
|
40
|
+
function error(message) {
|
|
41
|
+
log(`ERROR: ${message}`, 'red');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
function success(message) {
|
|
45
|
+
log(`[OK] ${message}`, 'green');
|
|
46
|
+
}
|
|
47
|
+
function info(message) {
|
|
48
|
+
log(`→ ${message}`, 'cyan');
|
|
49
|
+
}
|
|
50
|
+
function warn(message) {
|
|
51
|
+
log(`[WARN] ${message}`, 'yellow');
|
|
52
|
+
}
|
|
53
|
+
// Get registry URL from env or use default
|
|
54
|
+
const REGISTRY_URL = process.env.BSB_REGISTRY_URL || 'https://io.bsbcode.dev';
|
|
55
|
+
const REGISTRY_TOKEN = process.env.BSB_REGISTRY_TOKEN;
|
|
56
|
+
const VALID_CATEGORIES = new Set(['service', 'observable', 'events', 'config']);
|
|
57
|
+
const COMMAND = process.argv[2];
|
|
58
|
+
const ARGS = process.argv.slice(3);
|
|
59
|
+
/**
|
|
60
|
+
* Parse a plugin ID into org and name.
|
|
61
|
+
* Accepts both "org/name" and plain "name" formats.
|
|
62
|
+
* When no org is provided, defaults to "_" (unaffiliated).
|
|
63
|
+
*/
|
|
64
|
+
function parsePluginId(pluginId) {
|
|
65
|
+
if (pluginId.includes('/')) {
|
|
66
|
+
const [org, ...rest] = pluginId.split('/');
|
|
67
|
+
return { org, name: rest.join('/') };
|
|
68
|
+
}
|
|
69
|
+
return { org: '_', name: pluginId };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Format a plugin ID for display.
|
|
73
|
+
* Hides the "_" sentinel org for unaffiliated plugins.
|
|
74
|
+
*/
|
|
75
|
+
function displayPluginId(org, name) {
|
|
76
|
+
return org === '_' ? name : `${org}/${name}`;
|
|
77
|
+
}
|
|
78
|
+
function normalizeIgnoredPluginId(raw, org) {
|
|
79
|
+
const value = raw.trim();
|
|
80
|
+
if (value.startsWith(`${org}/`)) {
|
|
81
|
+
return value.substring(org.length + 1);
|
|
82
|
+
}
|
|
83
|
+
if (value.startsWith('_/')) {
|
|
84
|
+
return value.substring(2);
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
function isPng(buffer) {
|
|
89
|
+
if (buffer.length < 8)
|
|
90
|
+
return false;
|
|
91
|
+
const signature = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
|
|
92
|
+
return signature.every((byte, idx) => buffer[idx] === byte);
|
|
93
|
+
}
|
|
94
|
+
function resolveCategory(pluginMeta) {
|
|
95
|
+
const raw = (pluginMeta.category || pluginMeta.id.split('-')[0] || '').toLowerCase();
|
|
96
|
+
if (!VALID_CATEGORIES.has(raw)) {
|
|
97
|
+
throw new Error(`Invalid category "${raw}" for plugin "${pluginMeta.id}". Valid categories: service, observable, events, config.`);
|
|
98
|
+
}
|
|
99
|
+
return raw;
|
|
100
|
+
}
|
|
101
|
+
function resolveImagePath(pluginMeta) {
|
|
102
|
+
if (!pluginMeta.image)
|
|
103
|
+
return null;
|
|
104
|
+
const basePath = pluginMeta.basePath || '.';
|
|
105
|
+
return path.resolve(process.cwd(), basePath, pluginMeta.image);
|
|
106
|
+
}
|
|
107
|
+
function formatRegistryError(parsed, statusCode, raw) {
|
|
108
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
109
|
+
return raw && raw.trim().length > 0
|
|
110
|
+
? raw
|
|
111
|
+
: `HTTP ${statusCode ?? 'error'}`;
|
|
112
|
+
}
|
|
113
|
+
const base = parsed.error || `HTTP ${statusCode ?? 'error'}`;
|
|
114
|
+
const code = parsed.code ? ` [${parsed.code}]` : '';
|
|
115
|
+
if (Array.isArray(parsed.details) && parsed.details.length > 0) {
|
|
116
|
+
const detailText = parsed.details
|
|
117
|
+
.map((detail) => {
|
|
118
|
+
const path = detail?.path ? String(detail.path) : '<root>';
|
|
119
|
+
const message = detail?.message ? String(detail.message) : 'Invalid value';
|
|
120
|
+
return `${path}: ${message}`;
|
|
121
|
+
})
|
|
122
|
+
.join('; ');
|
|
123
|
+
return `${base}${code} - ${detailText}`;
|
|
124
|
+
}
|
|
125
|
+
if (parsed.message && typeof parsed.message === 'string' && parsed.message.trim().length > 0) {
|
|
126
|
+
return `${base}${code} - ${parsed.message}`;
|
|
127
|
+
}
|
|
128
|
+
return `${base}${code}`;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Make HTTP request to registry
|
|
132
|
+
*/
|
|
133
|
+
async function registryRequest(method, path, body, requireAuth = false) {
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
const url = new URL(path, REGISTRY_URL);
|
|
136
|
+
const isHttps = url.protocol === 'https:';
|
|
137
|
+
const lib = isHttps ? https : http;
|
|
138
|
+
const options = {
|
|
139
|
+
hostname: url.hostname,
|
|
140
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
141
|
+
path: url.pathname + url.search,
|
|
142
|
+
method,
|
|
143
|
+
headers: {
|
|
144
|
+
'Content-Type': 'application/json',
|
|
145
|
+
'Accept': 'application/json',
|
|
146
|
+
...(requireAuth && REGISTRY_TOKEN ? { Authorization: `Bearer ${REGISTRY_TOKEN}` } : {}),
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
const req = lib.request(options, (res) => {
|
|
150
|
+
let data = '';
|
|
151
|
+
res.on('data', (chunk) => {
|
|
152
|
+
data += chunk;
|
|
153
|
+
});
|
|
154
|
+
res.on('end', () => {
|
|
155
|
+
try {
|
|
156
|
+
const parsed = JSON.parse(data);
|
|
157
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
158
|
+
resolve(parsed);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
reject(new Error(formatRegistryError(parsed, res.statusCode, data)));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
166
|
+
resolve(data);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
reject(new Error(formatRegistryError(undefined, res.statusCode, data)));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
req.on('error', (err) => {
|
|
175
|
+
reject(err);
|
|
176
|
+
});
|
|
177
|
+
if (body) {
|
|
178
|
+
req.write(JSON.stringify(body));
|
|
179
|
+
}
|
|
180
|
+
req.end();
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
async function uploadPluginImage(org, pluginName, imagePath) {
|
|
184
|
+
if (!REGISTRY_TOKEN) {
|
|
185
|
+
throw new Error('BSB_REGISTRY_TOKEN environment variable not set');
|
|
186
|
+
}
|
|
187
|
+
if (!imagePath.toLowerCase().endsWith('.png')) {
|
|
188
|
+
throw new Error(`Only PNG images are supported for upload: ${imagePath}`);
|
|
189
|
+
}
|
|
190
|
+
if (!fs.existsSync(imagePath)) {
|
|
191
|
+
throw new Error(`Image file not found: ${imagePath}`);
|
|
192
|
+
}
|
|
193
|
+
const imageBuffer = fs.readFileSync(imagePath);
|
|
194
|
+
if (!isPng(imageBuffer)) {
|
|
195
|
+
throw new Error(`Image is not a valid PNG file: ${imagePath}`);
|
|
196
|
+
}
|
|
197
|
+
const boundary = `----bsb-boundary-${Date.now().toString(16)}`;
|
|
198
|
+
const fileName = path.basename(imagePath);
|
|
199
|
+
const multipartHeader = `--${boundary}\r\n` +
|
|
200
|
+
`Content-Disposition: form-data; name="image"; filename="${fileName}"\r\n` +
|
|
201
|
+
`Content-Type: image/png\r\n\r\n`;
|
|
202
|
+
const multipartFooter = `\r\n--${boundary}--\r\n`;
|
|
203
|
+
const body = Buffer.concat([
|
|
204
|
+
Buffer.from(multipartHeader, 'utf-8'),
|
|
205
|
+
imageBuffer,
|
|
206
|
+
Buffer.from(multipartFooter, 'utf-8'),
|
|
207
|
+
]);
|
|
208
|
+
return new Promise((resolve, reject) => {
|
|
209
|
+
const uploadPath = `/plugins/${encodeURIComponent(org)}/${encodeURIComponent(pluginName)}/image`;
|
|
210
|
+
const url = new URL(uploadPath, REGISTRY_URL);
|
|
211
|
+
const isHttps = url.protocol === 'https:';
|
|
212
|
+
const lib = isHttps ? https : http;
|
|
213
|
+
const req = lib.request({
|
|
214
|
+
hostname: url.hostname,
|
|
215
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
216
|
+
path: url.pathname + url.search,
|
|
217
|
+
method: 'POST',
|
|
218
|
+
headers: {
|
|
219
|
+
'Accept': 'application/json',
|
|
220
|
+
'Authorization': `Bearer ${REGISTRY_TOKEN}`,
|
|
221
|
+
'Content-Type': `multipart/form-data; boundary=${boundary}`,
|
|
222
|
+
'Content-Length': body.length,
|
|
223
|
+
},
|
|
224
|
+
}, (res) => {
|
|
225
|
+
let data = '';
|
|
226
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
227
|
+
res.on('end', () => {
|
|
228
|
+
let parsed = {};
|
|
229
|
+
try {
|
|
230
|
+
parsed = data ? JSON.parse(data) : {};
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Keep raw payload fallback for error messages
|
|
234
|
+
}
|
|
235
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
236
|
+
resolve(parsed);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
reject(new Error(parsed.error || data || `HTTP ${res.statusCode}`));
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
req.on('error', reject);
|
|
244
|
+
req.write(body);
|
|
245
|
+
req.end();
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* List plugins from registry
|
|
250
|
+
*/
|
|
251
|
+
async function listPlugins() {
|
|
252
|
+
info('Fetching plugins from registry...');
|
|
253
|
+
try {
|
|
254
|
+
const result = await registryRequest('GET', '/plugins?limit=100');
|
|
255
|
+
if (result.results.length === 0) {
|
|
256
|
+
warn('No plugins found in registry');
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
log(`\nFound ${result.total} plugins:\n`, 'bright');
|
|
260
|
+
result.results.forEach((plugin) => {
|
|
261
|
+
log(` ${plugin.id} @ ${plugin.version}`, 'cyan');
|
|
262
|
+
log(` ${plugin.description}`, 'reset');
|
|
263
|
+
log(` Language: ${plugin.language} | Category: ${plugin.category}`, 'reset');
|
|
264
|
+
log('');
|
|
265
|
+
});
|
|
266
|
+
success(`Listed ${result.results.length} plugins`);
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
error(`Failed to list plugins: ${err.message}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Search plugins
|
|
274
|
+
*/
|
|
275
|
+
async function searchPlugins(query) {
|
|
276
|
+
if (!query) {
|
|
277
|
+
error('Please provide a search query: bsb-client search <query>');
|
|
278
|
+
}
|
|
279
|
+
info(`Searching for "${query}"...`);
|
|
280
|
+
try {
|
|
281
|
+
const result = await registryRequest('GET', `/plugins?query=${encodeURIComponent(query)}&limit=100`);
|
|
282
|
+
if (result.results.length === 0) {
|
|
283
|
+
warn(`No plugins found matching "${query}"`);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
log(`\nFound ${result.total} matches:\n`, 'bright');
|
|
287
|
+
result.results.forEach((plugin) => {
|
|
288
|
+
log(` ${plugin.id} @ ${plugin.version}`, 'cyan');
|
|
289
|
+
log(` ${plugin.description}`, 'reset');
|
|
290
|
+
log(` Language: ${plugin.language} | Category: ${plugin.category}`, 'reset');
|
|
291
|
+
log('');
|
|
292
|
+
});
|
|
293
|
+
success(`Found ${result.results.length} matches`);
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
error(`Failed to search plugins: ${err.message}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Get plugin info
|
|
301
|
+
*/
|
|
302
|
+
async function getPluginInfo(pluginId) {
|
|
303
|
+
if (!pluginId) {
|
|
304
|
+
error('Please provide a plugin ID: bsb-client info <name> or bsb-client info <org/name>');
|
|
305
|
+
}
|
|
306
|
+
const { org, name } = parsePluginId(pluginId);
|
|
307
|
+
const display = displayPluginId(org, name);
|
|
308
|
+
info(`Fetching plugin info for ${display}...`);
|
|
309
|
+
try {
|
|
310
|
+
const result = await registryRequest('GET', `/plugins/${org}/${name}`);
|
|
311
|
+
const plugin = result.plugin || result;
|
|
312
|
+
log(`\nPlugin: ${plugin.displayName}\n`, 'bright');
|
|
313
|
+
log(` ID: ${plugin.id}`, 'reset');
|
|
314
|
+
log(` Version: ${plugin.version}`, 'reset');
|
|
315
|
+
log(` Language: ${plugin.language}`, 'reset');
|
|
316
|
+
log(` Category: ${plugin.category}`, 'reset');
|
|
317
|
+
log(` Description: ${plugin.description}`, 'reset');
|
|
318
|
+
log(` Author: ${plugin.author || 'N/A'}`, 'reset');
|
|
319
|
+
log(` License: ${plugin.license || 'N/A'}`, 'reset');
|
|
320
|
+
log(` Homepage: ${plugin.homepage || 'N/A'}`, 'reset');
|
|
321
|
+
log(` Repository: ${plugin.repository || 'N/A'}`, 'reset');
|
|
322
|
+
log(` Events: ${plugin.eventCount} total`, 'reset');
|
|
323
|
+
log(` Downloads: ${plugin.downloads || 0}`, 'reset');
|
|
324
|
+
log('');
|
|
325
|
+
success('Plugin info retrieved');
|
|
326
|
+
}
|
|
327
|
+
catch (err) {
|
|
328
|
+
error(`Failed to get plugin info: ${err.message}`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get plugin schema
|
|
333
|
+
*/
|
|
334
|
+
async function getPluginSchema(pluginId) {
|
|
335
|
+
if (!pluginId) {
|
|
336
|
+
error('Please provide a plugin ID: bsb-client schema <name> or bsb-client schema <org/name>');
|
|
337
|
+
}
|
|
338
|
+
const { org, name } = parsePluginId(pluginId);
|
|
339
|
+
const display = displayPluginId(org, name);
|
|
340
|
+
info(`Fetching schema for ${display}...`);
|
|
341
|
+
try {
|
|
342
|
+
// Get plugin to find latest version
|
|
343
|
+
const result = await registryRequest('GET', `/plugins/${org}/${name}`);
|
|
344
|
+
const plugin = result.plugin || result;
|
|
345
|
+
const schema = await registryRequest('GET', `/plugins/${org}/${name}/${plugin.version}/schema`);
|
|
346
|
+
log(`\nEvent Schema for ${pluginId} @ ${plugin.version}:\n`, 'bright');
|
|
347
|
+
log(JSON.stringify(schema, null, 2), 'reset');
|
|
348
|
+
success('Schema retrieved');
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
error(`Failed to get schema: ${err.message}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Publish plugin(s) to registry.
|
|
356
|
+
* Iterates over all plugins in bsb-plugin.json and publishes each separately.
|
|
357
|
+
* Org is read from package.json "bsb.orgId" field, defaulting to "_" (unaffiliated).
|
|
358
|
+
*/
|
|
359
|
+
async function publishPlugin() {
|
|
360
|
+
if (!REGISTRY_TOKEN) {
|
|
361
|
+
error('BSB_REGISTRY_TOKEN environment variable not set. Get a token from the registry admin.');
|
|
362
|
+
}
|
|
363
|
+
info('Publishing plugin(s) to registry...');
|
|
364
|
+
try {
|
|
365
|
+
// Read package.json
|
|
366
|
+
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
367
|
+
if (!fs.existsSync(pkgPath)) {
|
|
368
|
+
error('No package.json found in current directory');
|
|
369
|
+
}
|
|
370
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
371
|
+
// Read publish manifest from bsb-plugin.json
|
|
372
|
+
const manifestPath = path.join(process.cwd(), 'bsb-plugin.json');
|
|
373
|
+
if (!fs.existsSync(manifestPath)) {
|
|
374
|
+
error('No bsb-plugin.json found. Run "bsb-plugin-cli build" first.');
|
|
375
|
+
}
|
|
376
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
377
|
+
const plugins = Array.isArray(manifest.nodejs) ? manifest.nodejs : [];
|
|
378
|
+
if (plugins.length === 0) {
|
|
379
|
+
error('No Node.js plugins found in bsb-plugin.json');
|
|
380
|
+
}
|
|
381
|
+
// Schemas are still sourced from generated lib/schemas/{plugin}.json
|
|
382
|
+
const schemasDir = path.join(process.cwd(), 'lib', 'schemas');
|
|
383
|
+
if (!fs.existsSync(schemasDir)) {
|
|
384
|
+
error('No lib/schemas/ directory found. Run "bsb-plugin-cli build" first.');
|
|
385
|
+
}
|
|
386
|
+
// Read project README.md as fallback documentation
|
|
387
|
+
const readmePath = path.join(process.cwd(), 'README.md');
|
|
388
|
+
const readmeContent = fs.existsSync(readmePath) ? fs.readFileSync(readmePath, 'utf-8') : undefined;
|
|
389
|
+
// Org from package.json bsb.orgId, default to "_" (unaffiliated)
|
|
390
|
+
const org = pkg.bsb?.orgId || '_';
|
|
391
|
+
const publishIgnoreRaw = pkg.bsb?.publishIgnore;
|
|
392
|
+
const publishIgnore = new Set(Array.isArray(publishIgnoreRaw)
|
|
393
|
+
? publishIgnoreRaw
|
|
394
|
+
.filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
|
|
395
|
+
.map((entry) => normalizeIgnoredPluginId(entry, org))
|
|
396
|
+
: []);
|
|
397
|
+
let published = 0;
|
|
398
|
+
let skipped = 0;
|
|
399
|
+
let errors = 0;
|
|
400
|
+
for (const pluginMeta of plugins) {
|
|
401
|
+
const pluginName = pluginMeta.id;
|
|
402
|
+
const display = displayPluginId(org, pluginName);
|
|
403
|
+
if (publishIgnore.has(pluginName)) {
|
|
404
|
+
info(`Skipping ${display} (listed in package.json bsb.publishIgnore)`);
|
|
405
|
+
skipped++;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
try {
|
|
409
|
+
const category = resolveCategory({ id: pluginName, category: pluginMeta.category });
|
|
410
|
+
const imagePath = resolveImagePath({ basePath: pluginMeta.basePath, image: pluginMeta.image });
|
|
411
|
+
// Read event schema from lib/schemas/{pluginId}.json
|
|
412
|
+
const schemaPath = path.join(schemasDir, `${pluginName}.json`);
|
|
413
|
+
let eventSchema = { pluginName, version: pkg.version, events: {} };
|
|
414
|
+
let configSchema;
|
|
415
|
+
let schemaDeps;
|
|
416
|
+
if (fs.existsSync(schemaPath)) {
|
|
417
|
+
try {
|
|
418
|
+
const parsed = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
|
|
419
|
+
eventSchema = {
|
|
420
|
+
pluginName: parsed.pluginName || pluginName,
|
|
421
|
+
version: parsed.version || pkg.version,
|
|
422
|
+
events: parsed.events || {},
|
|
423
|
+
};
|
|
424
|
+
if (parsed.capabilities && typeof parsed.capabilities === 'object') {
|
|
425
|
+
eventSchema.capabilities = parsed.capabilities;
|
|
426
|
+
}
|
|
427
|
+
if (Array.isArray(parsed.dependencies) && parsed.dependencies.length > 0) {
|
|
428
|
+
eventSchema.dependencies = parsed.dependencies;
|
|
429
|
+
schemaDeps = parsed.dependencies;
|
|
430
|
+
}
|
|
431
|
+
if (parsed.configSchema && typeof parsed.configSchema === 'object') {
|
|
432
|
+
configSchema = parsed.configSchema;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
// Non-fatal -- use defaults
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
// Fallback: configSchema from plugin.json
|
|
440
|
+
if (!configSchema && pluginMeta.configSchema && typeof pluginMeta.configSchema === 'object') {
|
|
441
|
+
configSchema = pluginMeta.configSchema;
|
|
442
|
+
}
|
|
443
|
+
// Read documentation files listed in plugin metadata
|
|
444
|
+
const documentation = [];
|
|
445
|
+
const docPaths = Array.isArray(pluginMeta.documentation) ? pluginMeta.documentation : [];
|
|
446
|
+
for (const docPath of docPaths) {
|
|
447
|
+
const fullPath = path.resolve(process.cwd(), docPath);
|
|
448
|
+
if (fs.existsSync(fullPath)) {
|
|
449
|
+
documentation.push(fs.readFileSync(fullPath, 'utf-8'));
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
warn(`Documentation file not found: ${docPath}`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
// Fallback to project README.md
|
|
456
|
+
if (documentation.length === 0) {
|
|
457
|
+
if (readmeContent) {
|
|
458
|
+
documentation.push(readmeContent);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
error(`No documentation found for ${display}. Add documentation paths to Config metadata or provide a README.md.`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
const publishRequest = {
|
|
465
|
+
org,
|
|
466
|
+
name: pluginName,
|
|
467
|
+
version: pkg.version,
|
|
468
|
+
language: 'nodejs',
|
|
469
|
+
metadata: {
|
|
470
|
+
displayName: pluginMeta.name || pluginName,
|
|
471
|
+
description: pluginMeta.description || pkg.description || '',
|
|
472
|
+
category,
|
|
473
|
+
tags: pluginMeta.tags || pkg.keywords || [],
|
|
474
|
+
author: pluginMeta.author || pkg.author,
|
|
475
|
+
license: pluginMeta.license || pkg.license,
|
|
476
|
+
homepage: pluginMeta.homepage || pkg.homepage,
|
|
477
|
+
repository: pluginMeta.repository || (typeof pkg.repository === 'string' ? pkg.repository : pkg.repository?.url),
|
|
478
|
+
},
|
|
479
|
+
eventSchema,
|
|
480
|
+
documentation,
|
|
481
|
+
package: {
|
|
482
|
+
nodejs: pkg.name,
|
|
483
|
+
},
|
|
484
|
+
visibility: 'public',
|
|
485
|
+
};
|
|
486
|
+
if (configSchema) {
|
|
487
|
+
publishRequest.configSchema = configSchema;
|
|
488
|
+
}
|
|
489
|
+
// Top-level dependencies (registry gives these priority over eventSchema.dependencies)
|
|
490
|
+
if (schemaDeps) {
|
|
491
|
+
publishRequest.dependencies = schemaDeps;
|
|
492
|
+
}
|
|
493
|
+
info(`Publishing ${display} @ ${pkg.version}...`);
|
|
494
|
+
const result = await registryRequest('POST', '/plugins', publishRequest, true);
|
|
495
|
+
if (imagePath) {
|
|
496
|
+
info(`Uploading image for ${display}...`);
|
|
497
|
+
await uploadPluginImage(org, pluginName, imagePath);
|
|
498
|
+
}
|
|
499
|
+
success(`Published: ${display} @ ${result.version}${imagePath ? ' (with image)' : ''}`);
|
|
500
|
+
published++;
|
|
501
|
+
}
|
|
502
|
+
catch (err) {
|
|
503
|
+
log(` Failed to publish ${display}: ${err.message}`, 'red');
|
|
504
|
+
errors++;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
log('');
|
|
508
|
+
if (published > 0) {
|
|
509
|
+
success(`Published ${published} plugin(s)${skipped > 0 ? `, ${skipped} skipped` : ''}${errors > 0 ? `, ${errors} failed` : ''}`);
|
|
510
|
+
}
|
|
511
|
+
if (published === 0 && skipped > 0 && errors === 0) {
|
|
512
|
+
success(`No plugins published (${skipped} skipped via package.json bsb.publishIgnore).`);
|
|
513
|
+
}
|
|
514
|
+
if (errors > 0 && published === 0) {
|
|
515
|
+
error(`All ${errors} plugin(s) failed to publish`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
catch (err) {
|
|
519
|
+
error(`Failed to publish plugin: ${err.message}`);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Ensure the project's .gitignore contains the src/.bsb/ entry.
|
|
524
|
+
*/
|
|
525
|
+
function ensureGitignore() {
|
|
526
|
+
const projectRoot = process.cwd();
|
|
527
|
+
const gitignorePath = path.join(projectRoot, '.gitignore');
|
|
528
|
+
const bsbDir = path.join(projectRoot, 'src', '.bsb');
|
|
529
|
+
let relativeBsbDir = path.relative(projectRoot, bsbDir).replace(/\\/g, '/');
|
|
530
|
+
if (!relativeBsbDir.endsWith('/')) {
|
|
531
|
+
relativeBsbDir += '/';
|
|
532
|
+
}
|
|
533
|
+
try {
|
|
534
|
+
if (fs.existsSync(gitignorePath)) {
|
|
535
|
+
const content = fs.readFileSync(gitignorePath, 'utf-8');
|
|
536
|
+
const lines = content.split(/\r?\n/);
|
|
537
|
+
const alreadyIgnored = lines.some(line => {
|
|
538
|
+
const trimmed = line.trim();
|
|
539
|
+
return trimmed === relativeBsbDir ||
|
|
540
|
+
trimmed === relativeBsbDir.replace(/\/$/, '') ||
|
|
541
|
+
trimmed === '.bsb/' ||
|
|
542
|
+
trimmed === '.bsb' ||
|
|
543
|
+
trimmed === 'src/.bsb/' ||
|
|
544
|
+
trimmed === 'src/.bsb';
|
|
545
|
+
});
|
|
546
|
+
if (!alreadyIgnored) {
|
|
547
|
+
const newline = content.endsWith('\n') ? '' : '\n';
|
|
548
|
+
fs.writeFileSync(gitignorePath, content + newline + relativeBsbDir + '\n', 'utf-8');
|
|
549
|
+
success(`Added '${relativeBsbDir}' to .gitignore`);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
fs.writeFileSync(gitignorePath, relativeBsbDir + '\n', 'utf-8');
|
|
554
|
+
success(`Created .gitignore with '${relativeBsbDir}'`);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
catch {
|
|
558
|
+
// Non-fatal
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Install plugin from registry (download schema and generate virtual client)
|
|
563
|
+
*/
|
|
564
|
+
async function installPlugin(pluginId) {
|
|
565
|
+
if (!pluginId) {
|
|
566
|
+
error('Please provide a plugin ID: bsb-client install <name> or bsb-client install <org/name>');
|
|
567
|
+
}
|
|
568
|
+
const { org, name } = parsePluginId(pluginId);
|
|
569
|
+
const display = displayPluginId(org, name);
|
|
570
|
+
info(`Installing plugin ${display}...`);
|
|
571
|
+
try {
|
|
572
|
+
// Get plugin metadata
|
|
573
|
+
const detailResult = await registryRequest('GET', `/plugins/${org}/${name}`);
|
|
574
|
+
const plugin = detailResult.plugin || detailResult;
|
|
575
|
+
// Get plugin schema
|
|
576
|
+
const schema = await registryRequest('GET', `/plugins/${org}/${name}/${plugin.version}/schema`);
|
|
577
|
+
// Create directories for remote schemas and virtual clients
|
|
578
|
+
const schemasDir = path.join(process.cwd(), 'src', '.bsb', 'schemas');
|
|
579
|
+
const clientsDir = path.join(process.cwd(), 'src', '.bsb', 'clients');
|
|
580
|
+
if (!fs.existsSync(schemasDir)) {
|
|
581
|
+
fs.mkdirSync(schemasDir, { recursive: true });
|
|
582
|
+
}
|
|
583
|
+
if (!fs.existsSync(clientsDir)) {
|
|
584
|
+
fs.mkdirSync(clientsDir, { recursive: true });
|
|
585
|
+
}
|
|
586
|
+
// Ensure .gitignore covers the generated directory
|
|
587
|
+
ensureGitignore();
|
|
588
|
+
// Save schema
|
|
589
|
+
const schemaFile = path.join(schemasDir, `${name}.json`);
|
|
590
|
+
fs.writeFileSync(schemaFile, JSON.stringify(schema, null, 2), 'utf-8');
|
|
591
|
+
success(`Downloaded schema for ${display}`);
|
|
592
|
+
// Generate virtual client by calling the generator
|
|
593
|
+
const generatorPath = path.join(__dirname, 'generate-client-types.js');
|
|
594
|
+
if (fs.existsSync(generatorPath)) {
|
|
595
|
+
const { execSync } = require('child_process');
|
|
596
|
+
try {
|
|
597
|
+
execSync(`node "${generatorPath}"`, {
|
|
598
|
+
cwd: process.cwd(),
|
|
599
|
+
stdio: 'pipe',
|
|
600
|
+
});
|
|
601
|
+
success(`Generated virtual client for ${display}`);
|
|
602
|
+
}
|
|
603
|
+
catch (err) {
|
|
604
|
+
warn('Failed to generate virtual client automatically. Run your build to regenerate.');
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
log('');
|
|
608
|
+
success(`Plugin ${display} @ ${plugin.version} installed`);
|
|
609
|
+
log(` Schema: ${schemaFile}`, 'reset');
|
|
610
|
+
log(` Import: import ${pluginNameToClassName(name)} from './.bsb/clients/${name}'`, 'reset');
|
|
611
|
+
}
|
|
612
|
+
catch (err) {
|
|
613
|
+
error(`Failed to install plugin: ${err.message}`);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Convert plugin key/ID to PascalCase client class name.
|
|
618
|
+
* Strips non-alphanumeric characters to ensure valid TypeScript identifiers.
|
|
619
|
+
*/
|
|
620
|
+
function pluginNameToClassName(pluginId) {
|
|
621
|
+
let name = pluginId;
|
|
622
|
+
if (name.startsWith('service-')) {
|
|
623
|
+
name = name.substring('service-'.length);
|
|
624
|
+
}
|
|
625
|
+
const pascal = name
|
|
626
|
+
.replace(/[^a-zA-Z0-9-]/g, '')
|
|
627
|
+
.split('-')
|
|
628
|
+
.filter(part => part.length > 0)
|
|
629
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
|
630
|
+
.join('');
|
|
631
|
+
return pascal + 'Client';
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Generate API token
|
|
635
|
+
*/
|
|
636
|
+
async function generateToken() {
|
|
637
|
+
warn('Token generation is not yet implemented.');
|
|
638
|
+
warn('Please contact the registry administrator to obtain an API token.');
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Main CLI handler
|
|
642
|
+
*/
|
|
643
|
+
async function main() {
|
|
644
|
+
if (!COMMAND) {
|
|
645
|
+
log('BSB Client CLI - Plugin Registry Commands', 'bright');
|
|
646
|
+
log('');
|
|
647
|
+
log('Usage:', 'cyan');
|
|
648
|
+
log(' bsb-client list - List all plugins from registry');
|
|
649
|
+
log(' bsb-client search <query> - Search plugins');
|
|
650
|
+
log(' bsb-client info <name> - Get plugin details');
|
|
651
|
+
log(' bsb-client schema <name> - Get plugin event schema');
|
|
652
|
+
log(' bsb-client install <name> - Download schema and generate types');
|
|
653
|
+
log(' bsb-client publish - Publish current plugin(s) to registry');
|
|
654
|
+
log(' bsb-client token generate - Generate a new API token');
|
|
655
|
+
log('');
|
|
656
|
+
log('Plugin IDs:', 'cyan');
|
|
657
|
+
log(' Use plain name: bsb-client info service-bsb-registry');
|
|
658
|
+
log(' Or with org: bsb-client info myorg/service-bsb-registry');
|
|
659
|
+
log('');
|
|
660
|
+
log('Environment:', 'cyan');
|
|
661
|
+
log(` BSB_REGISTRY_URL = ${REGISTRY_URL}`);
|
|
662
|
+
log(` BSB_REGISTRY_TOKEN = ${REGISTRY_TOKEN ? '***' + REGISTRY_TOKEN.substring(REGISTRY_TOKEN.length - 4) : '(not set)'}`);
|
|
663
|
+
log('');
|
|
664
|
+
process.exit(0);
|
|
665
|
+
}
|
|
666
|
+
switch (COMMAND) {
|
|
667
|
+
case 'list':
|
|
668
|
+
await listPlugins();
|
|
669
|
+
break;
|
|
670
|
+
case 'search':
|
|
671
|
+
await searchPlugins(ARGS[0]);
|
|
672
|
+
break;
|
|
673
|
+
case 'info':
|
|
674
|
+
await getPluginInfo(ARGS[0]);
|
|
675
|
+
break;
|
|
676
|
+
case 'schema':
|
|
677
|
+
await getPluginSchema(ARGS[0]);
|
|
678
|
+
break;
|
|
679
|
+
case 'install':
|
|
680
|
+
await installPlugin(ARGS[0]);
|
|
681
|
+
break;
|
|
682
|
+
case 'publish':
|
|
683
|
+
await publishPlugin();
|
|
684
|
+
break;
|
|
685
|
+
case 'token':
|
|
686
|
+
if (ARGS[0] === 'generate') {
|
|
687
|
+
await generateToken();
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
error('Unknown token command. Use: bsb-client token generate');
|
|
691
|
+
}
|
|
692
|
+
break;
|
|
693
|
+
default:
|
|
694
|
+
error(`Unknown command: ${COMMAND}`);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
// Run CLI
|
|
698
|
+
main().catch((err) => {
|
|
699
|
+
error(`Unexpected error: ${err.message}`);
|
|
700
|
+
});
|
|
701
|
+
//# sourceMappingURL=bsb-client-cli.js.map
|