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.
@@ -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;