@hynaweb/stage 1.0.5 → 1.3.0

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/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ Copyright (c) 2026 HYNAWEB. All Rights Reserved.
2
+
3
+ PROPRIETARY AND CONFIDENTIAL SOFTWARE.
4
+
5
+ This software and associated documentation files (the "Software") are the exclusive property of HYNAWEB.
6
+
7
+ No part of this Software may be copied, reproduced, modified, merged, published, distributed, sublicensed, sold, or used in any form without the prior written permission of HYNAWEB.
8
+
9
+ Unauthorized use, duplication, or distribution of this Software is strictly prohibited and may result in severe civil and criminal penalties.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # ⚔ HynaStage
2
+
3
+ **Ephemeral Firecracker MicroVMs in 5 seconds. Built on a $150 Android phone.**
4
+
5
+ AI agents write code in seconds, but provisioning staging environments takes minutes. HynaStage is a CLI that spins up isolated E2B sandboxes, deploys your HTML/code, and returns a live URL instantly. They auto-destroy after 1 hour to save costs.
6
+
7
+ ## šŸš€ Quick Start
8
+
9
+ ```bash
10
+ npm install -g @hynaweb/stage
11
+ hyna-stage up -f index.html --key=hyna_your_api_key
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { program } from 'commander';
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import chalk from 'chalk';
7
+ import ora from 'ora';
8
+ import inquirer from 'inquirer';
9
+
10
+ const DEPLOY_URL = "https://mczesspakhkomlnmfstw.supabase.co/functions/v1/deploy-stage";
11
+ const DESTROY_URL = "https://mczesspakhkomlnmfstw.supabase.co/functions/v1/destroy-stage";
12
+
13
+ program
14
+ .name('hyna-stage')
15
+ .description('Ephemeral cloud environments in 5 seconds.')
16
+ .version('1.0.7');
17
+
18
+ // ── UP COMMAND ──
19
+ program
20
+ .command('up')
21
+ .description('Deploy a file to a temporary HYNA environment')
22
+ .option('-f, --file <file>', 'File to deploy', 'index.html')
23
+ .option('-k, --key <key>', 'Your HYNA API key')
24
+ .action(async (options) => {
25
+ let apiKey = options.key;
26
+ if (!apiKey) {
27
+ const answers = await inquirer.prompt([
28
+ {
29
+ type: 'input',
30
+ name: 'key',
31
+ message: 'Enter your HYNA API Key:',
32
+ validate: (input) => input.length > 0 ? true : 'API Key is required'
33
+ }
34
+ ]);
35
+ apiKey = answers.key;
36
+ }
37
+
38
+ const filePath = path.resolve(process.cwd(), options.file);
39
+ if (!fs.existsSync(filePath)) {
40
+ console.error(chalk.red(`āŒ Error: File not found -> ${options.file}`));
41
+ process.exit(1);
42
+ }
43
+
44
+ const stats = fs.statSync(filePath);
45
+ const spinner = ora('Spinning up cloud environment...').start();
46
+
47
+ try {
48
+ let fileContent = fs.readFileSync(filePath);
49
+ const isLarge = stats.size > 50000;
50
+
51
+ if (isLarge) {
52
+ spinner.text = 'Encoding large file for transport...';
53
+ fileContent = fileContent.toString('base64');
54
+ } else {
55
+ fileContent = fileContent.toString('utf-8');
56
+ }
57
+
58
+ spinner.text = 'Deploying to E2B MicroVM...';
59
+
60
+ const response = await fetch(DEPLOY_URL, {
61
+ method: 'POST',
62
+ headers: {
63
+ 'Content-Type': 'application/json',
64
+ 'Authorization': `Bearer ${apiKey}`
65
+ },
66
+ body: JSON.stringify({ apiKey: apiKey, code: fileContent, isBase64: isLarge })
67
+ });
68
+
69
+ const data = await response.json();
70
+ if (!response.ok) throw new Error(data.error || `Server responded with ${response.status}`);
71
+
72
+ spinner.succeed(chalk.green('Environment is LIVE!'));
73
+
74
+ console.log('');
75
+ console.log(chalk.bgBlue.white.bold(` šŸ”— URL: ${data.url} `));
76
+ console.log(chalk.gray(` Sandbox ID: ${data.sandbox_id}`));
77
+ console.log(chalk.gray(` (Auto-destroys in 1 hour)\n`));
78
+
79
+ } catch (err) {
80
+ spinner.fail(chalk.red('Deployment failed'));
81
+ console.error(chalk.red(`\nāŒ ${err.message}\n`));
82
+ }
83
+ });
84
+
85
+ // ── DOWN COMMAND ──
86
+ program
87
+ .command('down')
88
+ .description('Destroy an active environment early')
89
+ .argument('<sandbox_id>', 'The Sandbox ID to destroy')
90
+ .option('-k, --key <key>', 'Your HYNA API key')
91
+ .action(async (sandboxId, options) => {
92
+ let apiKey = options.key;
93
+ if (!apiKey) {
94
+ const answers = await inquirer.prompt([
95
+ {
96
+ type: 'input',
97
+ name: 'key',
98
+ message: 'Enter your HYNA API Key:',
99
+ validate: (input) => input.length > 0 ? true : 'API Key is required'
100
+ }
101
+ ]);
102
+ apiKey = answers.key;
103
+ }
104
+
105
+ const spinner = ora(`Destroying sandbox ${sandboxId}...`).start();
106
+
107
+ try {
108
+ const response = await fetch(DESTROY_URL, {
109
+ method: 'POST',
110
+ headers: {
111
+ 'Content-Type': 'application/json',
112
+ 'Authorization': `Bearer ${apiKey}`
113
+ },
114
+ body: JSON.stringify({ sandbox_id: sandboxId })
115
+ });
116
+
117
+ const data = await response.json();
118
+ if (!response.ok) throw new Error(data.error || 'Failed to destroy sandbox');
119
+
120
+ spinner.succeed(chalk.green('Environment destroyed successfully!'));
121
+ console.log(chalk.gray(` The E2B VM has been terminated.\n`));
122
+ } catch (err) {
123
+ spinner.fail(chalk.red('Destroy failed'));
124
+ console.error(chalk.red(`\nāŒ ${err.message}\n`));
125
+ }
126
+ });
127
+
128
+ program.parse();
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@hynaweb/stage",
3
+ "version": "1.0.7",
4
+ "description": "Ephemeral cloud environments in 5 seconds.",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "hyna-stage": "./index.js"
8
+ },
9
+ "type": "module",
10
+ "dependencies": {
11
+ "chalk": "^5.3.0",
12
+ "commander": "^11.0.0",
13
+ "inquirer": "^9.2.12",
14
+ "ora": "^7.0.1"
15
+ }
16
+ }