codeplay-common 4.10.1 → 4.10.3
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/CHANGELOG.md +10 -0
- package/RELEASE_NOTES.md +10 -0
- package/files/buildCodeplay/codeplayBeforeBuild.js +132 -7
- package/files/finalrelease +7 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.10.3 — 2026-10-23
|
|
4
|
+
|
|
5
|
+
Version name: 4.10.3. Version code/build number: not applicable to this npm package.
|
|
6
|
+
|
|
7
|
+
Files changed: `package.json`, `files/finalrelease`, `CHANGELOG.md`, `RELEASE_NOTES.md`.
|
|
8
|
+
|
|
9
|
+
- Allow ad-free apps with `plugins.AdMob.ADMOB_ENABLED: false` to pass release validation without an AdMob alias or controller.
|
|
10
|
+
- Continue requiring a production AdMob alias when advertising is enabled or the enabled flag is unspecified.
|
|
11
|
+
- Preserve rejection of test aliases, commented or duplicate aliases, and missing production controllers for apps with ads enabled.
|
|
12
|
+
|
|
3
13
|
## 4.10.0 — 2026-10-23
|
|
4
14
|
|
|
5
15
|
Version name: 4.10.0. Version code/build number: not applicable to this npm package.
|
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Release notes
|
|
2
2
|
|
|
3
|
+
## 4.10.3 — 2026-10-23
|
|
4
|
+
|
|
5
|
+
Version name: 4.10.3. Version code/build number: not applicable to this npm package.
|
|
6
|
+
|
|
7
|
+
Files changed: `package.json`, `files/finalrelease`, `CHANGELOG.md`, `RELEASE_NOTES.md`.
|
|
8
|
+
|
|
9
|
+
- Release ad-free apps without adding an unnecessary AdMob alias or controller.
|
|
10
|
+
- Explicitly set `plugins.AdMob.ADMOB_ENABLED` to `false` to use the ad-free release path.
|
|
11
|
+
- Keep production AdMob safety checks for apps with advertising enabled.
|
|
12
|
+
|
|
3
13
|
## 4.10.0 — 2026-10-23
|
|
4
14
|
|
|
5
15
|
Version name: 4.10.0. Version code/build number: not applicable to this npm package.
|
|
@@ -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
|
|
package/files/finalrelease
CHANGED
|
@@ -90,6 +90,12 @@ function stripJavaScriptComments(content) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
function checkProductionAdmobAlias() {
|
|
93
|
+
const capacitorConfig = JSON.parse(readFileSync(resolve(__dirname, 'capacitor.config.json'), 'utf8'));
|
|
94
|
+
if (capacitorConfig.plugins?.AdMob?.ADMOB_ENABLED === false) {
|
|
95
|
+
console.log('ℹ️ AdMob is disabled; production @admob alias validation skipped.');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
93
99
|
const possibleConfigFiles = ['vite.config.mjs', 'vite.config.js'];
|
|
94
100
|
const viteConfigPath = possibleConfigFiles
|
|
95
101
|
.map(configFile => resolve(__dirname, configFile))
|
|
@@ -133,7 +139,7 @@ function checkProductionAdmobAlias() {
|
|
|
133
139
|
console.log(`✅ Production @admob alias verified: ${activeAlias}`);
|
|
134
140
|
}
|
|
135
141
|
|
|
136
|
-
//
|
|
142
|
+
// Validate the production alias first when AdMob is enabled.
|
|
137
143
|
checkProductionAdmobAlias();
|
|
138
144
|
|
|
139
145
|
// Define a mapping between store IDs and store names
|