electron-userland / electron-compile

DEPRECATED: Electron supporting package to compile JS and CSS in Electron applications
1.01k stars 97 forks source link

Passthrough configuration not working for application/xml #278

Open ravihugo opened 6 years ago

ravihugo commented 6 years ago

Loving the dev experience! However I seem to have hit an interesting issue. This can be a low priority issue for me as I have a work-around but I wanted to at least report it.

My app is an electron-forge app from template react/typescript.

There is some XSLT processing in the app from a third party CDA viewer tool, which performs a fetch of an XSLT file. During the fetch I am getting an error (see last error in the issue). I researched it and found a few similar issues. Mostly: #94

Just hit this same issue with application/xml as the mime type when I was trying to use passthrough If I place it here in .compilerc:

{
  "env": {
    "development": {
      "application/xml": {
        "passthrough": true
      },

Error: Found compiler settings for missing compiler: application/xml

But if I place it at the root level:

{
  "application/xml": {
    "passthrough": true
  },
  "env": {
    "development": {
      "text/typescript": {

There is no startup error but there is also no effect on the .xslt file I am fetching with a REST call in the code.

The actual REST fetch results in the following error:

Failed to compile /PATH/src/ccdviewer/cda.xsl: Compiling /PATH/src/ccdviewer/cda.xsl resulted in a MIME type of application/xml, which we don't know how to handle
Error: Compiling /PATH/src/ccdviewer/cda.xsl resulted in a MIME type of application/xml, which we don't know how to handle
    at /PATH/node_modules/electron-compile/lib/compiler-host.js:431:17
    at Generator.next (<anonymous>)
...clipped...

My work-around was to simply rename the file I am fetching from .xsl to some other extension that electron doesn't really care about.

crdrost commented 6 years ago

It is actually even a little worse as passthrough is presently broken, though I did submit a pull request a week ago to fix it. If it had worked then the present semantics would recompile your XML infinitely. Maybe it's better that it did not recognize the MIME type!

So what's happening is that file.xsl is getting passed to @paulcbetts/mime-types which autodetects from the file extension that the proper type is application/xml which electron-compile cannot handle. Electron-compile very much at present hard-codes the compilers it works with, and this is probably what needs to change: choosing your compilers would instead be based entirely on a config file.

Given that env is also being deprecated by Babel it seems like the next step for electron-compile may be a .compilerc.js file with a new syntax for the config file. Just to spitball an idea as someone who has only just started being involved with electron-compile, maybe a possibility to retain the freedom you probably need is that this .compilerc.js file will module.exports = a JSON-serializable object which is a dictionary mapping MIME types to config objects, where a config object is an array whose first element is a string and whose subsequent elements depend on the first string. So you could maybe start with:

module.exports = {
  "application/xml": ["pass through"],
  "text/javascript": ["run once", "prettier", {}]
};

... or so. The arrays then give you s-expressions in the module library, which gives you a sort of little domain-specific language (maybe ["run once", ...args] immediately gets simplified to ["once", ["run", ...args] for example). We could then scaffold a missing .compilerc.js file to be something like:

const config = JSON.parse(require('fs').readFileSync('./.compilerc', {encoding: 'utf8'}));
const node_env = process.env.NODE_ENV || 'development';
const mimes = {};
function merge_config(conf1, conf2) {
  // fill in something better?
  return conf2;
}
for (let key of config) {
  if (key !== 'env') {
    mimes[key] = config[key];
  }
}
if (config.env && config.env[node_env]) {
  const override = config.env[node_env];
  for (let key of override) {
    mimes[key] = merge_config(mimes[key], override[key]);
  }
}
module.exports = {};
for (let mime of mimes) {
  switch (mime) {
      // fill in: map the currently fixed options like 'text/javascript' to ['run', 'babel'] or whatever, etc.
    default:
      module.exports[mime] = ['pass through'];
      break;
  }
}

This would decouple electron-compile from a fixed set of compilers without losing the deep flexibility that one gets from hard-coding (which one only does in the first place because ofc Babel needs something slightly different than SASS which needs something slightly different than LESS, or whatever). Like, in the absolute worst case you can just support the syntax "text/javascript": ["babel", babelrc_config] and get that logic back into the internals in a programmatic way.