Files
api/plugin/builder/build-vendor-store.ts
Eli Bosley 4f63b4cf3b feat: native slackware package (#1381)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added detailed versioning for plugin packages incorporating
architecture and build identifiers.
- Simplified and improved install/uninstall scripts with backup and
dynamic package detection.
- Introduced comprehensive setup, verification, patching, and cleanup
scripts for the Unraid API environment.
- Enhanced service control with explicit start, stop, restart, and
status commands.
- Added robust dependency management scripts for restoring and archiving
Node.js modules.
- Implemented vendor archive metadata storage and dynamic handling
during build and runtime.
- Added new CLI options and environment schemas for consistent build
configuration.
- Introduced new shutdown scripts to gracefully stop flash-backup and
unraid-api services.
- Added utility scripts for API version detection and vendor archive
configuration.
- Added a new package description file detailing Unraid API features and
homepage link.

- **Bug Fixes**
- Improved validation and error reporting for missing manifests,
dependencies, and configuration files.
  - Enhanced fallback logic for locating and creating vendor archives.
- Fixed iframe compatibility in UI by updating HTML and Firefox
preference files.

- **Chores**
- Updated .gitignore with generated file patterns for Node.js binaries
and archives.
  - Removed obsolete internal documentation and legacy cleanup scripts.
- Refined Docker Compose and CI workflows to pass precise API versioning
and manage build artifacts.
- Centralized common environment validation and CLI option definitions
across build tools.
- Cleaned up plugin manifest by removing Node.js and PNPM-related
entities and legacy logic.
- Improved logging and error handling in build and installation scripts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-05-08 22:54:10 -04:00

104 lines
4.1 KiB
TypeScript

import { deployDir, vendorStorePath } from "./utils/paths";
import { join } from "path";
import { existsSync, mkdirSync } from "node:fs";
import { startingDir } from "./utils/consts";
import { copyFile, stat } from "node:fs/promises";
import { execSync } from "child_process";
/**
* The name of the node_modules archive that will be vendored with the plugin.
* @param version API version to use in the filename
* @returns The name of the node_modules bundle file
*/
export function getVendorBundleName(version: string): string {
return `node_modules-for-v${version}.tar.xz`;
}
/**
* Get the full path where the vendor bundle should be stored
* @param version API version to use in the filename
* @returns The full path to the vendor bundle
*/
export function getVendorFullPath(version: string): string {
return join(vendorStorePath, getVendorBundleName(version));
}
/**
* Create a tarball of the node_modules for local development
* @param outputPath Path to write the tarball to
*/
async function createNodeModulesTarball(outputPath: string): Promise<void> {
console.log(`Creating node_modules tarball at ${outputPath}`);
try {
// Create a tarball of the node_modules directly from the API directory
const apiNodeModules = join(process.cwd(), "..", "api", "node_modules");
if (existsSync(apiNodeModules)) {
console.log(`Found API node_modules at ${apiNodeModules}, creating tarball...`);
execSync(`tar -cJf "${outputPath}" -C "${join(process.cwd(), "..", "api")}" node_modules`);
console.log(`Successfully created node_modules tarball at ${outputPath}`);
return;
}
throw new Error(`API node_modules not found at ${apiNodeModules}`);
} catch (error) {
console.error(`Failed to create node_modules tarball: ${error}`);
throw error;
}
}
/**
* Prepare a versioned bundle of the API's node_modules to vendor dependencies.
*
* It first tries to use the `packed-node-modules.tar.xz` from the mounted volume.
* If that fails, it checks the parent API directory and tries to create a tarball from node_modules.
*
* After this operation, the vendored node_modules will be available inside the `deployDir`.
*
* @param apiVersion Required API version to use for the vendor bundle
*/
export async function bundleVendorStore(apiVersion: string): Promise<void> {
// Ensure deploy directory exists
mkdirSync(deployDir, { recursive: true });
const vendorStoreTarPath = join(deployDir, getVendorBundleName(apiVersion));
// Possible locations for the node modules archive
const possibleLocations = [
join(startingDir, "node-modules-archive/packed-node-modules.tar.xz"), // Docker mount
join(process.cwd(), "..", "api", "deploy", "node-modules-archive", "packed-node-modules.tar.xz") // Direct path to API deploy
];
let foundArchive = false;
for (const archivePath of possibleLocations) {
try {
console.log(`Checking for vendor store at ${archivePath}`);
if (!existsSync(archivePath)) {
console.log(`Archive not found at ${archivePath}`);
continue;
}
const stats = await stat(archivePath);
if (!stats.isFile()) {
console.log(`${archivePath} exists but is not a file`);
continue;
}
console.log(`Copying vendor store from ${archivePath} to ${vendorStoreTarPath}`);
await copyFile(archivePath, vendorStoreTarPath);
console.log(`Successfully copied vendor store to ${vendorStoreTarPath}`);
foundArchive = true;
break;
} catch (error) {
console.log(`Error checking ${archivePath}: ${error}`);
}
}
if (!foundArchive) {
console.log("Could not find existing node_modules archive, attempting to create one");
// Create a temporary archive in the deploy directory
const tempArchivePath = join(deployDir, "temp-node-modules.tar.xz");
await createNodeModulesTarball(tempArchivePath);
await copyFile(tempArchivePath, vendorStoreTarPath);
}
}