gofront 1.6.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/vendor.js CHANGED
@@ -19,12 +19,17 @@ export function getExportNames(pkgName, globals = {}) {
19
19
  const clean = base.replace(/[^a-zA-Z0-9_]/g, "_");
20
20
  const names = new Set([pkgName, base, clean]);
21
21
  const extra = globals[pkgName];
22
- for (const name of Array.isArray(extra) ? extra : extra ? [extra] : [])
23
- names.add(name);
22
+ for (const name of Array.isArray(extra)
23
+ ? extra
24
+ : typeof extra === "string"
25
+ ? [extra]
26
+ : []) {
27
+ if (typeof name === "string") names.add(name);
28
+ }
24
29
  return [...names];
25
30
  }
26
31
 
27
- export function generateVendorEntry(packages, globals = {}) {
32
+ export function generateVendorEntry(packages, globals = {}, namedExports = {}) {
28
33
  const imports = [];
29
34
  const assignments = [];
30
35
  const exports = [];
@@ -40,6 +45,46 @@ export function generateVendorEntry(packages, globals = {}) {
40
45
  );
41
46
  }
42
47
 
48
+ // Named export global assignments (e.g. window.h = preact.h)
49
+ const pkgNamed = Object.create(null);
50
+ const rawNamed = namedExports[pkg];
51
+ const isSafeKey = (k) =>
52
+ typeof k === "string" &&
53
+ k !== "__proto__" &&
54
+ k !== "prototype" &&
55
+ k !== "constructor";
56
+
57
+ if (Array.isArray(rawNamed)) {
58
+ for (const name of rawNamed) {
59
+ if (isSafeKey(name)) pkgNamed[name] = name;
60
+ }
61
+ } else if (rawNamed && typeof rawNamed === "object") {
62
+ for (const [k, v] of Object.entries(rawNamed)) {
63
+ if (isSafeKey(k) && isSafeKey(v)) pkgNamed[k] = v;
64
+ }
65
+ }
66
+
67
+ if (typeof globals[pkg] === "object" && !Array.isArray(globals[pkg])) {
68
+ for (const [k, v] of Object.entries(globals[pkg])) {
69
+ if (isSafeKey(k) && isSafeKey(v)) pkgNamed[k] = v;
70
+ }
71
+ } else if (Array.isArray(globals[pkg])) {
72
+ for (const item of globals[pkg]) {
73
+ if (typeof item === "object" && item !== null) {
74
+ for (const [k, v] of Object.entries(item)) {
75
+ if (isSafeKey(k) && isSafeKey(v)) pkgNamed[k] = v;
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ for (const [globalName, exportName] of Object.entries(pkgNamed)) {
82
+ if (!isSafeKey(globalName) || !isSafeKey(exportName)) continue;
83
+ assignments.push(
84
+ ` window[${JSON.stringify(globalName)}] = ${id}[${JSON.stringify(exportName)}] !== undefined ? ${id}[${JSON.stringify(exportName)}] : (${id}.default ? ${id}.default[${JSON.stringify(exportName)}] : undefined);`,
85
+ );
86
+ }
87
+
43
88
  const cleanId = pkg
44
89
  .replace(/^@[^/]+\//, "")
45
90
  .replace(/[^a-zA-Z0-9_$]/g, "_");
@@ -82,8 +127,26 @@ function findBundler(projectDir) {
82
127
  return null;
83
128
  }
84
129
 
85
- // Normalises `vendor.globals` ({ pkg: string | string[] }) to { pkg: string[] }.
86
- function normalizeGlobals(raw) {
130
+ export function normalizeNamedExports(raw) {
131
+ if (raw === undefined || raw === null) return {};
132
+ if (typeof raw !== "object" || Array.isArray(raw)) return {};
133
+ const out = {};
134
+ for (const [pkg, value] of Object.entries(raw)) {
135
+ if (Array.isArray(value)) {
136
+ const map = {};
137
+ for (const name of value) {
138
+ if (typeof name === "string") map[name] = name;
139
+ }
140
+ out[pkg] = map;
141
+ } else if (typeof value === "object" && value !== null) {
142
+ out[pkg] = { ...value };
143
+ }
144
+ }
145
+ return out;
146
+ }
147
+
148
+ // Normalises `vendor.globals` ({ pkg: string | string[] | object })
149
+ export function normalizeGlobals(raw) {
87
150
  if (raw === undefined || raw === null) return {};
88
151
  if (typeof raw !== "object" || Array.isArray(raw)) {
89
152
  throw new Error(
@@ -92,13 +155,17 @@ function normalizeGlobals(raw) {
92
155
  }
93
156
  const out = {};
94
157
  for (const [pkg, value] of Object.entries(raw)) {
95
- const list = Array.isArray(value) ? value : [value];
96
- if (list.some((v) => typeof v !== "string")) {
158
+ if (typeof value === "string") {
159
+ out[pkg] = [value];
160
+ } else if (Array.isArray(value)) {
161
+ out[pkg] = value;
162
+ } else if (typeof value === "object" && value !== null) {
163
+ out[pkg] = value;
164
+ } else {
97
165
  throw new Error(
98
- `gofront: vendor.globals[${JSON.stringify(pkg)}] must be a string or array of strings`,
166
+ `gofront: vendor.globals[${JSON.stringify(pkg)}] must be a string, array, or object`,
99
167
  );
100
168
  }
101
- out[pkg] = list;
102
169
  }
103
170
  return out;
104
171
  }
@@ -119,6 +186,7 @@ export function loadVendorConfig(projectDir) {
119
186
  let packages = dependencies;
120
187
  let minify = false;
121
188
  let globals = {};
189
+ let namedExports = {};
122
190
 
123
191
  if (typeof vendorConfig === "string") {
124
192
  dest = vendorConfig;
@@ -127,13 +195,16 @@ export function loadVendorConfig(projectDir) {
127
195
  if (Array.isArray(vendorConfig.packages)) packages = vendorConfig.packages;
128
196
  if (typeof vendorConfig.minify === "boolean") minify = vendorConfig.minify;
129
197
  globals = normalizeGlobals(vendorConfig.globals);
198
+ namedExports = normalizeNamedExports(
199
+ vendorConfig.namedExports ?? vendorConfig.exports,
200
+ );
130
201
  }
131
202
 
132
203
  if (!dest) {
133
204
  dest = existsSync(join(projectDir, "app")) ? "app/vendor.js" : "vendor.js";
134
205
  }
135
206
 
136
- return { dest, packages, minify, globals };
207
+ return { dest, packages, minify, globals, namedExports };
137
208
  }
138
209
 
139
210
  function resolveDestinationPaths(projectRoot, dest) {
@@ -299,6 +370,10 @@ export async function bundleVendor(projectDir = ".", options = {}) {
299
370
  const dest = options.dest ?? config.dest;
300
371
  const minify = options.minify ?? config.minify ?? false;
301
372
  const globals = { ...config.globals, ...normalizeGlobals(options.globals) };
373
+ const namedExports = {
374
+ ...config.namedExports,
375
+ ...normalizeNamedExports(options.namedExports ?? options.exports),
376
+ };
302
377
 
303
378
  if (!packages || packages.length === 0) {
304
379
  return {
@@ -366,7 +441,7 @@ export async function bundleVendor(projectDir = ".", options = {}) {
366
441
  };
367
442
  }
368
443
 
369
- const entryCode = generateVendorEntry(packages, globals);
444
+ const entryCode = generateVendorEntry(packages, globals, namedExports);
370
445
  const entryFile = join(
371
446
  projectRoot,
372
447
  `.gofront-vendor-entry-${Date.now()}.mjs`,