@brightspot/ui-builder 2.0.2 → 5.0.4-pre.20260626
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/dist/vite/vite-config.js
CHANGED
|
@@ -105,7 +105,6 @@ export async function createBuildConfig({ builder }) {
|
|
|
105
105
|
lib: {
|
|
106
106
|
entry: path.resolve(cwd, entry),
|
|
107
107
|
formats: [format],
|
|
108
|
-
fileName: () => output.jsName,
|
|
109
108
|
// Vite library mode requires `name` whenever format is 'iife'.
|
|
110
109
|
// resolveConfig guarantees this is set when format is iife (explicit
|
|
111
110
|
// or derived from package.json#name), so this guard is defensive
|
|
@@ -117,7 +116,19 @@ export async function createBuildConfig({ builder }) {
|
|
|
117
116
|
outDir: output.dir,
|
|
118
117
|
rollupOptions: {
|
|
119
118
|
output: {
|
|
120
|
-
|
|
119
|
+
// String form (not a function) so Rollup interpolates `[hash]`,
|
|
120
|
+
// `[name]`, and other tokens in `output.jsName` / `output.cssName`.
|
|
121
|
+
// Tokenless values pass through literally. `lib.fileName` is
|
|
122
|
+
// deliberately omitted — when both are set, `entryFileNames`
|
|
123
|
+
// takes precedence and tokens still don't interpolate inside
|
|
124
|
+
// `lib.fileName`'s return value.
|
|
125
|
+
entryFileNames: output.jsName,
|
|
126
|
+
assetFileNames: output.cssName,
|
|
127
|
+
// Hex (not Rollup's default base64) so emitted filenames match
|
|
128
|
+
// `[a-f0-9]+` — URL-safe lowercase, the contract any downstream
|
|
129
|
+
// caller that greps for hex hashes expects. No effect on
|
|
130
|
+
// tokenless filenames.
|
|
131
|
+
hashCharacters: 'hex',
|
|
121
132
|
...(format === 'iife' ? { intro: AMD_GUARD_INTRO, outro: AMD_GUARD_OUTRO } : {}),
|
|
122
133
|
},
|
|
123
134
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspot/ui-builder",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.4-pre.20260626",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"description": "Zero-config build toolkit for Brightspot CMS front-end development.",
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
"brightspot-ui": "./dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"exports": {
|
|
11
|
+
"./vite": {
|
|
12
|
+
"types": "./dist/vite/vite-config.d.ts",
|
|
13
|
+
"default": "./dist/vite/vite-config.js"
|
|
14
|
+
},
|
|
11
15
|
"./configs/tsconfig.base.json": "./configs/tsconfig.base.json",
|
|
12
16
|
"./configs/eslint.config.mjs": "./configs/eslint.config.mjs",
|
|
13
17
|
"./configs/prettier.config.mjs": "./configs/prettier.config.mjs"
|
|
@@ -19,6 +23,8 @@
|
|
|
19
23
|
"scripts": {
|
|
20
24
|
"build": "tsc --noEmitOnError && chmod +x ./dist/index.js",
|
|
21
25
|
"clean": "shx rm -rf ./dist/*",
|
|
26
|
+
"prepublishOnly": "yarn install --frozen-lockfile",
|
|
27
|
+
"prepack": "yarn build",
|
|
22
28
|
"test": "vitest run",
|
|
23
29
|
"test:watch": "vitest"
|
|
24
30
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function resolveTarget(): string;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import os from 'node:os';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { log } from './logger.js';
|
|
5
|
-
const LOCAL_URL_PATH = path.join(os.homedir(), '.brightspot', 'local-url');
|
|
6
|
-
const DEFAULT_TARGET = 'http://localhost';
|
|
7
|
-
export function resolveTarget() {
|
|
8
|
-
try {
|
|
9
|
-
const url = fs.readFileSync(LOCAL_URL_PATH, 'utf8').trim();
|
|
10
|
-
if (url) {
|
|
11
|
-
log.info(`Proxy target: ${url}`);
|
|
12
|
-
return url;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
log.warn(`${LOCAL_URL_PATH} not found — falling back to ${DEFAULT_TARGET}`);
|
|
17
|
-
}
|
|
18
|
-
return DEFAULT_TARGET;
|
|
19
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
-
/**
|
|
3
|
-
* Build a `proxyRes` handler that strips occurrences of the upstream
|
|
4
|
-
* origin from HTML response bodies. Brightspot embeds absolute URLs
|
|
5
|
-
* (e.g. `https://localhost/storage/resource_resource/foo.js`) for
|
|
6
|
-
* storage assets, generated from a CDN setting that ignores
|
|
7
|
-
* X-Forwarded-* headers. Without rewriting, the browser at the proxy
|
|
8
|
-
* origin (`https://localhost:5173`) would issue cross-origin requests
|
|
9
|
-
* back to the upstream — module scripts then fail CORS, and mixed
|
|
10
|
-
* content blocks plain-HTTP origins. Stripping the origin makes those
|
|
11
|
-
* URLs relative, so the browser routes them through the dev proxy.
|
|
12
|
-
*
|
|
13
|
-
* Non-HTML responses pass through untouched. Empty / no-content
|
|
14
|
-
* statuses pass through too.
|
|
15
|
-
*
|
|
16
|
-
* Requires `selfHandleResponse: true` on the proxy entry so the
|
|
17
|
-
* response stream isn't already piped to the client.
|
|
18
|
-
*/
|
|
19
|
-
export declare function rewriteHtmlBody(target: string): (proxyRes: IncomingMessage, _req: IncomingMessage, res: ServerResponse) => void;
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import zlib from 'node:zlib';
|
|
2
|
-
/**
|
|
3
|
-
* Build a `proxyRes` handler that strips occurrences of the upstream
|
|
4
|
-
* origin from HTML response bodies. Brightspot embeds absolute URLs
|
|
5
|
-
* (e.g. `https://localhost/storage/resource_resource/foo.js`) for
|
|
6
|
-
* storage assets, generated from a CDN setting that ignores
|
|
7
|
-
* X-Forwarded-* headers. Without rewriting, the browser at the proxy
|
|
8
|
-
* origin (`https://localhost:5173`) would issue cross-origin requests
|
|
9
|
-
* back to the upstream — module scripts then fail CORS, and mixed
|
|
10
|
-
* content blocks plain-HTTP origins. Stripping the origin makes those
|
|
11
|
-
* URLs relative, so the browser routes them through the dev proxy.
|
|
12
|
-
*
|
|
13
|
-
* Non-HTML responses pass through untouched. Empty / no-content
|
|
14
|
-
* statuses pass through too.
|
|
15
|
-
*
|
|
16
|
-
* Requires `selfHandleResponse: true` on the proxy entry so the
|
|
17
|
-
* response stream isn't already piped to the client.
|
|
18
|
-
*/
|
|
19
|
-
export function rewriteHtmlBody(target) {
|
|
20
|
-
const originPatterns = buildOriginPatterns(target);
|
|
21
|
-
return (proxyRes, _req, res) => {
|
|
22
|
-
const status = proxyRes.statusCode ?? 200;
|
|
23
|
-
const headers = sanitizeHeaders(proxyRes.headers);
|
|
24
|
-
// selfHandleResponse: true disables the proxy library's built-in
|
|
25
|
-
// autoRewrite/protocolRewrite, so redirect Location headers come
|
|
26
|
-
// through pointing at the upstream origin. Strip the upstream
|
|
27
|
-
// origin so the browser follows the redirect via the proxy, not
|
|
28
|
-
// directly to the upstream (which would be cross-origin / wrong
|
|
29
|
-
// port / wrong scheme).
|
|
30
|
-
const loc = headers['location'];
|
|
31
|
-
if (typeof loc === 'string') {
|
|
32
|
-
let rewritten = loc;
|
|
33
|
-
for (const re of originPatterns)
|
|
34
|
-
rewritten = rewritten.replace(re, '');
|
|
35
|
-
if (rewritten !== loc)
|
|
36
|
-
headers['location'] = rewritten;
|
|
37
|
-
}
|
|
38
|
-
const ct = String(headers['content-type'] ?? '').toLowerCase();
|
|
39
|
-
const isHtml = ct.includes('text/html');
|
|
40
|
-
const isEmpty = status === 204 || status === 304;
|
|
41
|
-
if (!isHtml || isEmpty) {
|
|
42
|
-
res.writeHead(status, headers);
|
|
43
|
-
proxyRes.pipe(res);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const stream = decodeStream(proxyRes, String(proxyRes.headers['content-encoding'] ?? ''));
|
|
47
|
-
const chunks = [];
|
|
48
|
-
stream.on('data', c => chunks.push(c));
|
|
49
|
-
stream.on('error', err => {
|
|
50
|
-
res.writeHead(502, { 'content-type': 'text/plain' });
|
|
51
|
-
res.end(`proxy decode error: ${err.message}`);
|
|
52
|
-
});
|
|
53
|
-
stream.on('end', () => {
|
|
54
|
-
let body = Buffer.concat(chunks).toString('utf8');
|
|
55
|
-
for (const re of originPatterns)
|
|
56
|
-
body = body.replace(re, '');
|
|
57
|
-
const out = Buffer.from(body, 'utf8');
|
|
58
|
-
headers['content-length'] = String(out.length);
|
|
59
|
-
res.writeHead(status, headers);
|
|
60
|
-
res.end(out);
|
|
61
|
-
});
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
// Vite serves over HTTP/2 (mkcert), but the upstream speaks HTTP/1.1.
|
|
65
|
-
// HTTP/2 forbids connection-specific headers and transfer-encoding;
|
|
66
|
-
// passing them through triggers ERR_HTTP2_INVALID_CONNECTION_HEADERS
|
|
67
|
-
// in node's writeHead. Also drop content-encoding because we always
|
|
68
|
-
// decompress and re-emit identity. content-length is recomputed by
|
|
69
|
-
// the caller after rewriting.
|
|
70
|
-
function sanitizeHeaders(input) {
|
|
71
|
-
const dropped = new Set([
|
|
72
|
-
'connection',
|
|
73
|
-
'transfer-encoding',
|
|
74
|
-
'keep-alive',
|
|
75
|
-
'proxy-authenticate',
|
|
76
|
-
'proxy-authorization',
|
|
77
|
-
'te',
|
|
78
|
-
'trailer',
|
|
79
|
-
'upgrade',
|
|
80
|
-
'http2-settings',
|
|
81
|
-
'content-encoding',
|
|
82
|
-
'content-length',
|
|
83
|
-
]);
|
|
84
|
-
const out = {};
|
|
85
|
-
for (const [k, v] of Object.entries(input)) {
|
|
86
|
-
if (v === undefined)
|
|
87
|
-
continue;
|
|
88
|
-
if (dropped.has(k.toLowerCase()))
|
|
89
|
-
continue;
|
|
90
|
-
out[k] = v;
|
|
91
|
-
}
|
|
92
|
-
return out;
|
|
93
|
-
}
|
|
94
|
-
function decodeStream(stream, encoding) {
|
|
95
|
-
switch (encoding.toLowerCase()) {
|
|
96
|
-
case 'gzip':
|
|
97
|
-
return stream.pipe(zlib.createGunzip());
|
|
98
|
-
case 'br':
|
|
99
|
-
return stream.pipe(zlib.createBrotliDecompress());
|
|
100
|
-
case 'deflate':
|
|
101
|
-
return stream.pipe(zlib.createInflate());
|
|
102
|
-
default:
|
|
103
|
-
return stream;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// Build regexes that match the upstream origin in a few common
|
|
107
|
-
// forms — both `http://` and `https://` so an http target still
|
|
108
|
-
// strips https variants the CMS may emit when X-Forwarded-Proto is
|
|
109
|
-
// honored, and an explicit-port form so e.g. http://localhost:8080
|
|
110
|
-
// strips both with and without :8080.
|
|
111
|
-
function buildOriginPatterns(target) {
|
|
112
|
-
const escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
113
|
-
const u = new URL(target);
|
|
114
|
-
const host = u.hostname;
|
|
115
|
-
const explicitPort = u.port;
|
|
116
|
-
// Form: scheme://host(:port)? — only strip when followed by a path
|
|
117
|
-
// boundary so we don't eat unrelated strings that happen to share
|
|
118
|
-
// the prefix.
|
|
119
|
-
const patterns = [
|
|
120
|
-
new RegExp(`https?://${escape(host)}(?=[/'"\\)\\s])`, 'g'),
|
|
121
|
-
new RegExp(`https?://${escape(host)}:\\d+(?=[/'"\\)\\s])`, 'g'),
|
|
122
|
-
];
|
|
123
|
-
void explicitPort;
|
|
124
|
-
return patterns;
|
|
125
|
-
}
|