@scriptdb/cli 1.0.7 → 1.0.9

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 CHANGED
@@ -4,31 +4,20 @@ Command-line interface for ScriptDB - Database management with TypeScript script
4
4
 
5
5
  ## Installation
6
6
 
7
- ### From Binary (Info Only)
8
-
9
- Pre-built binaries are available for download:
10
-
11
- - **Linux x64**: `scriptdb-linux-x64`
12
- - **Linux ARM64**: `scriptdb-linux-arm64`
13
- - **Linux x64 (musl)**: `scriptdb-linux-x64-musl`
14
- - **Linux ARM64 (musl)**: `scriptdb-linux-arm64-musl`
15
- - **macOS x64 (Intel)**: `scriptdb-darwin-x64`
16
- - **macOS ARM64 (Apple Silicon)**: `scriptdb-darwin-arm64`
17
- - **Windows x64**: `scriptdb-windows-x64.exe`
18
-
19
- **Note**: These binaries are standalone info-only builds. They show help/version but don't include server functionality. For full functionality, install from source.
20
-
21
- Make it executable (Linux/macOS):
7
+ Install from npm:
22
8
  ```bash
23
- chmod +x scriptdb-*
24
- sudo mv scriptdb-* /usr/local/bin/scriptdb
9
+ npm install -g @scriptdb/cli
10
+ # or
11
+ bun add -g @scriptdb/cli
25
12
  ```
26
13
 
27
- ### From Source (Recommended for Full Functionality)
28
-
14
+ Install from source:
29
15
  ```bash
16
+ git clone <repo>
17
+ cd scriptdb
30
18
  bun install
31
- bun run build:all
19
+ bun run build
20
+ npm link
32
21
  ```
33
22
 
34
23
  ## Usage
@@ -109,6 +98,55 @@ Example:
109
98
  }
110
99
  ```
111
100
 
101
+ ### Package Management
102
+
103
+ Install packages to ScriptDB:
104
+ ```bash
105
+ # Install to ~/.scriptdb/packages
106
+ scriptdb add lodash
107
+ scriptdb add axios express
108
+
109
+ # Install to current directory
110
+ scriptdb add --local lodash
111
+ ```
112
+
113
+ Remove packages:
114
+ ```bash
115
+ # Remove from ~/.scriptdb/packages
116
+ scriptdb remove lodash
117
+
118
+ # Remove from current directory
119
+ scriptdb remove --local lodash
120
+ ```
121
+
122
+ ### Monitoring
123
+
124
+ View real-time logs:
125
+ ```bash
126
+ scriptdb logs
127
+ ```
128
+
129
+ Monitor performance (CPU, memory, uptime):
130
+ ```bash
131
+ scriptdb monit
132
+ ```
133
+
134
+ ## Commands
135
+
136
+ | Command | Description |
137
+ |---------|-------------|
138
+ | `scriptdb start [-d]` | Start server (`-d` for daemon/PM2 mode) |
139
+ | `scriptdb stop` | Stop the running server |
140
+ | `scriptdb restart [-d]` | Restart the server |
141
+ | `scriptdb status` | Check server status and view metrics |
142
+ | `scriptdb logs` | View real-time logs |
143
+ | `scriptdb monit` | Monitor performance (CPU, memory, uptime) |
144
+ | `scriptdb shell` | Start interactive shell |
145
+ | `scriptdb add <pkg>` | Install packages to ~/.scriptdb |
146
+ | `scriptdb add --local <pkg>` | Install packages to current directory |
147
+ | `scriptdb remove <pkg>` | Remove packages from ~/.scriptdb |
148
+ | `scriptdb remove --local <pkg>` | Remove packages from current directory |
149
+
112
150
  ## Building
113
151
 
114
152
  ### Build for all platforms (local)
@@ -145,10 +183,28 @@ bun run dev
145
183
 
146
184
  ## Files
147
185
 
148
- - PID file: `~/.scriptdb/scriptdb.pid`
149
- - Log file: `~/.scriptdb/scriptdb.log`
150
186
  - Config file: `~/.scriptdb/config.json`
187
+ - Ecosystem config: `~/.scriptdb/ecosystem.config.js` (PM2)
188
+ - PM2 logs: `~/.scriptdb/pm2-*.log`
151
189
  - Databases: `~/.scriptdb/databases/`
190
+ - Packages: `~/.scriptdb/packages/`
191
+
192
+ ## Changelog
193
+
194
+ ### 1.0.9 (2025-01-16)
195
+
196
+ **Added**
197
+ - Native `scriptdb logs` command to view real-time logs
198
+ - Native `scriptdb monit` command to monitor performance
199
+ - Native `scriptdb restart` command to restart the server
200
+ - Native `scriptdb stop` command to stop the server
201
+ - Dynamic version reading from package.json
202
+ - ESLint configuration for TypeScript linting
203
+
204
+ **Fixed**
205
+ - Fixed TypeScript module resolution errors
206
+ - Fixed test command to continue gracefully when packages have no tests
207
+ - Improved error handling and Windows compatibility
152
208
 
153
209
  ## License
154
210
 
package/dist/index.js CHANGED
@@ -95211,9 +95211,8 @@ export const ${databaseName} = {};
95211
95211
  if (this.users && Array.isArray(this.users) && this.users.length > 0) {
95212
95212
  const u = this.users[0] || { username: "" };
95213
95213
  const uname = u.username || null;
95214
- const pwd = typeof u.password === "string" && u.password ? u.password : null;
95215
- if (uname && pwd) {
95216
- cred = encodeURIComponent(String(uname)) + ":" + encodeURIComponent(String(pwd)) + "@";
95214
+ if (uname && typeof u.password === "string" && u.password) {
95215
+ cred = encodeURIComponent(String(uname)) + ":" + "*****" + "@";
95217
95216
  } else if (uname) {
95218
95217
  cred = encodeURIComponent(String(uname)) + "@";
95219
95218
  }
@@ -95254,7 +95253,7 @@ import { spawn } from "node:child_process";
95254
95253
  import Storage from "@scriptdb/storage";
95255
95254
  var pkgData = `{
95256
95255
  "name": "scriptdb-workspace",
95257
- "version": "1.0.7",
95256
+ "version": "1.0.9",
95258
95257
  "description": "ScriptDB workspace for custom scripts, services, and databases",
95259
95258
  "private": true,
95260
95259
  "devDependencies": {
@@ -95300,6 +95299,7 @@ var tsconfigData = `
95300
95299
  var dotGitignoreData = `
95301
95300
  # Ignore all files in this directory
95302
95301
  node_modules/
95302
+ bin/
95303
95303
  `;
95304
95304
  var ecosystemData = `
95305
95305
  module.exports = {
@@ -95603,7 +95603,7 @@ class ScriptDBClient {
95603
95603
  parsed.password = "";
95604
95604
  this.uri = parsed.toString();
95605
95605
  } catch (e) {
95606
- this.uri = normalized;
95606
+ this.uri = uri;
95607
95607
  }
95608
95608
  this.host = parsed.hostname || "localhost";
95609
95609
  this.port = parsed.port ? parseInt(parsed.port, 10) : 1234;
@@ -95694,6 +95694,12 @@ class ScriptDBClient {
95694
95694
  this._connecting = null;
95695
95695
  return reject(error);
95696
95696
  }
95697
+ if (!this.client) {
95698
+ const error = new Error("Failed to create client socket");
95699
+ this.logger?.error?.("Connection failed", error.message);
95700
+ this._connecting = null;
95701
+ return reject(error);
95702
+ }
95697
95703
  const onError = (err) => {
95698
95704
  this.logger?.error?.("Client socket error:", err && err.message ? err.message : err);
95699
95705
  this._handleDisconnect(err);
@@ -95704,7 +95710,7 @@ class ScriptDBClient {
95704
95710
  };
95705
95711
  this.client.on("error", onError);
95706
95712
  this.client.on("close", onClose);
95707
- if (this.socketTimeout > 0) {
95713
+ if (this.socketTimeout > 0 && this.client) {
95708
95714
  this.client.setTimeout(this.socketTimeout);
95709
95715
  this.client.on("timeout", () => {
95710
95716
  this.logger?.warn?.("Socket timeout, destroying connection");
@@ -96561,8 +96567,23 @@ async function server() {
96561
96567
  allowed.host = parsedConfig.host;
96562
96568
  if (parsedConfig.port !== undefined)
96563
96569
  allowed.port = parsedConfig.port;
96564
- if (parsedConfig.users !== undefined)
96565
- allowed.users = parsedConfig.users;
96570
+ if (parsedConfig.users !== undefined) {
96571
+ if (Array.isArray(parsedConfig.users)) {
96572
+ if (parsedConfig.users.length === 0) {
96573
+ allowed.users = [];
96574
+ } else if (typeof parsedConfig.users[0] === "string") {
96575
+ allowed.users = parsedConfig.users.map((username) => ({
96576
+ username,
96577
+ password: "",
96578
+ hash: false
96579
+ }));
96580
+ } else {
96581
+ allowed.users = parsedConfig.users;
96582
+ }
96583
+ } else {
96584
+ allowed.users = [parsedConfig.users];
96585
+ }
96586
+ }
96566
96587
  if (typeof parsedConfig.folder === "string")
96567
96588
  allowed.folder = parsedConfig.folder;
96568
96589
  if (typeof parsedConfig.secure === "boolean")
@@ -96629,7 +96650,7 @@ async function server() {
96629
96650
  } catch (err) {
96630
96651
  exitWithError("Failed to initialize VM", err);
96631
96652
  }
96632
- let storage;
96653
+ let storage = null;
96633
96654
  try {
96634
96655
  storage = new Storage2(baseDir, basePath);
96635
96656
  await storage.initialize();
@@ -96637,6 +96658,9 @@ async function server() {
96637
96658
  } catch (err) {
96638
96659
  exitWithError("Failed to initialize Storage", err);
96639
96660
  }
96661
+ if (!storage) {
96662
+ exitWithError("Storage was not initialized");
96663
+ }
96640
96664
  let scriptDBServer;
96641
96665
  try {
96642
96666
  scriptDBServer = new Protocal({
@@ -97271,7 +97295,7 @@ function ensureScriptDBDir() {
97271
97295
  if (!existsSync3(PACKAGE_JSON)) {
97272
97296
  const packageJsonContent = {
97273
97297
  name: "scriptdb-workspace",
97274
- version: "1.0.7",
97298
+ version: "1.0.9",
97275
97299
  description: "ScriptDB workspace for custom scripts, services, and databases",
97276
97300
  private: true,
97277
97301
  devDependencies: {
@@ -0,0 +1,12 @@
1
+ const { parentPort } = require('worker_threads');
2
+ const bcrypt = require('bcryptjs');
3
+
4
+ parentPort.on('message', async (msg) => {
5
+ const { id, password, hash } = msg;
6
+ try {
7
+ const ok = await bcrypt.compare(password, hash);
8
+ parentPort.postMessage({ id, ok });
9
+ } catch (e) {
10
+ parentPort.postMessage({ id, error: (e && e.message) || String(e) });
11
+ }
12
+ });
@@ -0,0 +1,82 @@
1
+ const { parentPort } = require('worker_threads');
2
+
3
+ // Lightweight validation + sanitization worker
4
+ // Expects messages: { id, action: 'validate', payload, options }
5
+
6
+ function shallowValidate(payload, schema, maxDepth = 4, maxNodes = 1000) {
7
+ const out = {};
8
+ let nodes = 0;
9
+ const checkDepth = (obj, depth) => {
10
+ if (depth > maxDepth) return false;
11
+ if (nodes++ > maxNodes) return false;
12
+ if (obj && typeof obj === 'object') {
13
+ for (const k of Object.keys(obj)) {
14
+ const expected = (schema || {})[k];
15
+ if (!expected) continue;
16
+ const val = obj[k];
17
+ if (expected === 'string' && typeof val === 'string') out[k] = val;
18
+ else if (expected === 'number' && typeof val === 'number') out[k] = val;
19
+ else if (expected === 'object' && val && typeof val === 'object') {
20
+ if (depth + 1 <= maxDepth) {
21
+ out[k] = {};
22
+ for (const nk of Object.keys(val)) {
23
+ if ((schema || {})[nk]) out[k][nk] = val[nk];
24
+ }
25
+ }
26
+ }
27
+ }
28
+ return true;
29
+ }
30
+ return false;
31
+ };
32
+ if (!checkDepth(payload, 0)) return {};
33
+ return out;
34
+ }
35
+
36
+ function sanitizeResult(res, opts) {
37
+ const allowedKeys = opts && opts.allowedKeys ? opts.allowedKeys : ['result', 'value', 'items', 'length', 'status', 'message'];
38
+ const maxNodes = opts && opts.maxNodes || 2000;
39
+ const maxDepth = opts && opts.maxDepth || 6;
40
+ const maxString = opts && opts.maxString || 1000;
41
+ let nodes = 0;
42
+ const rec = (input, depth = 0) => {
43
+ if (nodes++ > maxNodes) return '[REDACTED_NODES]';
44
+ if (depth > maxDepth) return '[REDACTED_DEPTH]';
45
+ if (input === null || input === undefined) return input;
46
+ if (typeof input === 'string') {
47
+ if (input.length > maxString) return input.slice(0, maxString) + '...[TRUNC]';
48
+ return input;
49
+ }
50
+ if (typeof input === 'number' || typeof input === 'boolean') return input;
51
+ if (Array.isArray(input)) return input.map((v) => rec(v, depth + 1));
52
+ if (typeof input === 'object') {
53
+ const out = {};
54
+ for (const k of Object.keys(input)) {
55
+ if (allowedKeys.includes(k)) out[k] = rec(input[k], depth + 1);
56
+ else out[k] = '[REDACTED]';
57
+ }
58
+ return out;
59
+ }
60
+ return '[REDACTED]';
61
+ };
62
+ return rec(res, 0);
63
+ }
64
+
65
+ parentPort.on('message', async (m) => {
66
+ if (!m || !m.id) return;
67
+ try {
68
+ if (m.action === 'validate') {
69
+ const allowed = shallowValidate(m.payload, m.options.schema, m.options.maxDepth, m.options.maxNodes);
70
+ parentPort.postMessage({ id: m.id, res: allowed });
71
+ return;
72
+ }
73
+ if (m.action === 'sanitize') {
74
+ const out = sanitizeResult(m.payload, m.options || {});
75
+ parentPort.postMessage({ id: m.id, res: out });
76
+ return;
77
+ }
78
+ parentPort.postMessage({ id: m.id, error: 'unknown action' });
79
+ } catch (e) {
80
+ parentPort.postMessage({ id: m.id, error: (e && e.message) || String(e) });
81
+ }
82
+ });
@@ -0,0 +1,25 @@
1
+ const { parentPort } = require('worker_threads');
2
+ const VMModule = require('@scriptdb/vm');
3
+ const VM = VMModule && VMModule.VM ? VMModule.VM : VMModule;
4
+
5
+ let vmInstance = null;
6
+
7
+ parentPort.on('message', async (msg) => {
8
+ const { id, action, options, payload } = msg;
9
+ try {
10
+ if (action === 'init') {
11
+ vmInstance = new VM(options || {});
12
+ parentPort.postMessage({ id, ok: true });
13
+ return;
14
+ }
15
+ if (action === 'run') {
16
+ if (!vmInstance) throw new Error('vm not initialized');
17
+ const res = await vmInstance.run(payload);
18
+ parentPort.postMessage({ id, res });
19
+ return;
20
+ }
21
+ parentPort.postMessage({ id, error: 'unknown action' });
22
+ } catch (e) {
23
+ parentPort.postMessage({ id, error: (e && e.message) || String(e) });
24
+ }
25
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptdb/cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "CLI tool to start and manage ScriptDB server",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,7 +13,7 @@
13
13
  ],
14
14
  "scripts": {
15
15
  "dev": "bun --watch src/index.ts",
16
- "build": "bun build src/index.ts --outdir dist --target node --format esm --external '@scriptdb/*'",
16
+ "build": "bun build src/index.ts --outdir dist --target node --format esm --external '@scriptdb/*' && node scripts/copy-workers.cjs",
17
17
  "build:types": "tsc --emitDeclarationOnly",
18
18
  "build:all": "bun run build && bun run build:types",
19
19
  "test": "bun test",
@@ -38,8 +38,8 @@
38
38
  "typescript": "^5.0.0"
39
39
  },
40
40
  "dependencies": {
41
- "@scriptdb/client": "^1.0.7",
42
- "@scriptdb/server": "^1.0.7",
41
+ "@scriptdb/client": "^1.0.9",
42
+ "@scriptdb/server": "^1.0.9",
43
43
  "bcryptjs": "^3.0.3",
44
44
  "bottleneck": "^2.19.5",
45
45
  "jsonwebtoken": "^9.0.3",