Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1241e4a333 | |||
| f93d3e2cfe | |||
| 78a5615bb5 | |||
| d4a100ff32 |
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"@git.zone/cli": {
|
||||
"projectType": "npm",
|
||||
"module": {
|
||||
"githost": "code.foss.global",
|
||||
"gitscope": "push.rocks",
|
||||
"gitrepo": "smartdeno",
|
||||
"description": "A module to run Deno scripts from Node.js, including functionalities for downloading Deno and executing Deno scripts.",
|
||||
"npmPackagename": "@push.rocks/smartdeno",
|
||||
"license": "MIT",
|
||||
"projectDomain": "push.rocks"
|
||||
},
|
||||
"release": {
|
||||
"registries": [
|
||||
"https://verdaccio.lossless.digital",
|
||||
"https://registry.npmjs.org"
|
||||
],
|
||||
"accessLevel": "public"
|
||||
}
|
||||
},
|
||||
"@git.zone/tsdoc": {
|
||||
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
||||
},
|
||||
"@ship.zone/szci": {
|
||||
"npmGlobalTools": [],
|
||||
"npmRegistryUrl": "registry.npmjs.org"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-04-30 - 1.2.1 - fix(smartdeno)
|
||||
normalize stderr output to an empty string and update build configuration
|
||||
|
||||
- Ensure executeScript always returns a string for stderr in both stdin and temp-file execution paths.
|
||||
- Adjust tests and TypeScript/build settings for stricter typing and updated toolchain compatibility.
|
||||
- Refresh package metadata and project configuration files, including registry and issue tracker settings.
|
||||
|
||||
## 2025-12-02 - 1.2.0 - feat(smartdeno)
|
||||
Run small scripts in-memory via stdin, fall back to temp files for large scripts; remove internal HTTP script server and simplify plugin dependencies; update API and docs.
|
||||
|
||||
- Execute scripts < 2MB via stdin (deno run -) to support fully in-memory execution with no disk I/O.
|
||||
- Automatically write scripts >= 2MB to a temp file under .nogit and clean up after execution.
|
||||
- Removed internal HTTP script server implementation and related types; start() no longer starts a script server.
|
||||
- Dropped plugin dependencies and exports related to @api.global/typedserver and @push.rocks/lik; plugins.ts simplified to only include necessary push.rocks modules and node path.
|
||||
- Updated package.json to remove unused dependencies and adjust keywords to reflect in-memory execution.
|
||||
- Updated README to document new start() behavior, in-memory execution, temp-file fallback, and simplified API signatures (start/stop/isRunning/executeScript).
|
||||
- ts index now only exports SmartDeno (removed direct type export of TDenoPermission from separate file).
|
||||
|
||||
## 2025-12-02 - 1.1.0 - feat(core)
|
||||
Add permission-controlled Deno execution, configurable script server port, improved downloader, dependency bumps and test updates
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2026 Task Venture Capital GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+14
-7
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"gitzone": {
|
||||
"@git.zone/cli": {
|
||||
"projectType": "npm",
|
||||
"module": {
|
||||
"githost": "code.foss.global",
|
||||
@@ -21,13 +21,20 @@
|
||||
"Ephemeral Execution",
|
||||
"Cross-platform"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"registries": [
|
||||
"https://verdaccio.lossless.digital",
|
||||
"https://registry.npmjs.org"
|
||||
],
|
||||
"accessLevel": "public"
|
||||
}
|
||||
},
|
||||
"npmci": {
|
||||
"npmGlobalTools": [],
|
||||
"npmAccessLevel": "public"
|
||||
},
|
||||
"tsdoc": {
|
||||
"@git.zone/tsdoc": {
|
||||
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
||||
},
|
||||
"@ship.zone/szci": {
|
||||
"npmGlobalTools": [],
|
||||
"npmRegistryUrl": "registry.npmjs.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-15
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@push.rocks/smartdeno",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.1",
|
||||
"private": false,
|
||||
"description": "A module to run Deno scripts from Node.js, including functionalities for downloading Deno and executing Deno scripts.",
|
||||
"main": "dist_ts/index.js",
|
||||
@@ -10,22 +10,20 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "(tstest test/ --verbose --timeout 60)",
|
||||
"build": "(tsbuild --web --allowimplicitany)",
|
||||
"build": "tsbuild --web",
|
||||
"buildDocs": "(tsdoc)"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@git.zone/tsbuild": "^3.1.2",
|
||||
"@git.zone/tsrun": "^2.0.0",
|
||||
"@git.zone/tstest": "^3.1.3",
|
||||
"@types/node": "^24.10.1"
|
||||
"@git.zone/tsbuild": "^4.4.0",
|
||||
"@git.zone/tsrun": "^2.0.3",
|
||||
"@git.zone/tstest": "^3.6.3",
|
||||
"@types/node": "^25.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@api.global/typedserver": "^4.0.0",
|
||||
"@push.rocks/lik": "^6.2.2",
|
||||
"@push.rocks/smartarchive": "^5.0.1",
|
||||
"@push.rocks/smartfs": "^1.2.0",
|
||||
"@push.rocks/smartarchive": "^5.2.2",
|
||||
"@push.rocks/smartfs": "^1.5.1",
|
||||
"@push.rocks/smartpath": "^6.0.0",
|
||||
"@push.rocks/smartshell": "^3.3.0",
|
||||
"@push.rocks/smartshell": "^3.3.8",
|
||||
"@push.rocks/smartunique": "^3.0.9"
|
||||
},
|
||||
"repository": {
|
||||
@@ -33,7 +31,7 @@
|
||||
"url": "https://code.foss.global/push.rocks/smartdeno.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://gitlab.com/push.rocks/smartdeno/issues"
|
||||
"url": "https://code.foss.global/push.rocks/smartdeno/issues"
|
||||
},
|
||||
"homepage": "https://code.foss.global/push.rocks/smartdeno",
|
||||
"browserslist": [
|
||||
@@ -48,6 +46,8 @@
|
||||
"dist_ts_web/**/*",
|
||||
"assets/**/*",
|
||||
"cli.js",
|
||||
".smartconfig.json",
|
||||
"license",
|
||||
"npmextra.json",
|
||||
"readme.md"
|
||||
],
|
||||
@@ -59,9 +59,9 @@
|
||||
"Development Tools",
|
||||
"Deno Download",
|
||||
"Code Execution",
|
||||
"Scripting Server",
|
||||
"Ephemeral Execution",
|
||||
"Cross-platform"
|
||||
"Cross-platform",
|
||||
"In-memory"
|
||||
],
|
||||
"packageManager": "pnpm@10.18.1+sha512.77a884a165cbba2d8d1c19e3b4880eee6d2fcabd0d879121e282196b80042351d5eb3ca0935fa599da1dc51265cc68816ad2bddd2a2de5ea9fdf92adbec7cd34"
|
||||
"packageManager": "pnpm@10.28.2"
|
||||
}
|
||||
|
||||
Generated
+2281
-1793
File diff suppressed because it is too large
Load Diff
@@ -43,9 +43,6 @@ await smartDeno.stop();
|
||||
await smartDeno.start({
|
||||
// Force download a local copy of Deno even if it's in PATH
|
||||
forceLocalDeno: true,
|
||||
|
||||
// Custom port for the internal script server (default: 3210)
|
||||
port: 4000,
|
||||
});
|
||||
```
|
||||
|
||||
@@ -153,7 +150,7 @@ const smartDeno = new SmartDeno();
|
||||
app.use(express.json());
|
||||
|
||||
// Initialize on startup
|
||||
await smartDeno.start({ port: 3211 });
|
||||
await smartDeno.start();
|
||||
|
||||
app.post('/execute', async (req, res) => {
|
||||
const { script, permissions } = req.body;
|
||||
@@ -180,8 +177,8 @@ app.listen(3000);
|
||||
SmartDeno works by:
|
||||
|
||||
1. **🦕 Deno Management** — Automatically downloads the latest Deno binary for your platform if not available or if `forceLocalDeno` is set
|
||||
2. **🖥️ Script Server** — Runs an internal HTTP server that serves scripts to Deno
|
||||
3. **⚡ Ephemeral Execution** — Each script execution is isolated and cleaned up after completion
|
||||
2. **💾 In-Memory Execution** — Scripts < 2MB are executed via stdin (`deno run -`), staying fully in-memory with no disk I/O
|
||||
3. **📁 Large Script Support** — Scripts >= 2MB automatically use a temp file (cleaned up after execution)
|
||||
4. **🔒 Permission Control** — Translates permission options to Deno's security flags
|
||||
|
||||
## 📚 API Reference
|
||||
@@ -198,8 +195,8 @@ const smartDeno = new SmartDeno();
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `start(options?)` | Initialize and start SmartDeno |
|
||||
| `stop()` | Stop SmartDeno and clean up resources |
|
||||
| `start(options?)` | Initialize SmartDeno (downloads Deno if needed) |
|
||||
| `stop()` | Stop SmartDeno instance |
|
||||
| `isRunning()` | Check if SmartDeno is currently running |
|
||||
| `executeScript(script, options?)` | Execute a Deno script |
|
||||
|
||||
@@ -208,7 +205,6 @@ const smartDeno = new SmartDeno();
|
||||
```typescript
|
||||
interface ISmartDenoOptions {
|
||||
forceLocalDeno?: boolean;
|
||||
port?: number;
|
||||
}
|
||||
|
||||
interface IExecuteScriptOptions {
|
||||
|
||||
@@ -15,6 +15,9 @@ tap.test('should throw when executing before start', async () => {
|
||||
await testSmartdeno.executeScript('console.log("test")');
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
if (!(e instanceof Error)) {
|
||||
throw e;
|
||||
}
|
||||
expect(e.message).toInclude('not started');
|
||||
}
|
||||
expect(threw).toBeTrue();
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartdeno',
|
||||
version: '1.1.0',
|
||||
version: '1.2.1',
|
||||
description: 'A module to run Deno scripts from Node.js, including functionalities for downloading Deno and executing Deno scripts.'
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import type { ScriptServer } from './classes.scriptserver.js';
|
||||
import * as plugins from './plugins.js';
|
||||
|
||||
export type TDenoPermission =
|
||||
| 'all'
|
||||
| 'env'
|
||||
| 'ffi'
|
||||
| 'hrtime'
|
||||
| 'net'
|
||||
| 'read'
|
||||
| 'run'
|
||||
| 'sys'
|
||||
| 'write';
|
||||
|
||||
export interface IDenoExecutionOptions {
|
||||
permissions?: TDenoPermission[];
|
||||
denoBinaryPath?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class contains logic to execute deno commands in an ephemeral way
|
||||
*/
|
||||
export class DenoExecution {
|
||||
public id: string;
|
||||
public scriptserverRef: ScriptServer;
|
||||
public script: string;
|
||||
public options: IDenoExecutionOptions;
|
||||
|
||||
constructor(scriptserverRef: ScriptServer, scriptArg: string, options: IDenoExecutionOptions = {}) {
|
||||
this.scriptserverRef = scriptserverRef;
|
||||
this.script = scriptArg;
|
||||
this.options = options;
|
||||
this.id = plugins.smartunique.shortId();
|
||||
}
|
||||
|
||||
private buildPermissionFlags(): string {
|
||||
const permissions = this.options.permissions || [];
|
||||
if (permissions.length === 0) {
|
||||
return '';
|
||||
}
|
||||
if (permissions.includes('all')) {
|
||||
return '-A';
|
||||
}
|
||||
return permissions.map(p => `--allow-${p}`).join(' ');
|
||||
}
|
||||
|
||||
public async execute(): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
||||
this.scriptserverRef.executionMap.add(this);
|
||||
|
||||
try {
|
||||
const denoBinary = this.options.denoBinaryPath || 'deno';
|
||||
const permissionFlags = this.buildPermissionFlags();
|
||||
const port = this.scriptserverRef.getPort();
|
||||
const scriptUrl = `http://localhost:${port}/getscript/${this.id}`;
|
||||
|
||||
const command = `${denoBinary} run ${permissionFlags} ${scriptUrl}`.replace(/\s+/g, ' ').trim();
|
||||
const result = await this.scriptserverRef.smartshellInstance.exec(command);
|
||||
|
||||
return {
|
||||
exitCode: result.exitCode,
|
||||
stdout: result.stdout,
|
||||
stderr: result.stderr,
|
||||
};
|
||||
} finally {
|
||||
// Clean up: remove from execution map after execution completes
|
||||
this.scriptserverRef.executionMap.remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
import type { DenoExecution } from './classes.denoexecution.js';
|
||||
import * as plugins from './plugins.js';
|
||||
|
||||
export interface IScriptServerOptions {
|
||||
port?: number;
|
||||
}
|
||||
|
||||
export class ScriptServer {
|
||||
private server: plugins.typedserver.servertools.Server;
|
||||
private port: number;
|
||||
public smartshellInstance = new plugins.smartshell.Smartshell({
|
||||
executor: 'bash'
|
||||
});
|
||||
|
||||
public executionMap = new plugins.lik.ObjectMap<DenoExecution>();
|
||||
|
||||
constructor(options: IScriptServerOptions = {}) {
|
||||
this.port = options.port ?? 3210;
|
||||
}
|
||||
|
||||
public getPort(): number {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public async start() {
|
||||
this.server = new plugins.typedserver.servertools.Server({
|
||||
port: this.port,
|
||||
cors: true,
|
||||
});
|
||||
this.server.addRoute(
|
||||
'/getscript/:executionId',
|
||||
new plugins.typedserver.servertools.Handler('GET', async (req, res) => {
|
||||
const executionId = req.params.executionId;
|
||||
const denoExecution = await this.executionMap.find(async denoExecutionArg => {
|
||||
return denoExecutionArg.id === executionId;
|
||||
});
|
||||
if (!denoExecution) {
|
||||
res.statusCode = 404;
|
||||
res.write('Execution not found');
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
res.write(denoExecution.script);
|
||||
res.end();
|
||||
})
|
||||
);
|
||||
await this.server.start();
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
if (this.server) {
|
||||
await this.server.stop();
|
||||
}
|
||||
this.executionMap.wipe();
|
||||
}
|
||||
}
|
||||
+101
-28
@@ -1,18 +1,25 @@
|
||||
import { DenoDownloader } from './classes.denodownloader.js';
|
||||
import * as plugins from './plugins.js';
|
||||
import * as paths from './paths.js';
|
||||
import { ScriptServer } from './classes.scriptserver.js';
|
||||
import { DenoExecution, type TDenoPermission } from './classes.denoexecution.js';
|
||||
|
||||
const MAX_STDIN_SIZE = 2 * 1024 * 1024; // 2MB threshold for stdin execution
|
||||
|
||||
export type TDenoPermission =
|
||||
| 'all'
|
||||
| 'env'
|
||||
| 'ffi'
|
||||
| 'hrtime'
|
||||
| 'net'
|
||||
| 'read'
|
||||
| 'run'
|
||||
| 'sys'
|
||||
| 'write';
|
||||
|
||||
export interface ISmartDenoOptions {
|
||||
/**
|
||||
* Force downloading a local copy of Deno even if it's available in PATH
|
||||
*/
|
||||
forceLocalDeno?: boolean;
|
||||
/**
|
||||
* Port for the internal script server (default: 3210)
|
||||
*/
|
||||
port?: number;
|
||||
}
|
||||
|
||||
export interface IExecuteScriptOptions {
|
||||
@@ -24,16 +31,14 @@ export interface IExecuteScriptOptions {
|
||||
|
||||
export class SmartDeno {
|
||||
private denoDownloader = new DenoDownloader();
|
||||
private scriptServer: ScriptServer;
|
||||
private denoBinaryPath: string | null = null;
|
||||
private isStarted = false;
|
||||
|
||||
constructor() {
|
||||
this.scriptServer = new ScriptServer();
|
||||
}
|
||||
private smartshellInstance = new plugins.smartshell.Smartshell({
|
||||
executor: 'bash',
|
||||
});
|
||||
|
||||
/**
|
||||
* Starts the SmartDeno instance
|
||||
* Starts the SmartDeno instance (downloads Deno if needed)
|
||||
* @param optionsArg Configuration options
|
||||
*/
|
||||
public async start(optionsArg: ISmartDenoOptions = {}): Promise<void> {
|
||||
@@ -41,11 +46,8 @@ export class SmartDeno {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create script server with configured port
|
||||
this.scriptServer = new ScriptServer({ port: optionsArg.port });
|
||||
|
||||
const denoAlreadyInPath = await plugins.smartshell.which('deno', {
|
||||
nothrow: true
|
||||
nothrow: true,
|
||||
});
|
||||
|
||||
if (!denoAlreadyInPath || optionsArg.forceLocalDeno) {
|
||||
@@ -56,19 +58,13 @@ export class SmartDeno {
|
||||
this.denoBinaryPath = 'deno';
|
||||
}
|
||||
|
||||
await this.scriptServer.start();
|
||||
this.isStarted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the SmartDeno instance and cleans up resources
|
||||
* Stops the SmartDeno instance
|
||||
*/
|
||||
public async stop(): Promise<void> {
|
||||
if (!this.isStarted) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.scriptServer.stop();
|
||||
this.isStarted = false;
|
||||
}
|
||||
|
||||
@@ -79,6 +75,19 @@ export class SmartDeno {
|
||||
return this.isStarted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build permission flags for Deno
|
||||
*/
|
||||
private buildPermissionFlags(permissions?: TDenoPermission[]): string {
|
||||
if (!permissions || permissions.length === 0) {
|
||||
return '';
|
||||
}
|
||||
if (permissions.includes('all')) {
|
||||
return '-A';
|
||||
}
|
||||
return permissions.map((p) => `--allow-${p}`).join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a Deno script
|
||||
* @param scriptArg The script content to execute
|
||||
@@ -93,11 +102,75 @@ export class SmartDeno {
|
||||
throw new Error('SmartDeno is not started. Call start() first.');
|
||||
}
|
||||
|
||||
const denoExecution = new DenoExecution(this.scriptServer, scriptArg, {
|
||||
permissions: options.permissions,
|
||||
denoBinaryPath: this.denoBinaryPath || undefined,
|
||||
});
|
||||
const denoBinary = this.denoBinaryPath || 'deno';
|
||||
const permissionFlags = this.buildPermissionFlags(options.permissions);
|
||||
const scriptSize = Buffer.byteLength(scriptArg, 'utf8');
|
||||
|
||||
return denoExecution.execute();
|
||||
if (scriptSize < MAX_STDIN_SIZE) {
|
||||
// Use stdin for small scripts (in-memory)
|
||||
return this.executeViaStdin(denoBinary, permissionFlags, scriptArg);
|
||||
} else {
|
||||
// Use temp file for large scripts
|
||||
return this.executeViaTempFile(denoBinary, permissionFlags, scriptArg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script via stdin (in-memory, for scripts < 2MB)
|
||||
* Uses `deno run -` which reads from stdin and supports all permission flags
|
||||
*/
|
||||
private async executeViaStdin(
|
||||
denoBinary: string,
|
||||
permissionFlags: string,
|
||||
script: string
|
||||
): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
||||
// Use base64 encoding to safely pass script through shell
|
||||
const base64Script = Buffer.from(script).toString('base64');
|
||||
const command = `echo '${base64Script}' | base64 -d | ${denoBinary} run ${permissionFlags} -`.trim().replace(/\s+/g, ' ');
|
||||
|
||||
const result = await this.smartshellInstance.exec(command);
|
||||
return {
|
||||
exitCode: result.exitCode,
|
||||
stdout: result.stdout,
|
||||
stderr: result.stderr ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script via temp file (for scripts >= 2MB)
|
||||
*/
|
||||
private async executeViaTempFile(
|
||||
denoBinary: string,
|
||||
permissionFlags: string,
|
||||
script: string
|
||||
): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
||||
const tempFileName = `deno_script_${plugins.smartunique.shortId()}.ts`;
|
||||
const tempFilePath = plugins.path.join(paths.nogitDir, tempFileName);
|
||||
const fsInstance = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
|
||||
|
||||
try {
|
||||
// Ensure .nogit directory exists
|
||||
await fsInstance.directory(paths.nogitDir).create();
|
||||
|
||||
// Write script to temp file
|
||||
await fsInstance.file(tempFilePath).write(script);
|
||||
|
||||
// Execute the script
|
||||
const command = `${denoBinary} run ${permissionFlags} "${tempFilePath}"`.trim().replace(/\s+/g, ' ');
|
||||
const result = await this.smartshellInstance.exec(command);
|
||||
|
||||
return {
|
||||
exitCode: result.exitCode,
|
||||
stdout: result.stdout,
|
||||
stderr: result.stderr ?? '',
|
||||
};
|
||||
} finally {
|
||||
// Clean up temp file
|
||||
try {
|
||||
await fsInstance.file(tempFilePath).delete();
|
||||
} catch {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from './classes.smartdeno.js';
|
||||
export type { TDenoPermission } from './classes.denoexecution.js';
|
||||
|
||||
+1
-10
@@ -5,15 +5,7 @@ export {
|
||||
path,
|
||||
}
|
||||
|
||||
// @api.global scope
|
||||
import * as typedserver from '@api.global/typedserver';
|
||||
|
||||
export {
|
||||
typedserver,
|
||||
}
|
||||
|
||||
// @push.rocks scope
|
||||
import * as lik from '@push.rocks/lik';
|
||||
import * as smartarchive from '@push.rocks/smartarchive';
|
||||
import * as smartfs from '@push.rocks/smartfs';
|
||||
import * as smartpath from '@push.rocks/smartpath';
|
||||
@@ -21,10 +13,9 @@ import * as smartshell from '@push.rocks/smartshell';
|
||||
import * as smartunique from '@push.rocks/smartunique';
|
||||
|
||||
export {
|
||||
lik,
|
||||
smartarchive,
|
||||
smartfs,
|
||||
smartpath,
|
||||
smartshell,
|
||||
smartunique,
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -5,10 +5,10 @@
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"noImplicitAny": true,
|
||||
"esModuleInterop": true,
|
||||
"verbatimModuleSyntax": true
|
||||
"verbatimModuleSyntax": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": [
|
||||
"dist_*/**/*.d.ts"
|
||||
]
|
||||
"exclude": ["dist_*/**/*.d.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user