Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config provider Deno support #1493

Open
peterreisz opened this issue Oct 6, 2023 · 6 comments
Open

Config provider Deno support #1493

peterreisz opened this issue Oct 6, 2023 · 6 comments
Labels
enhancement New feature or request

Comments

@peterreisz
Copy link

What is the problem this feature would solve?

Deno has a different api for accessing the environment variables.
There is no process.env.

const getEnv = () =>

What is the feature you are proposing to solve the problem?

Support Deno out of box for config provider.
I'm willing to contribute.

What alternatives have you considered?

Using the ConfigProvider.fromMap and manually passing the Deno env is an option, but

  • you have to set env variables one by one
  • or grant access the whole env reading in Deno.
@peterreisz peterreisz added the enhancement New feature or request label Oct 6, 2023
@mikearnaldi
Copy link
Member

How would supporting Deno look like?

@peterreisz
Copy link
Author

peterreisz commented Oct 7, 2023

Haven't tried, but something like this should work:

diff --git a/src/internal/configProvider.ts b/src/internal/configProvider.ts
index 44af3ae58..6de804e54 100644
--- a/src/internal/configProvider.ts
+++ b/src/internal/configProvider.ts
@@ -95,6 +95,37 @@ export const fromFlat = (flat: ConfigProvider.ConfigProvider.Flat): ConfigProvid
     flattened: flat
   })
 
+interface Environment {
+  getVariable(name: string): string | undefined;
+  getAllVariables(): { [key: string]: string | undefined; }
+}
+
+interface DenoRuntime {
+  Deno: {
+    env: {
+      get(key: string): string | undefined;
+      toObject(): { [index: string]: string; };
+    }
+  }
+}
+
+const isDenoRuntime = (runtime: {}): runtime is DenoRuntime => 'Deno' in runtime
+
+const getEnvironment = (): Environment => {
+  const runtime = globalThis;
+  if (isDenoRuntime(runtime)) {
+    return {
+      getVariable: (name) => runtime.Deno.env.get(name),
+      getAllVariables: () => runtime.Deno.env.toObject(),
+    }
+  }
+
+  return {
+    getVariable: (name) => process.env[name],
+    getAllVariables: () => process.env,
+  }
+}
+
 /** @internal */
 export const fromEnv = (
   config: Partial<ConfigProvider.ConfigProvider.FromEnvConfig> = {}
@@ -103,17 +134,14 @@ export const fromEnv = (
   const makePathString = (path: ReadonlyArray<string>): string => pipe(path, RA.join(pathDelim))
   const unmakePathString = (pathString: string): ReadonlyArray<string> => pathString.split(pathDelim)
 
-  const getEnv = () =>
-    typeof process !== "undefined" && "env" in process && typeof process.env === "object" ? process.env : {}
-
   const load = <A>(
     path: ReadonlyArray<string>,
     primitive: Config.Config.Primitive<A>,
     split = true
   ): Effect.Effect<never, ConfigError.ConfigError, ReadonlyArray<A>> => {
     const pathString = makePathString(path)
-    const current = getEnv()
-    const valueOpt = pathString in current ? Option.some(current[pathString]!) : Option.none()
+    const current = getEnvironment()
+    const valueOpt = Option.fromNullable(current.getVariable(pathString)) // this is doing a different thing, but otherwise you have to grant access to all env in Deno
     return pipe(
       valueOpt,
       core.mapError(() => configError.MissingData(path, `Expected ${pathString} to exist in the process context`)),
@@ -125,8 +153,8 @@ export const fromEnv = (
     path: ReadonlyArray<string>
   ): Effect.Effect<never, ConfigError.ConfigError, HashSet.HashSet<string>> =>
     core.sync(() => {
-      const current = getEnv()
-      const keys = Object.keys(current)
+      const current = getEnvironment()
+      const keys = Object.keys(current.getAllVariables())
       const keyPaths = Array.from(keys).map((value) => unmakePathString(value.toUpperCase()))
       const filteredKeyPaths = keyPaths.filter((keyPath) => {
         for (let i = 0; i < path.length; i++) {

@mikearnaldi
Copy link
Member

If you want to open a PR I'd be happy to review & merge

@peterreisz
Copy link
Author

I'm glad you are open to support Deno. I'll submit a PR then, just have to figure out some things. For example how to test the project with Deno.

@mikearnaldi
Copy link
Member

cc @fubhy who's proposing a multi-runtime test matrix

@fubhy
Copy link
Member

fubhy commented Oct 28, 2023

I can add a PR for the test matrix later today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Stale
Development

No branches or pull requests

3 participants