Skip to content

Commit

Permalink
refactor(config): go back to initial approach
Browse files Browse the repository at this point in the history
  • Loading branch information
emmenko committed May 10, 2022
1 parent f772751 commit 73b28db
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 45 deletions.
30 changes: 30 additions & 0 deletions packages/application-config/loaders/load-js-module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const get = require('lodash/get');

/**
* Custom JS module loader.
* This loader is used to load Custom Application config files that are not JSON files,
* for example any JS or TS files.
* To load the file, we need to make sure that we use our Babel preset to allow parsing
* the file with the supported features. TypeScript files are also loaded via the preset.
* Futhermore, we need to load the config file as a module, meaning that the exported
* Custom Application config can potentially contain JS functions and these should be preserved.
* To do that, we use `@babel/register` and ensure the Babel preset is used.
*/
function loadJsModule(filePath) {
// Skip registering Babel for tests, as Babel is alrady configured.
if (process.env.NODE_ENV !== 'test') {
require('@babel/register')({
babelrc: false,
extensions: ['.js', '.cjs', '.mjs', '.ts'],
presets: ['@commercetools-frontend/babel-preset-mc-app'],
});
}

// Require the module. It's expected that the module exports the application config.
const moduleExport = require(filePath);

// In case we are loading an ES module, we need to pick the `default` export.
return get(moduleExport, 'default', moduleExport);
}

module.exports = loadJsModule;
3 changes: 2 additions & 1 deletion packages/application-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"files": [
"dist",
"loaders",
"ssr",
"schema.json",
"package.json",
Expand All @@ -31,7 +32,7 @@
"build:schema": "json2ts schema.json src/schema.ts --style.singleQuote --bannerComment '/* eslint-disable prettier/prettier */\n// This file was automatically generated by json-schema-to-typescript.\n// DO NOT MODIFY IT BY HAND. Instead, modify the source schema.json file.'"
},
"dependencies": {
"@babel/core": "^7.17.9",
"@babel/register": "^7.17.7",
"@babel/runtime": "^7.17.9",
"@babel/runtime-corejs3": "^7.17.9",
"@commercetools-frontend/babel-preset-mc-app": "21.3.4",
Expand Down
60 changes: 20 additions & 40 deletions packages/application-config/src/load-config.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,32 @@
import fs from 'fs';
import getInObject from 'lodash/get';
import { transformSync } from '@babel/core';
import path from 'path';
import { cosmiconfigSync, defaultLoaders, type LoaderSync } from 'cosmiconfig';
import type { JSONSchemaForCustomApplicationConfigurationFiles } from './schema';
import { MissingOrInvalidConfigError } from './errors';

/**
* Custom JS module loader.
* This loader is used to load Custom Application config files that are not JSON files,
* for example any JS or TS files.
* To load the file, we need to make sure that we use our Babel preset to allow parsing
* the file with the supported features. TypeScript files are also loaded via the preset.
* Futhermore, we need to load the config file as a module, meaning that the exported
* Custom Application config can potentially contain JS functions.
* To do that, we need to first compile the file via Babel and then `require` it via Node.
* To keep things simple, we write a temporary file to the file system with the compiled code,
* require it and remove the compiled file again.
*/
const loadJsModule: LoaderSync = (filePath, content) => {
// Compile the config file with our Babel preset.
const transformResult = transformSync(content, {
filename: filePath,
babelrc: false,
presets: [
require.resolve('@commercetools-frontend/babel-preset-mc-app/production'),
],
});

if (!transformResult?.code) {
throw new Error(
`Failed to read Custom Application config file "${filePath}".`
);
// Helper function to find the package root path from the current location,
// for instance in respect to both source files and dist files.
const findPackageRootPath = (dir: string): string => {
const packageJsonPath = path.join(dir, 'package.json');
if (fs.existsSync(packageJsonPath)) {
return dir;
}
const parentDir = path.join(dir, '..');
return findPackageRootPath(parentDir);
};

const compiledConfigFilePath = `${filePath}.compiled`;
// Write the compiled config file.
fs.writeFileSync(compiledConfigFilePath, transformResult.code, {
encoding: 'utf8',
});

// Require the compiled module.
const moduleExport = require(compiledConfigFilePath);
const loadJsModule: LoaderSync = (filePath) => {
const packageRootPath = findPackageRootPath(
// Start from the parent folder
path.join(__dirname, '..')
);

// Remove the compiled module.
fs.rmSync(compiledConfigFilePath, { force: true });
const moduleLoader = require(path.join(
packageRootPath,
'loaders/load-js-module.js'
));

// In case we are loading an ES module, we need to pick the `default` export.
return getInObject(moduleExport, 'default', moduleExport);
return moduleLoader(filePath);
};

const moduleName = 'custom-application-config';
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
exports.entryPointUriPath = 'test';
const {
entryPointUriPathToPermissionKeys,
} = require('@commercetools-frontend/application-shell/ssr');

const entryPointUriPath = 'test';

exports.entryPointUriPath = entryPointUriPath;
exports.PERMISSIONS = entryPointUriPathToPermissionKeys(entryPointUriPath);
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
const {
entryPointUriPathToPermissionKeys,
} = require('@commercetools-frontend/application-shell/ssr');

const entryPointUriPath = 'test';
const PERMISSIONS = entryPointUriPathToPermissionKeys(entryPointUriPath);

module.exports = { entryPointUriPath };
module.exports = { entryPointUriPath, PERMISSIONS };
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
import { entryPointUriPathToPermissionKeys } from '@commercetools-frontend/application-shell/ssr';

export const entryPointUriPath = 'test';
export const PERMISSIONS = entryPointUriPathToPermissionKeys(entryPointUriPath);
3 changes: 3 additions & 0 deletions packages/application-config/test/fixtures/app-ts/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
import { entryPointUriPathToPermissionKeys } from '@commercetools-frontend/application-shell/ssr';

export const entryPointUriPath = 'test';
export const PERMISSIONS = entryPointUriPathToPermissionKeys(entryPointUriPath);
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1893,7 +1893,7 @@ __metadata:
languageName: node
linkType: hard

"@babel/register@npm:^7.13.16":
"@babel/register@npm:^7.13.16, @babel/register@npm:^7.17.7":
version: 7.17.7
resolution: "@babel/register@npm:7.17.7"
dependencies:
Expand Down Expand Up @@ -2651,7 +2651,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@commercetools-frontend/application-config@workspace:packages/application-config"
dependencies:
"@babel/core": ^7.17.9
"@babel/register": ^7.17.7
"@babel/runtime": ^7.17.9
"@babel/runtime-corejs3": ^7.17.9
"@commercetools-frontend/babel-preset-mc-app": 21.3.4
Expand Down

0 comments on commit 73b28db

Please sign in to comment.