@daemux/store-automator 0.10.67 → 0.10.68
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,14 +5,14 @@
|
|
|
5
5
|
},
|
|
6
6
|
"metadata": {
|
|
7
7
|
"description": "App Store & Google Play automation for Flutter apps",
|
|
8
|
-
"version": "0.10.
|
|
8
|
+
"version": "0.10.68"
|
|
9
9
|
},
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "store-automator",
|
|
13
13
|
"source": "./plugins/store-automator",
|
|
14
14
|
"description": "3 agents for app store publishing: reviewer, meta-creator, media-designer",
|
|
15
|
-
"version": "0.10.
|
|
15
|
+
"version": "0.10.68",
|
|
16
16
|
"keywords": [
|
|
17
17
|
"flutter",
|
|
18
18
|
"app-store",
|
package/package.json
CHANGED
package/src/templates.mjs
CHANGED
|
@@ -3,9 +3,11 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { ensureDir } from './utils.mjs';
|
|
4
4
|
import { backupIfChanging } from './backup.mjs';
|
|
5
5
|
|
|
6
|
+
const PLUGIN_NAME = 'daemux-store-automator';
|
|
6
7
|
const SENTINEL_BEGIN = '<!-- BEGIN daemux-store-automator -->';
|
|
7
8
|
const SENTINEL_END = '<!-- END daemux-store-automator -->';
|
|
8
9
|
const SENTINEL_BLOCK_RE = /<!-- BEGIN daemux-store-automator -->[\s\S]*?<!-- END daemux-store-automator -->/;
|
|
10
|
+
const FOREIGN_SENTINEL_RE = /<!-- BEGIN daemux-[a-z0-9-]+ -->[\s\S]*?<!-- END daemux-[a-z0-9-]+ -->/g;
|
|
9
11
|
|
|
10
12
|
const FILE_COPIES = [
|
|
11
13
|
['ci.config.yaml.template', 'ci.config.yaml'],
|
|
@@ -63,6 +65,12 @@ function looksLikeUnsentineledPluginContent(existing) {
|
|
|
63
65
|
return startsWithHeader && hasFastlane;
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
function hasForeignSentinels(existing) {
|
|
69
|
+
const matches = existing.match(FOREIGN_SENTINEL_RE);
|
|
70
|
+
if (!matches) return false;
|
|
71
|
+
return matches.some((m) => !m.includes(PLUGIN_NAME));
|
|
72
|
+
}
|
|
73
|
+
|
|
66
74
|
function composeNewFileContent(existing, wrappedBlock) {
|
|
67
75
|
if (!existing) {
|
|
68
76
|
return wrappedBlock;
|
|
@@ -71,6 +79,13 @@ function composeNewFileContent(existing, wrappedBlock) {
|
|
|
71
79
|
return existing.replace(SENTINEL_BLOCK_RE, wrappedBlock.replace(/\n$/, ''));
|
|
72
80
|
}
|
|
73
81
|
if (looksLikeUnsentineledPluginContent(existing)) {
|
|
82
|
+
if (hasForeignSentinels(existing)) {
|
|
83
|
+
console.log(
|
|
84
|
+
'Note: another Daemux plugin sentinel block detected. Appending updated ' +
|
|
85
|
+
'plugin block; you may want to manually remove the older unsentineled content.'
|
|
86
|
+
);
|
|
87
|
+
return `${existing.trimEnd()}\n\n${wrappedBlock}`;
|
|
88
|
+
}
|
|
74
89
|
return wrappedBlock;
|
|
75
90
|
}
|
|
76
91
|
const sep = existing.endsWith('\n') ? '' : '\n';
|
package/src/uninstall.mjs
CHANGED
|
@@ -12,10 +12,7 @@ import {
|
|
|
12
12
|
} from './utils.mjs';
|
|
13
13
|
import { removeMcpServers } from './mcp-setup.mjs';
|
|
14
14
|
import { backupIfChanging, pruneBackups } from './backup.mjs';
|
|
15
|
-
import {
|
|
16
|
-
readManagedSettings, getLedgerPath,
|
|
17
|
-
HISTORICAL_ENV_KEYS, HISTORICAL_ENV_VALUES,
|
|
18
|
-
} from './managed-settings.mjs';
|
|
15
|
+
import { readManagedSettings, getLedgerPath } from './managed-settings.mjs';
|
|
19
16
|
|
|
20
17
|
const SENTINEL_BEGIN = '<!-- BEGIN daemux-store-automator -->';
|
|
21
18
|
const SENTINEL_END = '<!-- END daemux-store-automator -->';
|
|
@@ -127,76 +124,36 @@ function cleanClaudeMd(baseDir, scopeLabel) {
|
|
|
127
124
|
}
|
|
128
125
|
}
|
|
129
126
|
|
|
130
|
-
function looksLikeHistoricalPluginStatusLine(current) {
|
|
131
|
-
return Boolean(
|
|
132
|
-
current
|
|
133
|
-
&& typeof current === 'object'
|
|
134
|
-
&& current.type === 'command'
|
|
135
|
-
&& typeof current.command === 'string'
|
|
136
|
-
&& current.command.includes('context_window')
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function pruneManagedEnv(settings, envKeys, envValues) {
|
|
141
|
-
if (!settings.env) return false;
|
|
142
|
-
let modified = false;
|
|
143
|
-
for (const key of envKeys) {
|
|
144
|
-
if (!(key in settings.env)) continue;
|
|
145
|
-
const expected = envValues ? envValues[key] : undefined;
|
|
146
|
-
if (expected === undefined || settings.env[key] === expected) {
|
|
147
|
-
delete settings.env[key];
|
|
148
|
-
modified = true;
|
|
149
|
-
} else {
|
|
150
|
-
console.log(`Preserving user-modified env.${key} in settings.json`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if (Object.keys(settings.env).length === 0) delete settings.env;
|
|
154
|
-
return modified;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function pruneManagedStatusLine(settings, ledgerStatusLine) {
|
|
158
|
-
if (!settings.statusLine) return false;
|
|
159
|
-
|
|
160
|
-
if (ledgerStatusLine) {
|
|
161
|
-
if (ledgerStatusLine.wasSet !== true) return false;
|
|
162
|
-
const managed = ledgerStatusLine.content;
|
|
163
|
-
if (JSON.stringify(settings.statusLine) !== JSON.stringify(managed)) {
|
|
164
|
-
console.log('Preserving user-modified statusLine in settings.json');
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
delete settings.statusLine;
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (!looksLikeHistoricalPluginStatusLine(settings.statusLine)) {
|
|
172
|
-
console.log('Preserving non-plugin statusLine in settings.json (no ledger, signature mismatch)');
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
delete settings.statusLine;
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
127
|
function cleanSettings(baseDir, scopeLabel, ledger) {
|
|
180
128
|
const settingsPath = join(baseDir, 'settings.json');
|
|
181
129
|
if (!existsSync(settingsPath)) return;
|
|
182
130
|
|
|
183
|
-
let settings;
|
|
184
131
|
try {
|
|
185
|
-
|
|
132
|
+
JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
186
133
|
} catch {
|
|
187
134
|
return;
|
|
188
135
|
}
|
|
189
136
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
137
|
+
// Env keys are intentionally NOT removed on uninstall. CLAUDE_CODE_ENABLE_TASKS
|
|
138
|
+
// and CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS are Claude-Code-level feature flags
|
|
139
|
+
// shared with other Daemux plugins (e.g. default-development). Uninstalling
|
|
140
|
+
// one plugin must not silently break another.
|
|
141
|
+
const ledgerEnvKeys = ledger?.envKeys ?? [];
|
|
142
|
+
if (ledgerEnvKeys.length > 0) {
|
|
143
|
+
console.log(
|
|
144
|
+
`Note: env keys left in settings.json (may be shared with other plugins): ${ledgerEnvKeys.join(', ')}`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
194
147
|
|
|
195
|
-
|
|
148
|
+
// statusLine is intentionally NOT removed on uninstall. Multiple Daemux plugins
|
|
149
|
+
// may inject the same statusLine; deleting it here would remove content that
|
|
150
|
+
// another plugin still relies on (same class of bug as the shared env-key fix).
|
|
151
|
+
if (ledger?.statusLine?.wasSet) {
|
|
152
|
+
console.log(
|
|
153
|
+
'Note: statusLine left in settings.json (may be shared with other plugins).'
|
|
154
|
+
);
|
|
155
|
+
}
|
|
196
156
|
|
|
197
|
-
const newRaw = JSON.stringify(settings, null, 2) + '\n';
|
|
198
|
-
backupIfChanging(settingsPath, newRaw);
|
|
199
|
-
writeFileSync(settingsPath, newRaw, 'utf8');
|
|
200
157
|
console.log(`Cleaned ${scopeLabel} settings`);
|
|
201
158
|
}
|
|
202
159
|
|