UNPKG

3.75 kBJavaScriptView Raw
1"use strict";
2
3const Plugin = require('broccoli-plugin');
4const fs = require('fs');
5const path = require('path');
6const walkSync = require('walk-sync');
7const getModuleConfig = require('./get-module-config');
8const getModuleSpecifier = require('./get-module-specifier');
9
10const IGNORED_EXTENSIONS = ['', '.md', '.html'];
11const INTERFACE = `
12export interface Dict<T> {
13 [index: string]: T;
14}
15declare let map: Dict<any>;
16export default map;
17`;
18
19function ResolutionMapBuilder(src, config, options) {
20 options = options || {};
21 Plugin.call(this, [src, config], {
22 annotation: options.annotation
23 });
24 this.options = options;
25}
26
27ResolutionMapBuilder.prototype = Object.create(Plugin.prototype);
28
29ResolutionMapBuilder.prototype.constructor = ResolutionMapBuilder;
30
31ResolutionMapBuilder.prototype.build = function() {
32 // Attempt to read config file
33 let configPath = path.posix.join(this.inputPaths[1], this.options.configPath);
34 let config;
35 if (fs.existsSync(configPath)) {
36 let configContents = fs.readFileSync(configPath, { encoding: 'utf8' });
37 config = JSON.parse(configContents);
38 } else {
39 config = {};
40 }
41
42 let moduleConfig = getModuleConfig(config.moduleConfiguration || this.options.defaultModuleConfiguration);
43 if (!moduleConfig) {
44 throw new Error(`The module configuration could not be found. Please add a config file to '${configPath}' and export an object with a 'moduleConfiguration' member.`);
45 }
46
47 let modulePrefix = config.modulePrefix || this.options.defaultModulePrefix;
48 if (!modulePrefix) {
49 throw new Error(`The module prefix could not be found. Add a config file to '${configPath}' and export an object with a 'modulePrefix' member.`);
50 }
51
52 let baseDir = this.options.baseDir || '';
53 let modulePath = path.posix.join(this.inputPaths[0], baseDir);
54 let modulePaths = walkSync(modulePath);
55 let mappedPaths = [];
56 let moduleImports = [];
57 let mapContents = [];
58
59 modulePaths.forEach(function(modulePath) {
60 let pathParts = path.parse(modulePath);
61
62 if (IGNORED_EXTENSIONS.indexOf(pathParts.ext) > -1) {
63 return;
64 }
65
66 let name = path.posix.join(pathParts.dir, pathParts.name);
67
68 // filter out index module
69 if (name !== 'index' && name !== 'main') {
70 mappedPaths.push(modulePath);
71 }
72 });
73
74 if (this.options.logSpecifiers) {
75 this.specifiers = [];
76 }
77
78 mappedPaths.forEach(modulePath => {
79 let module = modulePath.substring(0, modulePath.lastIndexOf('.'));
80 let extension = modulePath.substring(modulePath.lastIndexOf('.') + 1);
81 let specifier = getModuleSpecifier(modulePrefix, moduleConfig, module, extension);
82
83 // Only process non-null specifiers returned.
84 // Specifiers may be null in the case of an unresolvable collection (e.g. utils)
85 if (specifier) {
86 let moduleImportPath = path.posix.join('..', baseDir, module);
87 let moduleVar = '__' + module.replace(/\//g, '__').replace(/-/g, '_') + '__';
88 let moduleImport = "import { default as " + moduleVar + " } from '" + moduleImportPath + "';";
89 moduleImports.push(moduleImport);
90 mapContents.push("'" + specifier + "': " + moduleVar);
91
92 if (this.options.logSpecifiers) {
93 this.specifiers.push(specifier);
94 }
95 }
96 });
97
98 let destPath = path.posix.join(this.outputPath, 'config');
99 if (!fs.existsSync(destPath)) {
100 fs.mkdirSync(destPath);
101 }
102
103 let contents = moduleImports.join('\n') + '\n' +
104 "export default {" + mapContents.join(',') + "};" + '\n';
105
106 fs.writeFileSync(path.posix.join(this.outputPath, 'config', 'module-map.js'), contents, { encoding: 'utf8' });
107 fs.writeFileSync(path.posix.join(this.outputPath, 'config', 'module-map.d.ts'), INTERFACE, { encoding: 'utf8' });
108};
109
110module.exports = ResolutionMapBuilder;