From 21553258a1b4403c87a3358c7739aabadce5b492 Mon Sep 17 00:00:00 2001 From: Dany Date: Thu, 3 Oct 2024 19:45:45 +0200 Subject: [PATCH] feat: support containers flags --- build.config.ts | 2 +- eslint.config.mjs | 6 +++--- playground/bun.ts | 6 ++++++ playground/deno.ts | 6 ++++++ playground/node.ts | 6 ++++++ src/containers/container.ts | 22 ++++++++++++++++++++++ src/containers/docker.ts | 29 +++++++++++++++++++++++++++++ src/containers/index.ts | 2 ++ src/wsl/index.ts | 35 +++++++++++++++++++++++++++++++++++ test/containers.test.ts | 20 ++++++++++++++++++++ test/wsl.test.ts | 18 ++++++++++++++++++ 11 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 src/containers/container.ts create mode 100644 src/containers/docker.ts create mode 100644 src/containers/index.ts create mode 100644 src/wsl/index.ts create mode 100644 test/containers.test.ts create mode 100644 test/wsl.test.ts diff --git a/build.config.ts b/build.config.ts index 4595e48..eede9c2 100644 --- a/build.config.ts +++ b/build.config.ts @@ -10,7 +10,7 @@ export default defineBuildConfig({ minify: true, }, }, - entries: ["src/index"], + entries: ["src/index", "src/containers/index", "src/wsl/index"], hooks: { "rollup:options"(ctx, rollupConfig) { (rollupConfig.plugins as Plugin[]).push({ diff --git a/eslint.config.mjs b/eslint.config.mjs index d80ab73..dfc90fc 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,7 +4,7 @@ import unjs from "eslint-config-unjs"; export default unjs({ ignores: [], rules: { - "unicorn/no-null": 0, - "unicorn/prevent-abbreviations": 0 -}, + "unicorn/no-null": 0, + "unicorn/prevent-abbreviations": 0 + }, }); \ No newline at end of file diff --git a/playground/bun.ts b/playground/bun.ts index d8d7114..1ba9c56 100644 --- a/playground/bun.ts +++ b/playground/bun.ts @@ -1,6 +1,12 @@ import * as stdEnv from "../src"; +import * as stdWsl from "../src/wsl"; +import * as stdContainers from "../src/containers"; console.log({ ...stdEnv, process: "-", }); + +console.log(stdWsl); + +console.log(stdContainers); \ No newline at end of file diff --git a/playground/deno.ts b/playground/deno.ts index 40e44cd..18467b3 100644 --- a/playground/deno.ts +++ b/playground/deno.ts @@ -1,7 +1,13 @@ // @ts-nocheck import * as stdEnv from "../dist/index.mjs"; +import * as stdEnvWsl from "../dist/wsl/index.mjs"; +import * as stdEnvContainers from "../dist/containers/index.mjs"; Deno.env.set("FOOBAR", "baz"); console.log(stdEnv, stdEnv.process.env.FOOBAR); + +console.log(stdEnvWsl); + +console.log(stdEnvContainers); diff --git a/playground/node.ts b/playground/node.ts index d8d7114..d1a9b23 100644 --- a/playground/node.ts +++ b/playground/node.ts @@ -1,6 +1,12 @@ import * as stdEnv from "../src"; +import * as stdWsl from "../src/wsl"; +import * as stdContainers from "../src/containers"; console.log({ ...stdEnv, process: "-", }); + +console.log(stdWsl); + +console.log(stdContainers); diff --git a/src/containers/container.ts b/src/containers/container.ts new file mode 100644 index 0000000..3b738e4 --- /dev/null +++ b/src/containers/container.ts @@ -0,0 +1,22 @@ +import { statSync } from "node:fs"; +import { isDocker } from "./docker"; + +function hasContainerEnv() { + try { + statSync("/run/.containerenv"); + return true; + } catch { + return false; + } +} + +let isContainerCached: boolean; + +function _isContainer() { + if (isContainerCached === undefined) { + isContainerCached = hasContainerEnv(); + } + return isContainerCached; +} + +export const isContainer = _isContainer() || isDocker; diff --git a/src/containers/docker.ts b/src/containers/docker.ts new file mode 100644 index 0000000..2221092 --- /dev/null +++ b/src/containers/docker.ts @@ -0,0 +1,29 @@ +import { readFileSync, statSync } from "node:fs"; + +let isDockerCached: boolean; + +function _isDocker() { + if (isDockerCached === undefined) { + isDockerCached = hasDockerEnv() || hasDockerCGroup(); + } + return isDockerCached; +} + +function hasDockerEnv() { + try { + statSync("/.dockerenv"); + return true; + } catch { + return false; + } +} + +function hasDockerCGroup() { + try { + return readFileSync("/proc/self/cgroup", "utf8").includes("docker"); + } catch { + return false; + } +} + +export const isDocker = _isDocker(); diff --git a/src/containers/index.ts b/src/containers/index.ts new file mode 100644 index 0000000..3e5bb95 --- /dev/null +++ b/src/containers/index.ts @@ -0,0 +1,2 @@ +export * from "./docker"; +export * from "./container"; diff --git a/src/wsl/index.ts b/src/wsl/index.ts new file mode 100644 index 0000000..de9aacc --- /dev/null +++ b/src/wsl/index.ts @@ -0,0 +1,35 @@ +import { readFileSync } from "node:fs"; +import { release } from "node:os"; +import { isDocker } from "../containers"; + +let isWSLCached: boolean; + +function _isWsl() { + if (isWSLCached === undefined) { + isWSLCached = hasUnameOrProcVersion(); + } + return isWSLCached; +} + +function hasUnameOrProcVersion() { + if (globalThis.process?.platform !== "linux") { + return false; + } + if (release().toLowerCase().includes("microsoft")) { + if (isDocker) { + return false; + } + return true; + } + try { + return readFileSync("/proc/version", "utf8") + .toLowerCase() + .includes("microsoft") + ? !isDocker + : false; + } catch { + return false; + } +} + +export const isWsl = _isWsl(); diff --git a/test/containers.test.ts b/test/containers.test.ts new file mode 100644 index 0000000..98082f4 --- /dev/null +++ b/test/containers.test.ts @@ -0,0 +1,20 @@ +import { expect, it, describe } from "vitest"; +import * as stdEnv from "../src/containers"; + +describe("std-env containers", () => { + it("has expected exports", () => { + expect(Object.keys(stdEnv)).toMatchInlineSnapshot(` + [ + "isDocker", + "isContainer", + ] + `); + }); + + it("defaults", () => { + expect(stdEnv).toMatchObject({ + isDocker: expect.any(Boolean), + isContainer: expect.any(Boolean), + }); + }); +}); diff --git a/test/wsl.test.ts b/test/wsl.test.ts new file mode 100644 index 0000000..1ccde5c --- /dev/null +++ b/test/wsl.test.ts @@ -0,0 +1,18 @@ +import { expect, it, describe } from "vitest"; +import * as stdEnv from "../src/wsl"; + +describe("std-env wsl", () => { + it("has expected exports", () => { + expect(Object.keys(stdEnv)).toMatchInlineSnapshot(` + [ + "isWsl", + ] + `); + }); + + it("defaults", () => { + expect(stdEnv).toMatchObject({ + isWsl: expect.any(Boolean), + }); + }); +});