UNPKG

@sap/ams-dev

Version:

NodesJS AMS development environment

143 lines (114 loc) 4.13 kB
const https = require("node:https"); const fs = require('node:fs'); const path = require('node:path'); const zlib = require("node:zlib"); const AMS_INSTANCE_HEADER = "X-Ams-Instance-Id"; const version = require("../../package.json").version; const USER_AGENT = `@sap/ams-dev:${version}`; function addDefaultHeaders(headers, credentials) { headers[AMS_INSTANCE_HEADER] = credentials.authorization_instance_id; headers["User-Agent"] = USER_AGENT; } function createHTTPSAgent(options) { return new https.Agent({ cert: options.certificate, key: options.key, }); } module.exports = { addDefaultHeaders, createHTTPSAgent, createTgzFromDirectory }; /** * Creates a .tgz archive from a directory (only .dcl files) * @param {string} dirPath - Directory to compress * @returns {Promise<Buffer>} - The compressed .tgz buffer */ async function createTgzFromDirectory(dirPath) { const files = await collectDclFiles(dirPath, dirPath); const tarBuffer = createTarArchive(files); return new Promise((resolve, reject) => { zlib.gzip(tarBuffer, (err, compressed) => { if (err) reject(err); else resolve(compressed); }); }); } /** * Recursively collect all .dcl files from a directory */ async function collectDclFiles(baseDir, currentDir) { const files = []; const entries = await fs.promises.readdir(currentDir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(currentDir, entry.name); if (entry.isDirectory()) { const subFiles = await collectDclFiles(baseDir, fullPath); files.push(...subFiles); } else if (entry.isFile() && entry.name.endsWith('.dcl')) { const relativePath = path.relative(baseDir, fullPath); const content = await fs.promises.readFile(fullPath); files.push({ name: relativePath.split(path.sep).join('/'), // Normalize to forward slashes content, mode: 0o644, mtime: Math.floor(Date.now() / 1000) }); } } return files; } /** * Create a tar archive from a list of files */ function createTarArchive(files) { const blocks = []; for (const file of files) { const header = createTarHeader(file.name, file.content.length, file.mode, file.mtime); blocks.push(header); // Add file content (padded to 512-byte blocks) const paddedSize = Math.ceil(file.content.length / 512) * 512; const contentBlock = Buffer.alloc(paddedSize); file.content.copy(contentBlock); blocks.push(contentBlock); } // Add two empty blocks to end the tar archive blocks.push(Buffer.alloc(512)); blocks.push(Buffer.alloc(512)); return Buffer.concat(blocks); } /** * Create a tar header for a file */ function createTarHeader(filename, size, mode, mtime) { const header = Buffer.alloc(512); // Filename (0-99) header.write(filename.slice(0, 100), 0); // File mode (100-107) - octal header.write(mode.toString(8).padStart(7, '0') + '\0', 100); // Owner UID (108-115) header.write('0000000\0', 108); // Owner GID (116-123) header.write('0000000\0', 116); // File size in octal (124-135) header.write(size.toString(8).padStart(11, '0') + '\0', 124); // Modification time (136-147) header.write(mtime.toString(8).padStart(11, '0') + '\0', 136); // Checksum placeholder (148-155) - spaces for calculation header.write(' ', 148); // Type flag (156) - '0' for regular file header[156] = 48; // ASCII '0' // Link name (157-256) - empty for regular files // USTAR magic (257-262) header.write('ustar\0', 257); // USTAR version (263-264) header.write('00', 263); // Calculate checksum (sum of all bytes in header, treating checksum field as spaces) let checksum = 0; for (let i = 0; i < 512; i++) { checksum += header[i]; } header.write(checksum.toString(8).padStart(6, '0') + '\0 ', 148); return header; }