How to require external libraries in a component helper file?

I’m writing a theme component and I need to access two external libraries from a helper file. My current approach works, but it feels a bit clunky:

In my initializer:

import { apiInitializer } from 'discourse/lib/api';
import loadScript from 'discourse/lib/load-script';
import myHelper from '../lib/helper';

export default apiInitializer('0.11.1', (api) => {
  api.decorateCookedElement(
    (elem) => {
      loadScript(D3_URL).then(() => {
        loadScript(LUXON_URL).then(() => {
          ...
          myHelper(whatever, d3, luxon)
          ...
        })
      })
    },
    {id: 'discourse-xyz', onlyStream: true}
  )
});

Then in myHelper.js:

export default function myHelper(whatever, d3, luxon) {
  d3();
  luxon();
  ...
}

I tried requiring the libraries from the helper file directly, but that means I’d have to return a promise and then do myHelper(whatever, d3, luxon).then(...) in the initializer, which I’d rather not do for other reasons.

Is there a better approach?

You can use the approach I use in GitHub - merefield/discourse-tc-tag-cloud: A Discourse Theme Component that displays a tag cloud above the tag lists on the tags page

Note the assets are registered here:

And sit in the assets folder.

4 Likes

Thanks, Robert. I gave it a try but it’s not finding “theme_uploads”. Is this something I should set up in settings.yml?

No, you shouldn’t need to do that.

I note the syntax is still in the spec: discourse/theme_spec.rb at c8f4f7c235ca38b39d4b66bf9e1305410e36815e · discourse/discourse · GitHub

1 Like

Ah, my bad. I had the wrong filename in assets. I’ve fixed it, but now I’m getting a CSP error:

load-script.js:35 Refused to load the script 
'http://localhost:4200/uploads/default/original/1X/c4a31754250cf6a40f7cbed182cfe2456d9be9fe.js' because it violates the following Content Security Policy directive: 
"script-src http://localhost:4200/logs/ http://localhost:4200/sidekiq/ http://localhost:4200/mini-profiler-resources/ http://localhost:4200/assets/ http://localhost:4200/brotli_asset/ http://localhost:4200/extra-locales/ http://localhost:4200/highlight-js/ http://localhost:4200/javascripts/ http://localhost:4200/plugins/ http://localhost:4200/theme-javascripts/ http://localhost:4200/svg-sprite/ 
'unsafe-eval' http://localhost:4200/ember-cli-live-reload.js http://localhost:4200/_lr/ /uploads". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

I didn’t see you use an extend_content_security_policy in settings.yml, so I don’t know what I’m missing.

1 Like

I’ve got the uploads directory url added to my CSP src setting in any case. But I might add that which would make it more targeted :+1:t2:

Oh, you mean here? It works if I do this:

I thought there was a way to do it in settings.yml, like this (but it doesn’t seem to work with localhost):

extend_content_security_policy:
  type: list
  default: "script_src: http://localhost:4200/"
1 Like