@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 +78 -22
- package/dist/index.js +34 -10
- package/dist/workers/bcrypt-worker.js +12 -0
- package/dist/workers/validator-worker.js +82 -0
- package/dist/workers/vm-worker.js +25 -0
- package/package.json +4 -4
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
9
|
+
npm install -g @scriptdb/cli
|
|
10
|
+
# or
|
|
11
|
+
bun add -g @scriptdb/cli
|
|
25
12
|
```
|
|
26
13
|
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
Install from source:
|
|
29
15
|
```bash
|
|
16
|
+
git clone <repo>
|
|
17
|
+
cd scriptdb
|
|
30
18
|
bun install
|
|
31
|
-
bun run build
|
|
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
|
-
|
|
95215
|
-
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
42
|
-
"@scriptdb/server": "^1.0.
|
|
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",
|