local-bdk-cli 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/README.md +3 -0
- package/dist/commands/create.js +314 -0
- package/dist/commands/help.js +83 -0
- package/dist/commands/pack.js +116 -0
- package/dist/commands/publish.js +97 -0
- package/dist/commands/run.js +220 -0
- package/dist/commands/test.js +61 -0
- package/dist/commands/validate.js +57 -0
- package/dist/commands/version.js +62 -0
- package/dist/index.js +24 -0
- package/dist/lib/appPath.js +17 -0
- package/dist/lib/localstore.js +190 -0
- package/dist/lib/package.js +181 -0
- package/dist/utils/appConfig.js +24 -0
- package/dist/utils/createApp.js +47 -0
- package/dist/utils/getAppSettings.js +13 -0
- package/dist/utils/manifest.js +14 -0
- package/dist/utils/uploadApp.js +25 -0
- package/package.json +67 -0
- package/schemas/manifest.schema.json +92 -0
- package/templates/default/README.md +18 -0
- package/templates/default/assets/iframe.html +13 -0
- package/templates/default/assets/logo-small.svg +4 -0
- package/templates/default/assets/logo.svg +6 -0
- package/templates/default/manifest.json +31 -0
- package/templates/default/package.json +12 -0
- package/templates/default/translations/en.json +8 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerRun = registerRun;
|
|
37
|
+
const http = __importStar(require("http"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const child_process_1 = require("child_process");
|
|
41
|
+
const localstore_1 = require("../lib/localstore");
|
|
42
|
+
function registerRun(program) {
|
|
43
|
+
program
|
|
44
|
+
.command('run [source]')
|
|
45
|
+
.alias('apps:run')
|
|
46
|
+
.description('Run the app locally with live reload')
|
|
47
|
+
.option('--port <number>', 'port to run', '3000')
|
|
48
|
+
.option('--env <env>', 'environment', 'dev')
|
|
49
|
+
.option('--open', 'open browser after start', false)
|
|
50
|
+
.action((sourceArg, opts) => {
|
|
51
|
+
const sourceDir = path.resolve(process.cwd(), sourceArg || '.');
|
|
52
|
+
const port = parseInt(opts.port || '3000', 10);
|
|
53
|
+
const env = opts.env || 'dev';
|
|
54
|
+
// Check if manifest.json exists
|
|
55
|
+
const manifestPath = path.join(sourceDir, 'manifest.json');
|
|
56
|
+
if (!fs.existsSync(manifestPath)) {
|
|
57
|
+
console.error(`manifest.json not found in ${sourceDir}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
// Initialize LocalStore for local database operations
|
|
61
|
+
const localStore = new localstore_1.LocalStore(path.join(sourceDir, '.bdk/localstore'));
|
|
62
|
+
// Handler for database operations
|
|
63
|
+
const handleDBRequest = (operation, key, value) => {
|
|
64
|
+
try {
|
|
65
|
+
switch (operation) {
|
|
66
|
+
case 'set':
|
|
67
|
+
return localStore.store(key, value);
|
|
68
|
+
case 'get':
|
|
69
|
+
return localStore.fetch(key);
|
|
70
|
+
case 'update':
|
|
71
|
+
return localStore.update(key, value);
|
|
72
|
+
case 'delete':
|
|
73
|
+
return localStore.delete(key);
|
|
74
|
+
default:
|
|
75
|
+
throw new Error(`Unknown database operation: ${operation}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
console.error(`[DB] ERROR (${operation} ${key}): ${error.message}`);
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
// Create HTTP server
|
|
84
|
+
const server = http.createServer((req, res) => {
|
|
85
|
+
var _a;
|
|
86
|
+
// Add CORS headers
|
|
87
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
88
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
89
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
90
|
+
// Handle OPTIONS requests
|
|
91
|
+
if (req.method === 'OPTIONS') {
|
|
92
|
+
res.writeHead(200);
|
|
93
|
+
res.end();
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Handle database API requests
|
|
97
|
+
if (((_a = req.url) === null || _a === void 0 ? void 0 : _a.startsWith('/api/db')) && req.method === 'POST') {
|
|
98
|
+
let body = '';
|
|
99
|
+
req.on('data', (chunk) => {
|
|
100
|
+
body += chunk.toString();
|
|
101
|
+
});
|
|
102
|
+
req.on('error', (error) => {
|
|
103
|
+
console.error(`[DB] Request error:`, error);
|
|
104
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
105
|
+
res.end(JSON.stringify({ success: false, error: 'Request error' }));
|
|
106
|
+
});
|
|
107
|
+
req.on('end', () => {
|
|
108
|
+
try {
|
|
109
|
+
if (!body)
|
|
110
|
+
throw new Error('Empty request body');
|
|
111
|
+
const payload = JSON.parse(body);
|
|
112
|
+
const result = handleDBRequest(payload.operation, payload.key, payload.value);
|
|
113
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
114
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error(`[DB] Error:`, error);
|
|
118
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
119
|
+
res.end(JSON.stringify({ success: false, error: error.message }));
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// Handle static file requests
|
|
125
|
+
let filePath = req.url || '/';
|
|
126
|
+
if (filePath === '/') {
|
|
127
|
+
filePath = '/assets/iframe.html';
|
|
128
|
+
}
|
|
129
|
+
// Resolve the file path
|
|
130
|
+
const fullPath = path.join(sourceDir, filePath);
|
|
131
|
+
// Security: prevent directory traversal attacks
|
|
132
|
+
const resolvedPath = path.resolve(fullPath);
|
|
133
|
+
const basePath = path.resolve(sourceDir);
|
|
134
|
+
if (!resolvedPath.startsWith(basePath)) {
|
|
135
|
+
res.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
136
|
+
res.end('Forbidden');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Try to serve the file
|
|
140
|
+
fs.readFile(resolvedPath, (err, data) => {
|
|
141
|
+
if (err) {
|
|
142
|
+
// If file not found, try to serve index.html or 404
|
|
143
|
+
if (err.code === 'ENOENT') {
|
|
144
|
+
res.writeHead(404, { 'Content-Type': 'text/html' });
|
|
145
|
+
res.end(`
|
|
146
|
+
<!DOCTYPE html>
|
|
147
|
+
<html>
|
|
148
|
+
<head><title>404 Not Found</title></head>
|
|
149
|
+
<body>
|
|
150
|
+
<h1>404 - File Not Found</h1>
|
|
151
|
+
<p>Could not find: ${filePath}</p>
|
|
152
|
+
<p><a href="/">Go back</a></p>
|
|
153
|
+
</body>
|
|
154
|
+
</html>
|
|
155
|
+
`);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
159
|
+
res.end('Internal Server Error');
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// Determine content type
|
|
164
|
+
const ext = path.extname(resolvedPath);
|
|
165
|
+
let contentType = 'application/octet-stream';
|
|
166
|
+
if (ext === '.html')
|
|
167
|
+
contentType = 'text/html; charset=utf-8';
|
|
168
|
+
else if (ext === '.js')
|
|
169
|
+
contentType = 'application/javascript; charset=utf-8';
|
|
170
|
+
else if (ext === '.json')
|
|
171
|
+
contentType = 'application/json; charset=utf-8';
|
|
172
|
+
else if (ext === '.css')
|
|
173
|
+
contentType = 'text/css; charset=utf-8';
|
|
174
|
+
else if (ext === '.svg')
|
|
175
|
+
contentType = 'image/svg+xml';
|
|
176
|
+
else if (ext === '.png')
|
|
177
|
+
contentType = 'image/png';
|
|
178
|
+
else if (ext === '.jpg' || ext === '.jpeg')
|
|
179
|
+
contentType = 'image/jpeg';
|
|
180
|
+
else if (ext === '.gif')
|
|
181
|
+
contentType = 'image/gif';
|
|
182
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
183
|
+
res.end(data);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
server.listen(port, () => {
|
|
187
|
+
console.log(`✅ Dev server started on http://localhost:${port} (env=${env})`);
|
|
188
|
+
console.log(`📁 Serving from: ${sourceDir}`);
|
|
189
|
+
console.log(`📄 Iframe: http://localhost:${port}/assets/iframe.html`);
|
|
190
|
+
console.log(`💾 Database: Local storage at ${localStore.getFilePath()}`);
|
|
191
|
+
console.log(`\nPress Ctrl+C to stop the server\n`);
|
|
192
|
+
// Open browser if --open flag is set
|
|
193
|
+
if (opts.open) {
|
|
194
|
+
const url = `http://localhost:${port}`;
|
|
195
|
+
try {
|
|
196
|
+
const isWindows = process.platform === 'win32';
|
|
197
|
+
const command = isWindows
|
|
198
|
+
? `start ${url}`
|
|
199
|
+
: process.platform === 'darwin'
|
|
200
|
+
? `open ${url}`
|
|
201
|
+
: `xdg-open ${url}`;
|
|
202
|
+
(0, child_process_1.execSync)(command, { stdio: 'ignore' });
|
|
203
|
+
}
|
|
204
|
+
catch (e) {
|
|
205
|
+
// Silently ignore if browser open fails
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
server.on('error', (err) => {
|
|
210
|
+
if (err.code === 'EADDRINUSE') {
|
|
211
|
+
console.error(`❌ Port ${port} is already in use. Try a different port:`);
|
|
212
|
+
console.error(` npx bdk apps:run [source] --port 3001`);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
console.error(`❌ Server error: ${err.message}`);
|
|
216
|
+
}
|
|
217
|
+
process.exit(1);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerTest = registerTest;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
function registerTest(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('test [source]')
|
|
8
|
+
.alias('apps:test')
|
|
9
|
+
.description('Run unit and integration tests')
|
|
10
|
+
.option('--watch', 're-run tests on file changes', false)
|
|
11
|
+
.option('--coverage', 'generate coverage report', false)
|
|
12
|
+
.action((sourceArg, opts) => {
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const cwd = path.resolve(process.cwd(), sourceArg || '.');
|
|
16
|
+
// Check if package.json exists and has test script
|
|
17
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
18
|
+
const hasPkg = (() => {
|
|
19
|
+
try {
|
|
20
|
+
if (!fs.existsSync(pkgPath)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const p = require(pkgPath);
|
|
24
|
+
return !!p.scripts && (p.scripts.test || p.scripts['test:watch']);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
})();
|
|
30
|
+
if (!hasPkg) {
|
|
31
|
+
console.error('No test script found in package.json. Please add a `test` script.');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
if (opts.watch) {
|
|
35
|
+
// prefer npm run test -- --watch if available
|
|
36
|
+
try {
|
|
37
|
+
console.log('Running tests in watch mode...');
|
|
38
|
+
const child = (0, child_process_1.spawn)('npm', ['run', 'test', '--', '--watch'], { stdio: 'inherit', cwd: cwd, shell: true });
|
|
39
|
+
child.on('exit', (code) => process.exit(code || 0));
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
console.error('Failed to start watch tests:', e);
|
|
43
|
+
process.exit(2);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const args = ['run', 'test'];
|
|
49
|
+
if (opts.coverage) {
|
|
50
|
+
// many projects use `npm run test -- --coverage` to enable coverage
|
|
51
|
+
args.push('--', '--coverage');
|
|
52
|
+
}
|
|
53
|
+
console.log('Running tests...');
|
|
54
|
+
(0, child_process_1.execSync)('npm ' + args.join(' '), { stdio: 'inherit', cwd: cwd });
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
console.error('Tests failed.');
|
|
58
|
+
process.exit(e.status || 1);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.registerValidate = registerValidate;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const package_1 = require("../lib/package");
|
|
39
|
+
const appPath_1 = require("../lib/appPath");
|
|
40
|
+
function registerValidate(program) {
|
|
41
|
+
program
|
|
42
|
+
.command('validate [appDirectory]')
|
|
43
|
+
.alias('apps:validate')
|
|
44
|
+
.description('Validate app structure and manifest')
|
|
45
|
+
.action(async (appDirectory = '.') => {
|
|
46
|
+
try {
|
|
47
|
+
(0, appPath_1.validateAppPath)(appDirectory);
|
|
48
|
+
const appPath = path.resolve(appDirectory);
|
|
49
|
+
await (0, package_1.validatePkg)(appPath);
|
|
50
|
+
console.log('No validation errors');
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
console.error(err && err.message ? err.message : err);
|
|
54
|
+
process.exit(2);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerVersion = registerVersion;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function bumpVersion(v, level) {
|
|
10
|
+
const parts = v.split('.').map((s) => parseInt(s, 10));
|
|
11
|
+
while (parts.length < 3)
|
|
12
|
+
parts.push(0);
|
|
13
|
+
if (level === 'patch')
|
|
14
|
+
parts[2] = (parts[2] || 0) + 1;
|
|
15
|
+
if (level === 'minor') {
|
|
16
|
+
parts[1] = (parts[1] || 0) + 1;
|
|
17
|
+
parts[2] = 0;
|
|
18
|
+
}
|
|
19
|
+
if (level === 'major') {
|
|
20
|
+
parts[0] = (parts[0] || 0) + 1;
|
|
21
|
+
parts[1] = 0;
|
|
22
|
+
parts[2] = 0;
|
|
23
|
+
}
|
|
24
|
+
return parts.join('.');
|
|
25
|
+
}
|
|
26
|
+
function registerVersion(program) {
|
|
27
|
+
program
|
|
28
|
+
.command('version [source]')
|
|
29
|
+
.alias('apps:version')
|
|
30
|
+
.description('Show or bump app version')
|
|
31
|
+
.option('--bump <level>', 'patch|minor|major')
|
|
32
|
+
.option('--set <version>', 'set exact version')
|
|
33
|
+
.action((sourceArg, opts) => {
|
|
34
|
+
const manifestPath = path_1.default.resolve(process.cwd(), sourceArg || '.', 'manifest.json');
|
|
35
|
+
if (!fs_1.default.existsSync(manifestPath)) {
|
|
36
|
+
console.error('manifest.json not found at', manifestPath);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
const manifest = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf8'));
|
|
40
|
+
let version = manifest.version || '0.0.0';
|
|
41
|
+
if (opts.set) {
|
|
42
|
+
version = opts.set;
|
|
43
|
+
manifest.version = version;
|
|
44
|
+
fs_1.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
|
|
45
|
+
console.log(`Set version to ${version}`);
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
if (opts.bump) {
|
|
49
|
+
const level = opts.bump;
|
|
50
|
+
if (!['patch', 'minor', 'major'].includes(level)) {
|
|
51
|
+
console.error('Invalid bump level. Use patch, minor or major.');
|
|
52
|
+
process.exit(2);
|
|
53
|
+
}
|
|
54
|
+
version = bumpVersion(version, level);
|
|
55
|
+
manifest.version = version;
|
|
56
|
+
fs_1.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
|
|
57
|
+
console.log(`Bumped version to ${version}`);
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
console.log(version);
|
|
61
|
+
});
|
|
62
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const create_1 = require("./commands/create");
|
|
6
|
+
const run_1 = require("./commands/run");
|
|
7
|
+
const validate_1 = require("./commands/validate");
|
|
8
|
+
const pack_1 = require("./commands/pack");
|
|
9
|
+
const test_1 = require("./commands/test");
|
|
10
|
+
const version_1 = require("./commands/version");
|
|
11
|
+
const publish_1 = require("./commands/publish");
|
|
12
|
+
const help_1 = require("./commands/help");
|
|
13
|
+
const pkg = require('../package.json');
|
|
14
|
+
const program = new commander_1.Command();
|
|
15
|
+
program.name('bdk').version(pkg.version).description('BoldDesk Developer Kit CLI');
|
|
16
|
+
(0, create_1.registerCreate)(program);
|
|
17
|
+
(0, run_1.registerRun)(program);
|
|
18
|
+
(0, validate_1.registerValidate)(program);
|
|
19
|
+
(0, pack_1.registerPack)(program);
|
|
20
|
+
(0, test_1.registerTest)(program);
|
|
21
|
+
(0, version_1.registerVersion)(program);
|
|
22
|
+
(0, publish_1.registerPublish)(program);
|
|
23
|
+
(0, help_1.registerHelp)(program);
|
|
24
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateAppPath = validateAppPath;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function validateAppPath(appPath) {
|
|
10
|
+
const resolved = path_1.default.resolve(appPath);
|
|
11
|
+
if (!fs_1.default.existsSync(resolved))
|
|
12
|
+
throw new Error(`App path does not exist: ${resolved}`);
|
|
13
|
+
const manifest = path_1.default.join(resolved, 'manifest.json');
|
|
14
|
+
if (!fs_1.default.existsSync(manifest))
|
|
15
|
+
throw new Error(`manifest.json not found in ${resolved}`);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* BoldDesk LocalStore - Persistent local data storage during development
|
|
4
|
+
*
|
|
5
|
+
* Similar to Freshdesk FDK's DataStore (lib/utils/data.js)
|
|
6
|
+
* Stores key-value data in .bolddesk/localstore JSON file
|
|
7
|
+
*
|
|
8
|
+
* Key Format: '1234' or '1234:{jiraId:9878}' (first part is the key)
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.LocalStore = void 0;
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
/**
|
|
48
|
+
* LocalStore class for managing persistent local storage
|
|
49
|
+
* Mirrors Freshdesk's DataStore functionality
|
|
50
|
+
*/
|
|
51
|
+
class LocalStore {
|
|
52
|
+
constructor(filePath = '.bdk/localstore') {
|
|
53
|
+
this.data = {};
|
|
54
|
+
this.filePath = filePath;
|
|
55
|
+
this.ensureStore();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Ensure localstore folder and file exist
|
|
59
|
+
* Creates .bolddesk folder if needed
|
|
60
|
+
* Creates empty JSON file if needed
|
|
61
|
+
*/
|
|
62
|
+
ensureStore() {
|
|
63
|
+
const folder = path.dirname(this.filePath);
|
|
64
|
+
if (!fs.existsSync(folder)) {
|
|
65
|
+
fs.mkdirSync(folder, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
if (!fs.existsSync(this.filePath)) {
|
|
68
|
+
fs.writeFileSync(this.filePath, JSON.stringify({}));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Validate key format and constraints
|
|
73
|
+
* - Max 60 characters
|
|
74
|
+
* - Cannot be empty
|
|
75
|
+
* - Alphanumeric, dash, underscore, colon allowed
|
|
76
|
+
*/
|
|
77
|
+
validateKey(key) {
|
|
78
|
+
if (!key || typeof key !== 'string') {
|
|
79
|
+
throw new Error('The key cannot be blank');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Read localstore file from disk
|
|
84
|
+
* Returns parsed JSON object
|
|
85
|
+
* Returns empty object on error
|
|
86
|
+
*/
|
|
87
|
+
readLocalStore() {
|
|
88
|
+
try {
|
|
89
|
+
if (!fs.existsSync(this.filePath)) {
|
|
90
|
+
return {};
|
|
91
|
+
}
|
|
92
|
+
const content = fs.readFileSync(this.filePath, 'utf-8');
|
|
93
|
+
return JSON.parse(content);
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
console.error(`[LocalStore] Error reading file: ${e.message}`);
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Write localstore file to disk
|
|
102
|
+
* Pretty-prints JSON for human readability
|
|
103
|
+
*/
|
|
104
|
+
writeLocalStore(data) {
|
|
105
|
+
try {
|
|
106
|
+
fs.writeFileSync(this.filePath, JSON.stringify(data, null, 2));
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
console.error(`[LocalStore] Error writing file: ${e.message}`);
|
|
110
|
+
throw e;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Store operation - SET key/value
|
|
115
|
+
* Stores data as-is without modification
|
|
116
|
+
*
|
|
117
|
+
* @param key Storage key (e.g., 'ticket-001')
|
|
118
|
+
* @param data Value to store (JSON object)
|
|
119
|
+
* @returns { Created: true }
|
|
120
|
+
*/
|
|
121
|
+
store(key, data) {
|
|
122
|
+
this.validateKey(key);
|
|
123
|
+
const localStoreData = this.readLocalStore();
|
|
124
|
+
localStoreData[key] = data;
|
|
125
|
+
this.writeLocalStore(localStoreData);
|
|
126
|
+
return { Created: true };
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Fetch operation - GET key/value
|
|
130
|
+
* Retrieves stored data for a key
|
|
131
|
+
*
|
|
132
|
+
* @param key Storage key to retrieve
|
|
133
|
+
* @returns Stored data or undefined if not found
|
|
134
|
+
*/
|
|
135
|
+
fetch(key) {
|
|
136
|
+
const localStoreData = this.readLocalStore();
|
|
137
|
+
return localStoreData[key];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Update operation - PATCH key with new values
|
|
141
|
+
* Merges attributes with existing data
|
|
142
|
+
*
|
|
143
|
+
* @param key Storage key to update
|
|
144
|
+
* @param attributes Object with fields to merge
|
|
145
|
+
* @returns { Updated: true }
|
|
146
|
+
*/
|
|
147
|
+
update(key, attributes) {
|
|
148
|
+
this.validateKey(key);
|
|
149
|
+
const localStoreData = this.readLocalStore();
|
|
150
|
+
const existingRecord = localStoreData[key];
|
|
151
|
+
if (!existingRecord) {
|
|
152
|
+
throw new Error(`Record not found for key: ${key}`);
|
|
153
|
+
}
|
|
154
|
+
localStoreData[key] = { ...existingRecord, ...attributes };
|
|
155
|
+
this.writeLocalStore(localStoreData);
|
|
156
|
+
return { Updated: true };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Delete operation - DELETE key
|
|
160
|
+
* Similar to Freshdesk DataStore.delete()
|
|
161
|
+
*
|
|
162
|
+
* @param key Storage key to delete
|
|
163
|
+
* @returns { Deleted: true }
|
|
164
|
+
*/
|
|
165
|
+
delete(key) {
|
|
166
|
+
const localStoreData = this.readLocalStore();
|
|
167
|
+
delete localStoreData[key];
|
|
168
|
+
this.writeLocalStore(localStoreData);
|
|
169
|
+
return { Deleted: true };
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get the file path to localstore
|
|
173
|
+
*/
|
|
174
|
+
getFilePath() {
|
|
175
|
+
return this.filePath;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get all stored data (for debugging)
|
|
179
|
+
*/
|
|
180
|
+
getAll() {
|
|
181
|
+
return this.readLocalStore();
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Clear all data from localstore
|
|
185
|
+
*/
|
|
186
|
+
clear() {
|
|
187
|
+
this.writeLocalStore({});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
exports.LocalStore = LocalStore;
|