codeplay-common 4.10.1 → 4.10.2
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.
|
@@ -5,12 +5,137 @@ const fs = require('fs');
|
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const plist = require('plist');
|
|
7
7
|
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
const migrateViteTreeShaking = (content) =>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
);
|
|
8
|
+
// Edit only build.rollupOptions.treeshake in the exported Vite config.
|
|
9
|
+
// Keep source formatting/comments and valid custom option objects intact.
|
|
10
|
+
const migrateViteTreeShaking = (content) => {
|
|
11
|
+
const newline = content.includes('\r\n') ? '\r\n' : '\n';
|
|
12
|
+
const tokens = [];
|
|
13
|
+
const pairs = new Map();
|
|
14
|
+
const stack = [];
|
|
15
|
+
const lexer = /\s+|\/\*[\s\S]*?\*\/|\/\/[^\r\n]*|"(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|`(?:\\[\s\S]|[^`\\])*`|=>|\.\.\.|[\w$]+|[^\s]/gy;
|
|
16
|
+
let match;
|
|
17
|
+
while ((match = lexer.exec(content))) {
|
|
18
|
+
const value = match[0];
|
|
19
|
+
if (/^\s|^\/\*|^\/\//.test(value)) continue;
|
|
20
|
+
// Regex literals may contain braces/commas; treat them as a single value.
|
|
21
|
+
if (value === '/' && (!tokens.length || /^(?:=|\(|\[|:|,|return|=>|!|\?|\||&)$/.test(tokens.at(-1).value))) {
|
|
22
|
+
const regex = /^\/(?:\\[^\r\n]|\[(?:\\[^\r\n]|[^\]\\\r\n])*\]|[^/\\[\r\n])+\/[a-z]*/.exec(content.slice(match.index));
|
|
23
|
+
if (!regex) throw new Error('Cannot safely read Vite regex literal; configuration preserved.');
|
|
24
|
+
lexer.lastIndex = match.index + regex[0].length;
|
|
25
|
+
tokens.push({ value: regex[0], start: match.index, end: lexer.lastIndex });
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const index = tokens.length;
|
|
29
|
+
tokens.push({ value, start: match.index, end: lexer.lastIndex });
|
|
30
|
+
if (['{', '[', '('].includes(value)) stack.push(index);
|
|
31
|
+
else if (['}', ']', ')'].includes(value)) {
|
|
32
|
+
const open = stack.pop();
|
|
33
|
+
if (open === undefined || tokens[open].value !== ({ '}': '{', ']': '[', ')': '(' })[value]) {
|
|
34
|
+
throw new Error('Cannot safely read Vite configuration; file preserved.');
|
|
35
|
+
}
|
|
36
|
+
pairs.set(open, index);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (stack.length) throw new Error('Unbalanced Vite configuration; file preserved.');
|
|
40
|
+
const value = index => tokens[index]?.value;
|
|
41
|
+
const edits = [];
|
|
42
|
+
const properties = open => {
|
|
43
|
+
const result = [];
|
|
44
|
+
const close = pairs.get(open);
|
|
45
|
+
for (let i = open + 1; i < close;) {
|
|
46
|
+
if (value(i) === ',') { i++; continue; }
|
|
47
|
+
const start = i;
|
|
48
|
+
let key = i;
|
|
49
|
+
if (value(i) === '[') {
|
|
50
|
+
if (pairs.get(i) !== i + 2 || !/^['"]/.test(value(i + 1))) throw new Error('Dynamic Vite property name; file preserved.');
|
|
51
|
+
key = i + 1;
|
|
52
|
+
}
|
|
53
|
+
const accessor = ['get', 'set'].includes(value(i)) && value(i + 2) === '(';
|
|
54
|
+
if (accessor) key = i + 1;
|
|
55
|
+
const name = value(key).replace(/^(['"])(.*)\1$/, '$2');
|
|
56
|
+
const afterKey = value(start) === '[' ? pairs.get(start) + 1 : key + 1;
|
|
57
|
+
const colon = value(afterKey) === ':';
|
|
58
|
+
while (i < close && value(i) !== ',') i = pairs.has(i) ? pairs.get(i) + 1 : i + 1;
|
|
59
|
+
if (colon || (key === start && i === start + 1) || value(afterKey) === '(') {
|
|
60
|
+
result.push({ name, start, first: colon ? afterKey + 1 : start, end: i, comma: value(i) === ',', colon });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
const findConfig = (index, visited = new Set()) => {
|
|
66
|
+
if (visited.has(index)) throw new Error('Circular Vite configuration reference; file preserved.');
|
|
67
|
+
visited.add(index);
|
|
68
|
+
if (value(index) === 'async') return findConfig(index + 1, visited);
|
|
69
|
+
if (value(index) === '(') {
|
|
70
|
+
const close = pairs.get(index);
|
|
71
|
+
if (value(close + 1) === '=>') return findBody(close + 2, visited);
|
|
72
|
+
return findConfig(index + 1, visited);
|
|
73
|
+
}
|
|
74
|
+
if (value(index + 1) === '=>') return findBody(index + 2, visited);
|
|
75
|
+
if (value(index) === 'function') {
|
|
76
|
+
let body = index + 1;
|
|
77
|
+
while (body < tokens.length && value(body) !== '{') body++;
|
|
78
|
+
return findBody(body, visited);
|
|
79
|
+
}
|
|
80
|
+
if (value(index) === '{') return index;
|
|
81
|
+
if (value(index + 1) === '(') return findConfig(index + 2, visited);
|
|
82
|
+
const declaration = tokens.findIndex((token, i) => ['const', 'let', 'var'].includes(token.value) && value(i + 1) === value(index) && value(i + 2) === '=');
|
|
83
|
+
if (declaration >= 0) return findConfig(declaration + 3, visited);
|
|
84
|
+
throw new Error('Unsupported dynamic Vite config; cannot safely set treeshake. File preserved.');
|
|
85
|
+
};
|
|
86
|
+
const findBody = (index, visited) => {
|
|
87
|
+
if (value(index) !== '{') return findConfig(index, visited);
|
|
88
|
+
const returns = [];
|
|
89
|
+
for (let i = index + 1; i < pairs.get(index); i++) {
|
|
90
|
+
if (value(i) === 'return') returns.push(i + 1);
|
|
91
|
+
if (pairs.has(i)) i = pairs.get(i);
|
|
92
|
+
}
|
|
93
|
+
if (returns.length !== 1) throw new Error('Vite config must return one static object for automatic treeshake migration. File preserved.');
|
|
94
|
+
return findConfig(returns[0], visited);
|
|
95
|
+
};
|
|
96
|
+
const append = (open, property) => {
|
|
97
|
+
const close = pairs.get(open);
|
|
98
|
+
const last = tokens[close - 1];
|
|
99
|
+
const line = content.slice(content.lastIndexOf('\n', tokens[open].start) + 1, tokens[open].start);
|
|
100
|
+
const indent = line.match(/^[ \t]*/)[0];
|
|
101
|
+
const needsComma = close > open + 1 && last.value !== ',';
|
|
102
|
+
const inlineComma = needsComma && last.end === tokens[close].start;
|
|
103
|
+
if (needsComma && !inlineComma) edits.push({ start: last.end, end: last.end, text: ',' });
|
|
104
|
+
edits.push({ start: tokens[close].start, end: tokens[close].start, text: `${inlineComma ? ',' : ''}${newline}${indent} ${property},${newline}${indent}` });
|
|
105
|
+
};
|
|
106
|
+
let exported = tokens.findIndex((token, i) => token.value === 'export' && value(i + 1) === 'default');
|
|
107
|
+
if (exported >= 0) exported += 2;
|
|
108
|
+
else {
|
|
109
|
+
exported = tokens.findIndex((token, i) => token.value === 'module' && value(i + 1) === '.' && value(i + 2) === 'exports' && value(i + 3) === '=');
|
|
110
|
+
if (exported >= 0) exported += 4;
|
|
111
|
+
}
|
|
112
|
+
if (exported < 0) throw new Error('No supported Vite config export found; file preserved.');
|
|
113
|
+
const config = findConfig(exported);
|
|
114
|
+
const build = properties(config).filter(property => property.name === 'build').at(-1);
|
|
115
|
+
if (!build) append(config, 'build: { rollupOptions: { treeshake: true } }');
|
|
116
|
+
else {
|
|
117
|
+
if (value(build.first) !== '{' || pairs.get(build.first) !== build.end - 1) throw new Error('Dynamic Vite build settings; file preserved.');
|
|
118
|
+
const rollup = properties(build.first).filter(property => property.name === 'rollupOptions').at(-1);
|
|
119
|
+
if (!rollup) append(build.first, 'rollupOptions: { treeshake: true }');
|
|
120
|
+
else {
|
|
121
|
+
if (value(rollup.first) !== '{' || pairs.get(rollup.first) !== rollup.end - 1) throw new Error('Dynamic Vite rollupOptions; file preserved.');
|
|
122
|
+
const entries = properties(rollup.first).filter(property => property.name === 'treeshake');
|
|
123
|
+
if (!entries.length) append(rollup.first, 'treeshake: true');
|
|
124
|
+
else {
|
|
125
|
+
// JavaScript uses the last duplicate; retain that setting and remove earlier ones.
|
|
126
|
+
const keep = entries.at(-1);
|
|
127
|
+
for (const entry of entries.slice(0, -1)) {
|
|
128
|
+
edits.push({ start: tokens[entry.start].start, end: entry.comma ? tokens[entry.end].end : tokens[entry.end - 1].end, text: '' });
|
|
129
|
+
}
|
|
130
|
+
const isTrue = value(keep.first) === 'true' && keep.end === keep.first + 1;
|
|
131
|
+
const isObject = value(keep.first) === '{' && pairs.get(keep.first) === keep.end - 1;
|
|
132
|
+
if (!isTrue && !isObject) edits.push({ start: tokens[keep.first].start, end: tokens[keep.end - 1].end, text: keep.colon ? 'true' : 'treeshake: true' });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) content = content.slice(0, edit.start) + edit.text + content.slice(edit.end);
|
|
137
|
+
return content;
|
|
138
|
+
};
|
|
14
139
|
|
|
15
140
|
|
|
16
141
|
|
|
@@ -2952,7 +3077,7 @@ const syncViteTreeShaking = () => {
|
|
|
2952
3077
|
const next = migrateViteTreeShaking(current);
|
|
2953
3078
|
if (next !== current) {
|
|
2954
3079
|
fs.writeFileSync(configPath, next, 'utf8');
|
|
2955
|
-
console.log('✅
|
|
3080
|
+
console.log('✅ Vite treeshake setting updated without duplicate entries.');
|
|
2956
3081
|
}
|
|
2957
3082
|
};
|
|
2958
3083
|
|