@oxog/environment-detector
Version:
Comprehensive, zero-dependency environment detection for Node.js
1,173 lines (1,154 loc) • 31.8 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
BaseDetector: () => BaseDetector,
BasePlugin: () => BasePlugin,
Cache: () => Cache,
EnvironmentDetector: () => EnvironmentDetector,
PluginContextImpl: () => PluginContextImpl,
PluginManagerImpl: () => PluginManagerImpl,
VERSION: () => VERSION,
default: () => src_default
});
module.exports = __toCommonJS(src_exports);
// src/detectors/os.ts
var os = __toESM(require("os"));
// src/core/constants.ts
var DEFAULT_CACHE_TIMEOUT = 6e4;
var CI_ENV_VARS = Object.freeze({
CI: "CI",
CONTINUOUS_INTEGRATION: "CONTINUOUS_INTEGRATION",
BUILD_NUMBER: "BUILD_NUMBER",
CI_NAME: "CI_NAME"
});
var CI_PROVIDER_ENV_VARS = Object.freeze({
GITHUB_ACTIONS: "GITHUB_ACTIONS",
GITLAB_CI: "GITLAB_CI",
TRAVIS: "TRAVIS",
CIRCLECI: "CIRCLECI",
JENKINS_URL: "JENKINS_URL",
BITBUCKET_BUILD_NUMBER: "BITBUCKET_BUILD_NUMBER",
TEAMCITY_VERSION: "TEAMCITY_VERSION",
APPVEYOR: "APPVEYOR",
CODEBUILD_BUILD_ID: "CODEBUILD_BUILD_ID",
TF_BUILD: "TF_BUILD"
// Azure Pipelines
});
var CLOUD_ENV_VARS = Object.freeze({
AWS_LAMBDA_FUNCTION_NAME: "AWS_LAMBDA_FUNCTION_NAME",
AWS_EXECUTION_ENV: "AWS_EXECUTION_ENV",
AWS_REGION: "AWS_REGION",
FUNCTION_NAME: "FUNCTION_NAME",
// Google Cloud Functions
K_SERVICE: "K_SERVICE",
// Google Cloud Run
WEBSITE_SITE_NAME: "WEBSITE_SITE_NAME",
// Azure Functions
VERCEL: "VERCEL",
VERCEL_ENV: "VERCEL_ENV",
NETLIFY: "NETLIFY",
CF_WORKER: "CF_WORKER"
// Cloudflare Workers
});
var CONTAINER_FILES = Object.freeze({
DOCKER_ENV: "/.dockerenv",
DOCKER_INIT: "/.dockerinit",
WSL_INTEROP: "/run/WSL",
KUBERNETES_SERVICE: "/var/run/secrets/kubernetes.io"
});
var WSL_INDICATORS = Object.freeze({
ENV_VAR: "WSL_DISTRO_NAME",
PROC_VERSION: "Microsoft",
PROC_SYS: "/proc/sys/fs/binfmt_misc/WSLInterop"
});
var NODE_ENV_VALUES = Object.freeze({
DEVELOPMENT: "development",
PRODUCTION: "production",
TEST: "test",
STAGING: "staging"
});
// src/core/cache.ts
var Cache = class _Cache {
constructor() {
this.store = /* @__PURE__ */ new Map();
this.enabled = true;
}
static getInstance() {
if (!_Cache.instance) {
_Cache.instance = new _Cache();
}
return _Cache.instance;
}
get(key) {
if (!this.enabled) {
return void 0;
}
const entry = this.store.get(key);
if (!entry) {
return void 0;
}
const now = Date.now();
if (now - entry.timestamp > entry.timeout) {
this.store.delete(key);
return void 0;
}
return entry.value;
}
set(key, value, timeout = DEFAULT_CACHE_TIMEOUT) {
if (!this.enabled) {
return;
}
this.store.set(key, {
value,
timestamp: Date.now(),
timeout
});
}
has(key) {
if (!this.enabled) {
return false;
}
const entry = this.store.get(key);
if (!entry) {
return false;
}
const now = Date.now();
if (now - entry.timestamp > entry.timeout) {
this.store.delete(key);
return false;
}
return true;
}
delete(key) {
return this.store.delete(key);
}
clear() {
this.store.clear();
}
enable() {
this.enabled = true;
}
disable() {
this.enabled = false;
this.clear();
}
isEnabled() {
return this.enabled;
}
size() {
return this.store.size;
}
keys() {
return Array.from(this.store.keys());
}
};
// src/core/detector.ts
var BaseDetector = class {
constructor(options = {}) {
this.cache = Cache.getInstance();
this.options = {
cache: true,
cacheTimeout: 6e4,
async: false,
...options
};
}
detect() {
if (this.options.async) {
return this.detectAsync();
}
return this.detectSync();
}
reset() {
this.cache.delete(this.getCacheKey());
}
detectSync() {
const cacheKey = this.getCacheKey();
if (this.options.cache) {
const cached = this.cache.get(cacheKey);
if (cached !== void 0) {
return cached;
}
}
const result = this.performDetection();
if (this.options.cache) {
this.cache.set(cacheKey, result, this.options.cacheTimeout);
}
return result;
}
async detectAsync() {
const cacheKey = this.getCacheKey();
if (this.options.cache) {
const cached = this.cache.get(cacheKey);
if (cached !== void 0) {
return cached;
}
}
const result = await this.performAsyncDetection();
if (this.options.cache) {
this.cache.set(cacheKey, result, this.options.cacheTimeout);
}
return result;
}
async performAsyncDetection() {
return this.performDetection();
}
getCacheKey() {
return `detector:${this.name}`;
}
};
// src/detectors/os.ts
var OSDetector = class extends BaseDetector {
constructor() {
super(...arguments);
this.name = "os";
}
performDetection() {
try {
const platform5 = os.platform();
const release2 = os.release();
const version2 = os.version ? os.version() : release2;
const arch3 = os.arch();
let type = "unknown";
let isWindows = false;
let isMacOS = false;
let isLinux = false;
switch (platform5) {
case "win32":
type = "windows";
isWindows = true;
break;
case "darwin":
type = "macos";
isMacOS = true;
break;
case "linux":
type = "linux";
isLinux = true;
break;
}
return {
platform: platform5,
type,
version: version2,
release: release2,
arch: arch3,
isWindows,
isMacOS,
isLinux
};
} catch {
return {
platform: "linux",
type: "unknown",
arch: "unknown",
release: "unknown",
version: "unknown",
isWindows: false,
isMacOS: false,
isLinux: false
};
}
}
};
// src/detectors/container.ts
var os3 = __toESM(require("os"));
// src/utils/file.ts
var fs = __toESM(require("fs"));
function fileExists(path) {
try {
fs.accessSync(path, fs.constants.F_OK);
return true;
} catch {
return false;
}
}
function readFile(path) {
try {
return fs.readFileSync(path, "utf8");
} catch {
return null;
}
}
function isDirectory(path) {
try {
const stats = fs.statSync(path);
return stats.isDirectory();
} catch {
return false;
}
}
// src/utils/process.ts
var child_process = __toESM(require("child_process"));
var os2 = __toESM(require("os"));
function getEnv(key) {
return process.env[key];
}
function hasEnv(key) {
return key in process.env;
}
function getEnvBoolean(key, defaultValue = false) {
const value = getEnv(key);
if (!value) {
return defaultValue;
}
return value.toLowerCase() === "true" || value === "1";
}
function execSync2(command) {
try {
return child_process.execSync(command, {
encoding: "utf8",
stdio: ["pipe", "pipe", "ignore"]
}).trim();
} catch {
return null;
}
}
function getUID() {
if (process.getuid) {
return process.getuid();
}
return void 0;
}
function getGID() {
if (process.getgid) {
return process.getgid();
}
return void 0;
}
function getUsername() {
try {
return os2.userInfo().username;
} catch {
return void 0;
}
}
function isRoot() {
return getUID() === 0;
}
function parseNodeVersion() {
const version2 = process.version;
const [major, minor, patch] = version2.slice(1).split(".").map((v) => parseInt(v, 10));
return {
version: version2,
major: major || 0,
minor: minor || 0,
patch: patch || 0
};
}
// src/detectors/container.ts
var ContainerDetector = class extends BaseDetector {
constructor() {
super(...arguments);
this.name = "container";
}
performDetection() {
const isDocker = this.detectDocker();
const wslInfo = this.detectWSL();
const isKubernetes = this.detectKubernetes();
const isContainer = isDocker || wslInfo.isWSL || isKubernetes;
let containerType;
if (isDocker) {
containerType = "docker";
} else if (wslInfo.isWSL) {
containerType = "wsl";
} else if (isKubernetes) {
containerType = "kubernetes";
}
return {
isContainer,
isDocker,
isWSL: wslInfo.isWSL,
isKubernetes,
containerType,
wslVersion: wslInfo.version,
wslDistro: wslInfo.distro
};
}
detectDocker() {
if (fileExists(CONTAINER_FILES.DOCKER_ENV) || fileExists(CONTAINER_FILES.DOCKER_INIT)) {
return true;
}
const cgroupPath = "/proc/self/cgroup";
const cgroupContent = readFile(cgroupPath);
if (cgroupContent && (cgroupContent.includes("docker") || cgroupContent.includes("containerd"))) {
return true;
}
const initCgroupContent = readFile("/proc/1/cgroup");
if (initCgroupContent && (initCgroupContent.includes("docker") || initCgroupContent.includes("containerd"))) {
return true;
}
const mountInfo = readFile("/proc/self/mountinfo");
if (mountInfo && mountInfo.includes("docker")) {
return true;
}
return false;
}
detectWSL() {
if (os3.platform() === "win32") {
return { isWSL: false };
}
const wslDistro = getEnv(WSL_INDICATORS.ENV_VAR);
if (wslDistro) {
return {
isWSL: true,
version: this.getWSLVersion(),
distro: wslDistro
};
}
const procVersion = readFile("/proc/version");
if (procVersion && procVersion.toLowerCase().includes(WSL_INDICATORS.PROC_VERSION.toLowerCase())) {
return {
isWSL: true,
version: this.getWSLVersion(),
distro: this.getWSLDistro()
};
}
if (fileExists(WSL_INDICATORS.PROC_SYS) || isDirectory(CONTAINER_FILES.WSL_INTEROP)) {
return {
isWSL: true,
version: this.getWSLVersion(),
distro: this.getWSLDistro()
};
}
if (hasEnv("WSLENV") || hasEnv("WSL_INTEROP")) {
return {
isWSL: true,
version: this.getWSLVersion(),
distro: this.getWSLDistro()
};
}
return { isWSL: false };
}
detectKubernetes() {
if (isDirectory(CONTAINER_FILES.KUBERNETES_SERVICE)) {
return true;
}
if (hasEnv("KUBERNETES_SERVICE_HOST") || hasEnv("KUBERNETES_PORT")) {
return true;
}
const hostname2 = os3.hostname();
if (hostname2 && /^[a-z0-9]+-[a-z0-9]+-[a-z0-9]+(-[a-z0-9]+)*$/.test(hostname2)) {
if (fileExists("/var/run/secrets/kubernetes.io/serviceaccount/token")) {
return true;
}
}
return false;
}
getWSLVersion() {
const procVersion = readFile("/proc/version");
if (procVersion) {
if (procVersion.includes("WSL2") || procVersion.includes("microsoft-standard-WSL2")) {
return 2;
}
if (procVersion.includes("Microsoft") || procVersion.includes("WSL")) {
const kernelMatch = procVersion.match(/(\d+)\.(\d+)\.(\d+)/);
if (kernelMatch) {
const majorVersion = parseInt(kernelMatch[1] || "0", 10);
if (majorVersion >= 5) {
return 2;
}
}
return 1;
}
}
return void 0;
}
getWSLDistro() {
const envDistro = getEnv(WSL_INDICATORS.ENV_VAR);
if (envDistro) {
return envDistro;
}
const osRelease = readFile("/etc/os-release");
if (osRelease) {
const nameMatch = osRelease.match(/^NAME="?(.+?)"?$/m);
if (nameMatch) {
return nameMatch[1];
}
}
return void 0;
}
};
// src/detectors/ci.ts
var CIDetector = class extends BaseDetector {
constructor() {
super(...arguments);
this.name = "ci";
}
performDetection() {
const isCI = this.detectCI();
if (!isCI) {
return { isCI: false };
}
const provider = this.detectCIProvider();
const name = this.getCIName(provider);
const isPR = this.detectPullRequest(provider);
return {
isCI,
name,
isPR,
provider
};
}
detectCI() {
if (getEnvBoolean(CI_ENV_VARS.CI) || getEnvBoolean(CI_ENV_VARS.CONTINUOUS_INTEGRATION) || hasEnv(CI_ENV_VARS.BUILD_NUMBER) || hasEnv(CI_ENV_VARS.CI_NAME)) {
return true;
}
for (const envVar of Object.values(CI_PROVIDER_ENV_VARS)) {
if (hasEnv(envVar)) {
return true;
}
}
return false;
}
detectCIProvider() {
if (getEnvBoolean(CI_PROVIDER_ENV_VARS.GITHUB_ACTIONS)) {
return "github-actions";
}
if (getEnvBoolean(CI_PROVIDER_ENV_VARS.GITLAB_CI)) {
return "gitlab-ci";
}
if (getEnvBoolean(CI_PROVIDER_ENV_VARS.TRAVIS)) {
return "travis-ci";
}
if (getEnvBoolean(CI_PROVIDER_ENV_VARS.CIRCLECI)) {
return "circleci";
}
if (hasEnv(CI_PROVIDER_ENV_VARS.JENKINS_URL)) {
return "jenkins";
}
if (getEnvBoolean(CI_PROVIDER_ENV_VARS.TF_BUILD)) {
return "azure-pipelines";
}
if (hasEnv(CI_PROVIDER_ENV_VARS.BITBUCKET_BUILD_NUMBER)) {
return "bitbucket-pipelines";
}
if (hasEnv(CI_PROVIDER_ENV_VARS.TEAMCITY_VERSION)) {
return "teamcity";
}
if (getEnvBoolean(CI_PROVIDER_ENV_VARS.APPVEYOR)) {
return "appveyor";
}
if (hasEnv(CI_PROVIDER_ENV_VARS.CODEBUILD_BUILD_ID)) {
return "codebuild";
}
return "unknown";
}
getCIName(provider) {
switch (provider) {
case "github-actions":
return "GitHub Actions";
case "gitlab-ci":
return "GitLab CI";
case "travis-ci":
return "Travis CI";
case "circleci":
return "CircleCI";
case "jenkins":
return "Jenkins";
case "azure-pipelines":
return "Azure Pipelines";
case "bitbucket-pipelines":
return "Bitbucket Pipelines";
case "teamcity":
return "TeamCity";
case "appveyor":
return "AppVeyor";
case "codebuild":
return "AWS CodeBuild";
default:
return getEnv(CI_ENV_VARS.CI_NAME) || "Unknown CI";
}
}
detectPullRequest(provider) {
var _a;
switch (provider) {
case "github-actions":
return getEnv("GITHUB_EVENT_NAME") === "pull_request";
case "gitlab-ci":
return hasEnv("CI_MERGE_REQUEST_ID") || hasEnv("CI_EXTERNAL_PULL_REQUEST_IID");
case "travis-ci":
return getEnv("TRAVIS_PULL_REQUEST") !== "false";
case "circleci":
return hasEnv("CIRCLE_PULL_REQUEST") || hasEnv("CIRCLE_PR_NUMBER");
case "jenkins":
return hasEnv("CHANGE_ID") || hasEnv("ghprbPullId");
case "azure-pipelines":
return hasEnv("SYSTEM_PULLREQUEST_PULLREQUESTID");
case "bitbucket-pipelines":
return hasEnv("BITBUCKET_PR_ID");
case "teamcity":
return hasEnv("TEAMCITY_PULL_REQUEST_NUMBER");
case "appveyor":
return hasEnv("APPVEYOR_PULL_REQUEST_NUMBER");
case "codebuild":
return hasEnv("CODEBUILD_WEBHOOK_HEAD_REF") && ((_a = getEnv("CODEBUILD_WEBHOOK_HEAD_REF")) == null ? void 0 : _a.startsWith("refs/pull/")) || false;
default:
return hasEnv("PR_NUMBER") || hasEnv("PULL_REQUEST_ID") || hasEnv("PULL_REQUEST");
}
}
};
// src/detectors/cloud.ts
var CloudDetector = class extends BaseDetector {
constructor() {
super(...arguments);
this.name = "cloud";
}
performDetection() {
const provider = this.detectCloudProvider();
const isCloud = provider !== void 0;
const isServerless = this.isServerlessEnvironment(provider);
const functionName = this.getFunctionName(provider);
const region = this.getRegion(provider);
return {
isCloud,
provider,
isServerless,
functionName,
region
};
}
detectCloudProvider() {
if (hasEnv(CLOUD_ENV_VARS.AWS_LAMBDA_FUNCTION_NAME) || hasEnv(CLOUD_ENV_VARS.AWS_EXECUTION_ENV)) {
return "aws-lambda";
}
if (hasEnv(CLOUD_ENV_VARS.FUNCTION_NAME) || hasEnv(CLOUD_ENV_VARS.K_SERVICE)) {
return "google-cloud-functions";
}
if (hasEnv(CLOUD_ENV_VARS.WEBSITE_SITE_NAME) && hasEnv("FUNCTIONS_EXTENSION_VERSION")) {
return "azure-functions";
}
if (hasEnv(CLOUD_ENV_VARS.VERCEL) || hasEnv(CLOUD_ENV_VARS.VERCEL_ENV)) {
return "vercel";
}
if (hasEnv(CLOUD_ENV_VARS.NETLIFY) || hasEnv("NETLIFY_BUILD_BASE")) {
return "netlify";
}
if (hasEnv(CLOUD_ENV_VARS.CF_WORKER) || this.detectCloudflareWorkers()) {
return "cloudflare-workers";
}
if (this.detectAWS()) {
return "aws-lambda";
}
return void 0;
}
isServerlessEnvironment(provider) {
if (!provider) {
return false;
}
switch (provider) {
case "aws-lambda":
case "google-cloud-functions":
case "azure-functions":
case "cloudflare-workers":
return true;
case "vercel":
case "netlify":
return hasEnv("VERCEL_FUNCTION") || hasEnv("NETLIFY_FUNCTION_NAME") || hasEnv("NETLIFY_DEV");
default:
return false;
}
}
getFunctionName(provider) {
if (!provider) {
return void 0;
}
switch (provider) {
case "aws-lambda":
return getEnv(CLOUD_ENV_VARS.AWS_LAMBDA_FUNCTION_NAME);
case "google-cloud-functions":
return getEnv(CLOUD_ENV_VARS.FUNCTION_NAME) || getEnv(CLOUD_ENV_VARS.K_SERVICE);
case "azure-functions":
return getEnv(CLOUD_ENV_VARS.WEBSITE_SITE_NAME);
case "vercel":
return getEnv("VERCEL_FUNCTION");
case "netlify":
return getEnv("NETLIFY_FUNCTION_NAME");
case "cloudflare-workers":
return getEnv("CF_WORKER_NAME") || getEnv("WORKER_NAME");
default:
return void 0;
}
}
getRegion(provider) {
if (!provider) {
return void 0;
}
switch (provider) {
case "aws-lambda":
return getEnv(CLOUD_ENV_VARS.AWS_REGION) || getEnv("AWS_DEFAULT_REGION");
case "google-cloud-functions":
return getEnv("FUNCTION_REGION") || getEnv("GCP_REGION");
case "azure-functions":
return getEnv("REGION_NAME") || getEnv("AZURE_REGION");
case "vercel":
return getEnv("VERCEL_REGION");
case "cloudflare-workers":
return getEnv("CF_REGION");
default:
return void 0;
}
}
detectAWS() {
if (hasEnv("AWS_EXECUTION_ENV") || hasEnv("AWS_LAMBDA_RUNTIME_API") || hasEnv("_HANDLER") || hasEnv("LAMBDA_TASK_ROOT") || hasEnv("LAMBDA_RUNTIME_DIR")) {
return true;
}
if (hasEnv("ECS_CONTAINER_METADATA_URI") || hasEnv("ECS_CONTAINER_METADATA_URI_V4")) {
return true;
}
if (fileExists("/sys/hypervisor/uuid")) {
return true;
}
return false;
}
detectCloudflareWorkers() {
if (typeof global !== "undefined" && "caches" in global && "default" in global.caches) {
return true;
}
try {
const globalAny = global;
if (globalAny.CloudflareWorker || globalAny.MINIFLARE || globalAny.navigator && globalAny.navigator.userAgent === "Cloudflare-Workers") {
return true;
}
} catch {
}
return false;
}
};
// src/detectors/node.ts
var os4 = __toESM(require("os"));
var NodeDetector = class extends BaseDetector {
constructor() {
super(...arguments);
this.name = "node";
}
performDetection() {
const { version: version2, major, minor, patch } = parseNodeVersion();
const arch3 = os4.arch();
const platform5 = os4.platform();
return {
version: version2,
major,
minor,
patch,
arch: arch3,
platform: platform5
};
}
};
var EnvironmentModeDetector = class extends BaseDetector {
constructor() {
super(...arguments);
this.name = "mode";
}
performDetection() {
var _a;
const nodeEnv = (_a = getEnv("NODE_ENV")) == null ? void 0 : _a.toLowerCase();
switch (nodeEnv) {
case NODE_ENV_VALUES.PRODUCTION:
return "production";
case NODE_ENV_VALUES.DEVELOPMENT:
return "development";
case NODE_ENV_VALUES.TEST:
return "test";
case NODE_ENV_VALUES.STAGING:
return "staging";
default:
return "development";
}
}
};
// src/detectors/privileges.ts
var os5 = __toESM(require("os"));
var PrivilegeDetector = class extends BaseDetector {
constructor() {
super(...arguments);
this.name = "privileges";
}
performDetection() {
const platform5 = os5.platform();
const uid = getUID();
const gid = getGID();
const username = getUsername();
const isRootUser = isRoot();
const isAdminUser = this.isAdmin(platform5);
const isElevated = isRootUser || isAdminUser;
return {
isElevated,
isRoot: isRootUser,
isAdmin: isAdminUser,
uid,
gid,
username
};
}
isAdmin(platform5) {
switch (platform5) {
case "win32":
return this.isWindowsAdmin();
case "darwin":
case "linux":
return this.isUnixAdmin();
default:
return false;
}
}
isWindowsAdmin() {
try {
const result = execSync2("net session 2>nul");
return result !== null;
} catch {
try {
const whoami = execSync2("whoami /groups");
if (whoami) {
return whoami.toLowerCase().includes("s-1-5-32-544") || whoami.toLowerCase().includes("administrators");
}
} catch {
}
try {
const systemDir = execSync2('dir "%SystemRoot%\\System32\\config" 2>nul');
return systemDir !== null;
} catch {
return false;
}
}
}
isUnixAdmin() {
if (isRoot()) {
return true;
}
try {
const groups = execSync2("groups");
if (groups) {
const groupList = groups.toLowerCase();
return groupList.includes("admin") || groupList.includes("sudo") || groupList.includes("wheel") || groupList.includes("root");
}
} catch {
try {
const sudoCheck = execSync2("sudo -n true 2>/dev/null");
return sudoCheck !== null;
} catch {
return false;
}
}
return false;
}
};
// src/plugins/base.ts
var BasePlugin = class {
async install(context) {
var _a;
for (const detector of this.detectors) {
context.registerDetector(detector);
}
await ((_a = this.onInstall) == null ? void 0 : _a.call(this, context));
}
async uninstall() {
var _a;
await ((_a = this.onUninstall) == null ? void 0 : _a.call(this));
}
};
var PluginContextImpl = class {
constructor() {
this.detectors = /* @__PURE__ */ new Map();
this.eventHandlers = /* @__PURE__ */ new Map();
}
registerDetector(detector) {
this.detectors.set(detector.name, detector);
}
unregisterDetector(name) {
this.detectors.delete(name);
}
getDetector(name) {
return this.detectors.get(name);
}
getAllDetectors() {
return Array.from(this.detectors.values());
}
emit(event, data) {
const handlers = this.eventHandlers.get(event);
if (handlers) {
for (const handler of handlers) {
try {
const result = handler(data);
if (result instanceof Promise) {
result.catch((error) => {
console.error(`Error in event handler for '${event}':`, error);
});
}
} catch (error) {
console.error(`Error in event handler for '${event}':`, error);
}
}
}
}
on(event, handler) {
if (!this.eventHandlers.has(event)) {
this.eventHandlers.set(event, []);
}
this.eventHandlers.get(event).push(handler);
}
off(event, handler) {
const handlers = this.eventHandlers.get(event);
if (handlers) {
const index = handlers.indexOf(handler);
if (index > -1) {
handlers.splice(index, 1);
}
}
}
};
// src/plugins/manager.ts
var PluginManagerImpl = class _PluginManagerImpl {
constructor() {
this.plugins = /* @__PURE__ */ new Map();
this.context = new PluginContextImpl();
}
static getInstance() {
if (!_PluginManagerImpl.instance) {
_PluginManagerImpl.instance = new _PluginManagerImpl();
}
return _PluginManagerImpl.instance;
}
async use(plugin) {
var _a;
if (this.plugins.has(plugin.name)) {
throw new Error(`Plugin '${plugin.name}' is already installed`);
}
try {
await ((_a = plugin.install) == null ? void 0 : _a.call(plugin, this.context));
this.plugins.set(plugin.name, plugin);
this.context.emit("plugin:installed", { plugin });
} catch (error) {
this.context.emit("plugin:error", { plugin, error });
throw new Error(`Failed to install plugin '${plugin.name}': ${error}`);
}
}
async remove(pluginName) {
var _a;
const plugin = this.plugins.get(pluginName);
if (!plugin) {
throw new Error(`Plugin '${pluginName}' is not installed`);
}
try {
for (const detector of plugin.detectors) {
this.context.unregisterDetector(detector.name);
}
await ((_a = plugin.uninstall) == null ? void 0 : _a.call(plugin));
this.plugins.delete(pluginName);
this.context.emit("plugin:removed", { plugin });
} catch (error) {
this.context.emit("plugin:error", { plugin, error });
throw new Error(`Failed to remove plugin '${pluginName}': ${error}`);
}
}
get(pluginName) {
return this.plugins.get(pluginName);
}
getAll() {
return Array.from(this.plugins.values());
}
clear() {
for (const pluginName of this.plugins.keys()) {
try {
this.remove(pluginName);
} catch (error) {
console.error(`Error removing plugin '${pluginName}':`, error);
}
}
}
getContext() {
return this.context;
}
};
// src/version.ts
var VERSION = "1.0.0";
var BUILD_DATE = (/* @__PURE__ */ new Date()).toISOString();
var NODE_VERSION = process.version;
// src/index.ts
var EnvironmentDetector = class {
constructor(options) {
this.osDetector = new OSDetector();
this.containerDetector = new ContainerDetector();
this.ciDetector = new CIDetector();
this.cloudDetector = new CloudDetector();
this.nodeDetector = new NodeDetector();
this.modeDetector = new EnvironmentModeDetector();
this.privilegeDetector = new PrivilegeDetector();
this.pluginManager = PluginManagerImpl.getInstance();
this.cache = Cache.getInstance();
if (options) {
this.osDetector = new OSDetector(options);
this.containerDetector = new ContainerDetector(options);
this.ciDetector = new CIDetector(options);
this.cloudDetector = new CloudDetector(options);
this.nodeDetector = new NodeDetector(options);
this.modeDetector = new EnvironmentModeDetector(options);
this.privilegeDetector = new PrivilegeDetector(options);
if (options.cache === false) {
this.cache.disable();
}
}
}
getEnvironmentInfo() {
return {
os: this.osDetector.detect(),
container: this.containerDetector.detect(),
ci: this.ciDetector.detect(),
cloud: this.cloudDetector.detect(),
node: this.nodeDetector.detect(),
privileges: this.privilegeDetector.detect(),
mode: this.modeDetector.detect()
};
}
async getEnvironmentInfoAsync() {
const [os6, container, ci, cloud, node, privileges, mode] = await Promise.all([
Promise.resolve(this.osDetector.detect()),
Promise.resolve(this.containerDetector.detect()),
Promise.resolve(this.ciDetector.detect()),
Promise.resolve(this.cloudDetector.detect()),
Promise.resolve(this.nodeDetector.detect()),
Promise.resolve(this.privilegeDetector.detect()),
Promise.resolve(this.modeDetector.detect())
]);
return { os: os6, container, ci, cloud, node, privileges, mode };
}
// Convenience getters for individual detections
get isWindows() {
return this.osDetector.detect().isWindows;
}
get isMacOS() {
return this.osDetector.detect().isMacOS;
}
get isLinux() {
return this.osDetector.detect().isLinux;
}
get isWSL() {
return this.containerDetector.detect().isWSL;
}
get isDocker() {
return this.containerDetector.detect().isDocker;
}
get isKubernetes() {
return this.containerDetector.detect().isKubernetes;
}
get isContainer() {
return this.containerDetector.detect().isContainer;
}
get isCI() {
return this.ciDetector.detect().isCI;
}
get isCloud() {
return this.cloudDetector.detect().isCloud;
}
get isServerless() {
return this.cloudDetector.detect().isServerless;
}
get isElevated() {
return this.privilegeDetector.detect().isElevated;
}
get isRoot() {
return this.privilegeDetector.detect().isRoot;
}
get isAdmin() {
return this.privilegeDetector.detect().isAdmin;
}
// Plugin system
use(plugin) {
this.pluginManager.use(plugin);
}
removePlugin(pluginName) {
this.pluginManager.remove(pluginName);
}
// Cache management
clearCache() {
this.cache.clear();
}
enableCache() {
this.cache.enable();
}
disableCache() {
this.cache.disable();
}
// Reset all detectors
reset() {
this.osDetector.reset();
this.containerDetector.reset();
this.ciDetector.reset();
this.cloudDetector.reset();
this.nodeDetector.reset();
this.modeDetector.reset();
this.privilegeDetector.reset();
}
// Get version information
getVersion() {
return VERSION;
}
// Get detailed package information
getPackageInfo() {
return {
version: VERSION,
detectors: ["os", "container", "ci", "cloud", "node", "privileges", "mode"],
cacheEnabled: this.cache.isEnabled()
};
}
// Quick environment summary
getEnvironmentSummary() {
const info = this.getEnvironmentInfo();
const parts = [info.os.type];
if (info.container.isContainer) {
parts.push(info.container.containerType || "container");
}
if (info.ci.isCI) {
parts.push("ci");
}
if (info.cloud.isCloud) {
parts.push("cloud");
}
if (info.privileges.isElevated) {
parts.push("elevated");
}
return parts.join("+");
}
};
var env = new EnvironmentDetector();
var src_default = env;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BaseDetector,
BasePlugin,
Cache,
EnvironmentDetector,
PluginContextImpl,
PluginManagerImpl,
VERSION
});
//# sourceMappingURL=index.js.map