Merge pull request #215 from PR0M3TH3AN/feat/offline-bundle-7151517603269259215

feat: Add Offline Bundle to Landing Page
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-17 10:10:02 -05:00
commit 5704eec127
3 files changed
+79

No files matched your search

+32
View File
@@ -307,3 +307,35 @@ The lock CLI resolves roster names in this order:
2. Stop memory maintenance scheduler processes.
3. Preserve database state for post-incident analysis; do not drop or rewrite memory tables during rollback.
4. Keep prune actions in `dry-run` (or disabled) until lifecycle policy and data integrity are revalidated.
## Offline & Air-Gapped Installation
TORCH is designed to operate in diverse environments, including high-security, air-gapped, or offline networks where direct access to the npm registry is restricted.
### The Offline Bundle
The "Offline Bundle" is a standard npm package tarball (`.tgz`) generated during the build process. It contains the complete source code and dependency definitions required to run TORCH.
**Why use the bundle?**
1. **Security & Integrity:** You can verify the checksum of the tarball before installing it. It creates a frozen snapshot of the code that doesn't change.
2. **No Registry Dependency:** You can install it directly using `npm install ./torch-lock-0.1.0.tgz` without needing to connect to `registry.npmjs.org`.
3. **Project Integration:** Unlike a binary executable, the tarball installs TORCH as a standard dependency in your `package.json`. This ensures:
* Scripts like `npm run lock:check` work natively.
* TORCH versioning is managed alongside your other dependencies.
* It works across all operating systems that support Node.js.
### Installation Instructions
1. Download the tarball from the landing page or your internal artifact repository.
2. Place it in your project root or a `vendor/` directory.
3. Run the install command:
```bash
npm install ./torch-lock-0.1.0.tgz
```
*(Replace `0.1.0` with the actual version number)*
4. Initialize TORCH:
```bash
npx torch-lock init
```
+22
View File
@@ -1,6 +1,7 @@
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { execSync } from 'child_process';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@@ -15,6 +16,10 @@ const PROMPTS_SRC = path.join(__dirname, 'src', 'prompts', 'META_PROMPTS.md');
const CONFIG_SRC = path.join(__dirname, 'torch-config.json');
const ASSETS_SRC = path.join(__dirname, 'assets');
// Read package.json to get version and name
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
const tarballName = `${packageJson.name}-${packageJson.version}.tgz`;
// Ensure clean slate
if (fs.existsSync(DIST_DIR)) {
fs.rmSync(DIST_DIR, { recursive: true, force: true });
@@ -32,6 +37,9 @@ distHtml = distHtml.replace(/"\.\.\/dashboard\/"/g, '"dashboard/"'); // Link to
distHtml = distHtml.replace(/'\.\.\/src\/docs\/TORCH\.md'/g, "'src/docs/TORCH.md'");
distHtml = distHtml.replace(/"\.\.\/assets\//g, '"assets/');
// Inject Offline Bundle Filename
distHtml = distHtml.replace(/{{OFFLINE_BUNDLE_FILENAME}}/g, tarballName);
fs.writeFileSync(path.join(DIST_DIR, 'index.html'), distHtml);
// 2. Copy dashboard/ -> dist/dashboard/
@@ -71,4 +79,18 @@ if (fs.existsSync(ASSETS_SRC)) {
fs.cpSync(ASSETS_SRC, distAssets, { recursive: true });
}
// 7. Generate NPM Pack Tarball
console.log('Generating npm package tarball...');
try {
execSync('npm pack', { stdio: 'inherit' });
if (fs.existsSync(tarballName)) {
fs.renameSync(tarballName, path.join(DIST_DIR, tarballName));
console.log(`Moved ${tarballName} to dist/`);
} else {
console.error(`Error: ${tarballName} not found after npm pack.`);
}
} catch (error) {
console.error('Error packing npm module:', error);
}
console.log('Build complete! Output directory: dist/');
+25
View File
@@ -661,6 +661,31 @@ npm install https://github.com/PR0M3TH3AN/TORCH/archive/refs/heads/main.tar.gz &
Copy
</button>
</div>
<div style="margin-top: 4rem; text-align: center; width: 100%; max-width: 600px; padding-top: 2rem; border-top: 1px solid var(--border);">
<h3 style="font-size: 1.25rem; margin-bottom: 0.5rem; color: var(--text-strong);">Running Offline or Air-Gapped?</h3>
<p style="color: var(--muted); margin-bottom: 1.5rem; font-size: 0.95rem;">Download the standalone bundle and install it directly without registry access.</p>
<a href="{{OFFLINE_BUNDLE_FILENAME}}" download class="cta-button secondary" style="margin-bottom: 1.5rem;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 0.5rem;">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="7 10 12 15 17 10"></polyline>
<line x1="12" y1="15" x2="12" y2="3"></line>
</svg>
Download Bundle
</a>
<div class="install-code-wrapper" style="margin: 0 auto; max-width: 450px;">
<code id="offline-cmd">npm install ./{{OFFLINE_BUNDLE_FILENAME}}</code>
<button class="copy-install-btn" onclick="copyToClipboard('offline-cmd', this)">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
Copy
</button>
</div>
</div>
</div>
<section class="features">