UNPKG

5.29 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.getExports = getExports;
7exports.renderExports = renderExports;
8function forError(item) {
9 return typeof item === "string" ? item : `\n${JSON.stringify(item, null, " ")}\n`;
10}
11function splitCommand(command) {
12 const result = command.split("|").map(item => item.split(" ")).reduce((acc, val) => acc.concat(val), []);
13 for (const item of result) {
14 if (!item) {
15 throw new Error(`Invalid command "${item}" in "${command}" for exports. There must be only one separator: " ", or "|"`);
16 }
17 }
18 return result;
19}
20function resolveExports(type, item) {
21 let result;
22 if (typeof item === "string") {
23 const noWhitespaceItem = item.trim();
24 if (noWhitespaceItem.length === 0) {
25 throw new Error(`Invalid "${item}" value for export`);
26 }
27 const splittedItem = splitCommand(noWhitespaceItem);
28 if (splittedItem.length > 3) {
29 throw new Error(`Invalid "${item}" value for export`);
30 }
31 if (splittedItem.length === 1) {
32 result = {
33 syntax: type === "module" ? "named" : "multiple",
34 name: splittedItem[0],
35 // eslint-disable-next-line no-undefined
36 alias: undefined
37 };
38 } else {
39 result = {
40 syntax: splittedItem[0],
41 name: splittedItem[1],
42 alias:
43 // eslint-disable-next-line no-undefined
44 typeof splittedItem[2] !== "undefined" ? splittedItem[2] : undefined
45 };
46 }
47 } else {
48 result = {
49 syntax: type === "module" ? "named" : "multiple",
50 ...item
51 };
52 }
53 if (!["default", "named", "single", "multiple"].includes(result.syntax)) {
54 throw new Error(`Unknown "${result.syntax}" syntax export in "${forError(item)}" value`);
55 }
56 if (["default", "single"].includes(result.syntax) && typeof result.alias !== "undefined") {
57 throw new Error(`The "${result.syntax}" syntax can't have "${result.alias}" alias in "${forError(item)}" value`);
58 }
59 if (type === "commonjs") {
60 if (result.syntax === "default" || result.syntax === "named") {
61 throw new Error(`The "${type}" format can't be used with the "${result.syntax}" syntax export in "${forError(item)}" value`);
62 }
63 }
64 if (type === "module") {
65 if (result.syntax === "single" || result.syntax === "multiple") {
66 throw new Error(`The "${type}" format can't be used with the "${result.syntax}" syntax export in "${forError(item)}" value`);
67 }
68 }
69 return result;
70}
71function getIdentifiers(array) {
72 return array.reduce((accumulator, item) => {
73 if (typeof item.alias !== "undefined") {
74 accumulator.push({
75 type: "alias",
76 value: item.alias
77 });
78 return accumulator;
79 }
80 accumulator.push({
81 type: "name",
82 value: item.name
83 });
84 return accumulator;
85 }, []);
86}
87function getExports(type, exports) {
88 let result;
89 const exportItems = typeof exports === "string" && exports.includes(",") ? exports.split(",") : exports;
90 if (Array.isArray(exportItems)) {
91 result = exportItems.map(item => resolveExports(type, item));
92 } else {
93 result = [resolveExports(type, exportItems)];
94 }
95 const hasMultipleDefault = result.filter(({
96 syntax
97 }) => syntax === "default" || syntax === "single");
98 if (hasMultipleDefault.length > 1) {
99 throw new Error(`The "${type}" format can't have multiple "${type === "module" ? "default" : "single"}" exports in "\n${JSON.stringify(exports, null, " ")}\n" value`);
100 }
101 const identifiers = getIdentifiers(result);
102 const duplicates = duplicateBy(identifiers, "value");
103 if (duplicates.length > 0) {
104 throw new Error(`Duplicate ${duplicates.map(identifier => `"${identifier.value}" (as "${identifier.type}")`).join(", ")} identifiers found in "\n${JSON.stringify(exports, null, " ")}\n" value`);
105 }
106 return result;
107}
108function duplicateBy(array, key) {
109 return array.filter((a, aIndex) => array.filter((b, bIndex) => b[key] === a[key] && aIndex !== bIndex).length > 0);
110}
111function renderExports(loaderContext, type, exports) {
112 let code = "";
113 const defaultExport = exports.filter(({
114 syntax
115 }) => syntax === "default" || syntax === "single");
116 const namedExports = exports.filter(({
117 syntax
118 }) => syntax === "named" || syntax === "multiple");
119 if (defaultExport.length > 0) {
120 // eslint-disable-next-line default-case
121 switch (type) {
122 case "commonjs":
123 code += "module.exports = ";
124 break;
125 case "module":
126 code += "export default ";
127 break;
128 }
129 code += `${defaultExport[0].name};\n`;
130 }
131 if (namedExports.length > 0) {
132 // eslint-disable-next-line default-case
133 switch (type) {
134 case "commonjs":
135 code += "module.exports = {\n";
136 break;
137 case "module":
138 code += "export {\n";
139 break;
140 }
141 namedExports.forEach((namedExport, i) => {
142 const needComma = i < namedExports.length - 1;
143 const {
144 name
145 } = namedExport;
146 // eslint-disable-next-line no-undefined
147 const alias = namedExport.alias || undefined;
148 code += ` ${type === "commonjs" ? alias ? `${JSON.stringify(alias)}: (${name})` : `${name}` : `${name}${alias ? ` as ${alias}` : ""}`}${needComma ? ",\n" : ""}`;
149 });
150 code += "\n};\n";
151 }
152 return code;
153}
\No newline at end of file