SoftwareBrothers / adminjs

AdminJS is an admin panel for apps written in node.js
https://adminjs.co
MIT License
8.07k stars 650 forks source link

[Bug]: Issue with AdminJSOptions.env when pre-bundling for deployment #1593

Closed mattrochon closed 4 months ago

mattrochon commented 7 months ago

Contact Details

No response

What happened?

When I bundle for deployment I host all my static/public assets on a CDN. Not just the js files adminJS uses, but also images, css, config etc.

To that end, in my code I dynamically build the urls based on an environment variable CDN_PATH, which is really only available on the server, as its part of the build automation to create that.

On the UI side, I tried passing this down to the components using AdminJSOptions.env:

image

but it doesnt seem this this is passed on when rendering the app using bundled files:

image

Almost everything works, except when I'm using a component that requires a url source, like an <img> tag, for example.

Since the node app is the one initiating the app rendering, even if it ultimately uses components fromt he CDN, couldnt it still pass the adminjs env info tot he frontend for use by the react app?

Bug prevalence

Always

AdminJS dependencies version

"dependencies": { "@adminjs/bundler": "^3.0.0", "@adminjs/express": "^6.1.0", "@adminjs/prisma": "^5.0.1", "@adminjs/themes": "^1.0.1", "@adminjs/upload": "^4.0.1", "@aws-sdk/client-api-gateway": "^3.465.0", "@aws-sdk/client-cognito-identity-provider": "^3.468.0", "@fortawesome/fontawesome-free": "^6.5.1", "@types/express": "^4.17.21", "adminjs": "^7.4.2", "amazon-cognito-identity-js": "^6.3.7", "cors": "^2.8.5", "express": "^4.18.2", "express-formidable": "^1.2.0", "express-session": "^1.17.3", "memorystore": "^1.6.7", "prisma": "^5.6.0", "tslib": "^2.6.2" }, "devDependencies": { "@types/cors": "^2.8.17", "@types/express-session": "^1.17.10", "tsx": "^4.6.2", "nodemon": "^3.0.2" },

What browsers do you see the problem on?

No response

Relevant log output

n/a

Relevant code that's giving you issues

No response

dziraf commented 7 months ago

It seems to be an issue with @adminjs/bundler. I will probably have to update it so that it requires AdminJSOptions.

You should be able to add missing envs by creating a custom script.

import fs from 'fs/promises'

const setEnvs = async (admin: AdminJS) => {
  const { env = {} } = admin.options

  const script = Object.keys(env).map((envKey) => (
    `AdminJS.env.${envKey} = ${JSON.stringify(env[envKey])}\n`
  )).join('')

  await fs.writeFile('<destination path>', script, 'utf8')
}

You can run it in the same file where you use @adminjs/bundler. If you don't want to create an AdminJS instance for the script, it's enough if you pass only AdminJSOptions object or envs object.

Afterwards, add the generated script to AdminJS assets:

const admin = new AdminJS({
  // ...
  assets: {
    scripts: process.env.NODE_ENV === 'production' ?  ['/envs.js'] : [],
  }
})
mattrochon commented 7 months ago

Thats a clever solution, for my use, those values weren't known at build time, so I did the same thing with terraform:

locals {
  adminjs_ui_env = templatefile("${path.module}/ui-env.tftpl", {
    env = {
      DEFAULT_BASE_PATH = "/app"
      CDN_PATH          = "https://${aws_s3_bucket.my_bucket.bucket}.s3.amazonaws.com/dashboard/"
    }
  })
}

resource "aws_s3_object" "ui-env-js" {
  bucket = aws_s3_bucket.my_bucket.id
  key    = "dashboard/ui-env.js"
  content_base64 = base64encode(local.adminjs_ui_env)
  etag   = md5(local.adminjs_ui_env)
  content_type     = "application/javascript"
  acl = "public-read"
}

ui-env.tftpl

%{ for config_key, config_value in env }
AdminJS.env.${config_key} = ${config_value}
%{ endfor ~}
mattrochon commented 7 months ago

Confirmed works

Dauniusha commented 7 months ago

Just copy env string is working too:

env: {
    IMAGES_PATH: `${process.env.IMAGES_PATH}`,
}

So it's seems to be an unclear behaviour, not a real bug 🙂