UNPKG

@embeddable.com/sdk-core

Version:

Core Embeddable SDK module responsible for web-components bundling and publishing.

229 lines (201 loc) 6.45 kB
import * as fs from "node:fs/promises"; import { CREDENTIALS_DIR } from "./credentials"; import path from "node:path"; import ora from "ora"; export const checkNodeVersion = async () => { const spinner = ora("Checking node version...").start(); const [major, minor] = process.versions.node.split(".").map(Number); let packageJson; try { packageJson = JSON.parse( await fs.readFile( path.join(import.meta.dirname, "../package.json"), "utf-8", ), ); } catch (e) { throw new Error("Failed to read package.json of core-sdk"); } const { engines: { node }, } = packageJson; const [minMajor, minMinor] = node .split(".") .map((v: string) => v.replace(/[^\d]/g, "")) .map(Number); if (major < minMajor || (major === minMajor && minor < minMinor)) { spinner.fail( `Node version ${minMajor}.${minMinor} or higher is required. You are running ${major}.${minor}.`, ); process.exit(1); } else { spinner.stop(); return true; } }; /** * Get the value of a process argument by key * Example: getArgumentByKey("--email") or getArgumentByKey(["--email", "-e"]) * @param key The key to search for in the process arguments * @returns */ export const getArgumentByKey = (key: string | string[]) => { if (Array.isArray(key)) { for (const k of key) { if (process.argv.includes(k)) { const index = process.argv.indexOf(k); return index !== -1 ? process.argv[index + 1] : undefined; } } return undefined; } const index = process.argv.indexOf(key); return index !== -1 ? process.argv[index + 1] : undefined; }; export const SUCCESS_FLAG_FILE = `${CREDENTIALS_DIR}/success`; /** * Store a flag in the credentials directory to indicate a successful build * This is used to determine if the build was successful or not */ export const storeBuildSuccessFlag = async () => { try { await fs.access(CREDENTIALS_DIR); } catch (_e) { await fs.mkdir(CREDENTIALS_DIR); } await fs.writeFile(SUCCESS_FLAG_FILE, "true"); }; /** * Remove the success flag from the credentials directory */ export const removeBuildSuccessFlag = async () => { try { await fs.unlink(SUCCESS_FLAG_FILE); } catch (_e) {} }; /** * Check if the build was successful */ export const checkBuildSuccess = async () => { try { await fs.access(SUCCESS_FLAG_FILE); return true; } catch (_e) { return false; } }; const getPackageVersion = async (packageName: string) => { const packageJsonPath = path.join( process.cwd(), "node_modules", packageName, "package.json", ); let packageJson; try { packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8")); return packageJson.version; } catch (e) { return undefined; } }; /** * Attempts to resolve a local file reference to get the actual package version * @param packageName The name of the package * @param filePath The file path reference (e.g. "file:../packages/core") * @returns The resolved version or "local-dev" if not found */ const resolveLocalFileVersion = async ( packageName: string, filePath: string, ) => { try { // Remove the file: prefix and resolve the path const refPath = filePath.replace(/^file:/, ""); const absPath = path.resolve(process.cwd(), refPath, "package.json"); // Read the package.json from the referenced path const refPackageJson = JSON.parse(await fs.readFile(absPath, "utf-8")); return refPackageJson.version || "local-dev"; } catch (e) { console.warn(`Failed to resolve local version for ${packageName}`, e); return "local-dev"; } }; export const getSDKVersions = async () => { const packageNames = [ "@embeddable.com/core", "@embeddable.com/react", "@embeddable.com/sdk-core", "@embeddable.com/sdk-react", "@embeddable.com/sdk-utils", ]; // First try to get versions from node_modules const sdkVersions = await packageNames.reduce< Promise<Record<string, string>> >( async (accPromise, packageName) => { const acc = await accPromise; // Wait for the previous accumulator to resolve const version = await getPackageVersion(packageName); if (version) { acc[packageName] = version; } return acc; }, Promise.resolve({}), // Start with a resolved promise containing an empty object ); // If no versions were found, try to get them from package.json dependencies/devDependencies if ( Object.keys(sdkVersions).length === 0 && process.env.NODE_ENV !== "test" ) { try { const packageJsonPath = path.join(process.cwd(), "package.json"); const packageJson = JSON.parse( await fs.readFile(packageJsonPath, "utf-8"), ); const { dependencies = {}, devDependencies = {} } = packageJson; const allDeps = { ...dependencies, ...devDependencies }; for (const packageName of packageNames) { if (allDeps[packageName]) { // For file: references, try to get the actual version from the referenced package if (allDeps[packageName].startsWith("file:")) { sdkVersions[packageName] = await resolveLocalFileVersion( packageName, allDeps[packageName], ); } else { sdkVersions[packageName] = allDeps[packageName]; } } } } catch (e) { console.warn("Failed to read package.json for SDK versions", e); } } // If we're in a test environment and still have no versions, add fallback values if (Object.keys(sdkVersions).length === 0) { const isTestEnv = process.cwd().includes("test-sdk"); if (isTestEnv) { console.warn("Test environment detected, using fallback SDK versions"); packageNames.forEach((pkg) => { sdkVersions[pkg] = "local-dev"; }); } } return sdkVersions; }; export const hrtimeToISO8601 = ( hrtime: number[] | null | undefined, ): String => { if (hrtime === null || hrtime === undefined) { return ""; } const seconds = hrtime[0]; const nanoseconds = hrtime[1]; // Convert time components const totalSeconds = seconds + nanoseconds / 1e9; const minutes = Math.floor(totalSeconds / 60); const remainingSeconds = totalSeconds % 60; // Format ISO 8601 duration without hours return `PT${minutes > 0 ? minutes + "M" : ""}${remainingSeconds.toFixed(3)}S`; };