UNPKG

vercel-php

Version:
187 lines (186 loc) 6.94 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.readRuntimeFile = exports.ensureLocalPhp = exports.runComposerScripts = exports.runComposerInstall = exports.modifyPhpIni = exports.getLauncherFiles = exports.getPhpFiles = void 0; const path_1 = __importDefault(require("path")); const child_process_1 = require("child_process"); const build_utils_1 = require("@vercel/build-utils"); const libphp = __importStar(require("@libphp/amazon-linux-2-v83")); const PHP_PKG = path_1.default.dirname(require.resolve('@libphp/amazon-linux-2-v83/package.json')); const PHP_BIN_DIR = path_1.default.join(PHP_PKG, "native/php"); const PHP_MODULES_DIR = path_1.default.join(PHP_BIN_DIR, "modules"); const PHP_LIB_DIR = path_1.default.join(PHP_PKG, "native/lib"); const COMPOSER_BIN = path_1.default.join(PHP_BIN_DIR, "composer"); async function getPhpFiles() { const files = await libphp.getFiles(); // Drop CGI + FPM from libphp, it's not needed for our case delete files['php/php-cgi']; delete files['php/php-fpm']; delete files['php/php-fpm.ini']; const runtimeFiles = {}; // Map from @libphp to Vercel's File objects for (const [filename, filepath] of Object.entries(files)) { runtimeFiles[filename] = new build_utils_1.FileFsRef({ fsPath: filepath }); } // Set some bins executable runtimeFiles['php/php'].mode = 33261; // 0755; runtimeFiles['php/composer'].mode = 33261; // 0755; return runtimeFiles; } exports.getPhpFiles = getPhpFiles; function getLauncherFiles() { const files = { 'helpers.js': new build_utils_1.FileFsRef({ fsPath: path_1.default.join(__dirname, 'launchers/helpers.js'), }) }; files['launcher.js'] = new build_utils_1.FileFsRef({ fsPath: path_1.default.join(__dirname, 'launchers/builtin.js'), }); return files; } exports.getLauncherFiles = getLauncherFiles; async function modifyPhpIni(userFiles, runtimeFiles) { // Validate user files contains php.ini if (!userFiles['api/php.ini']) return; // Validate runtime contains php.ini if (!runtimeFiles['php/php.ini']) return; const phpiniBlob = await build_utils_1.FileBlob.fromStream({ stream: runtimeFiles['php/php.ini'].toStream(), }); const userPhpiniBlob = await build_utils_1.FileBlob.fromStream({ stream: userFiles['api/php.ini'].toStream(), }); return new build_utils_1.FileBlob({ data: phpiniBlob.data.toString() .concat("; [User]\n") .concat(userPhpiniBlob.data.toString()) }); } exports.modifyPhpIni = modifyPhpIni; async function runComposerInstall(workPath) { console.log('🐘 Installing Composer dependencies [START]'); // @todo PHP_COMPOSER_INSTALL env await runPhp([ COMPOSER_BIN, 'install', '--profile', '--no-dev', '--no-interaction', '--no-scripts', '--ignore-platform-reqs', '--no-progress' ], { stdio: 'inherit', cwd: workPath }); console.log('🐘 Installing Composer dependencies [DONE]'); } exports.runComposerInstall = runComposerInstall; async function runComposerScripts(composerFile, workPath) { var _a; let composer; try { composer = JSON.parse(await readRuntimeFile(composerFile)); } catch (e) { console.error('🐘 Composer file is not valid JSON'); console.error(e); return; } if ((_a = composer === null || composer === void 0 ? void 0 : composer.scripts) === null || _a === void 0 ? void 0 : _a.vercel) { console.log('🐘 Running composer scripts [START]'); await runPhp([COMPOSER_BIN, 'run', 'vercel'], { stdio: 'inherit', cwd: workPath }); console.log('🐘 Running composer scripts [DONE]'); } } exports.runComposerScripts = runComposerScripts; async function ensureLocalPhp() { try { await spawnAsync('which', ['php', 'php-cgi'], { stdio: 'pipe' }); return true; } catch (e) { return false; } } exports.ensureLocalPhp = ensureLocalPhp; async function readRuntimeFile(file) { const blob = await build_utils_1.FileBlob.fromStream({ stream: file.toStream(), }); return blob.data.toString(); } exports.readRuntimeFile = readRuntimeFile; // ***************************************************************************** // PRIVATE API ***************************************************************** // ***************************************************************************** async function runPhp(args, opts = {}) { try { await spawnAsync('php', args, { ...opts, env: { ...process.env, ...(opts.env || {}), COMPOSER_HOME: '/tmp', PATH: `${PHP_BIN_DIR}:${process.env.PATH}`, PHP_INI_EXTENSION_DIR: PHP_MODULES_DIR, PHP_INI_SCAN_DIR: `:${path_1.default.resolve(__dirname, '../conf')}`, LD_LIBRARY_PATH: `${PHP_LIB_DIR}:/usr/lib64:/lib64:${process.env.LD_LIBRARY_PATH}` } }); } catch (e) { console.error(e); process.exit(1); } } function spawnAsync(command, args, opts = {}) { return new Promise((resolve, reject) => { const child = (0, child_process_1.spawn)(command, args, { stdio: "ignore", ...opts }); child.on('error', reject); child.on('exit', (code, signal) => { if (code === 0) { resolve(); } else { reject(new Error(`Exited with ${code || signal}`)); } }); }); }