wfu-migrate 0.1.28 → 0.1.30
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/commands/correct-user-sync.d.ts +20 -0
- package/dist/commands/correct-user-sync.d.ts.map +1 -0
- package/dist/commands/correct-user-sync.js +367 -0
- package/dist/commands/correct-user-sync.js.map +1 -0
- package/dist/commands/user-sync.d.ts +17 -0
- package/dist/commands/user-sync.d.ts.map +1 -0
- package/dist/commands/user-sync.js +226 -0
- package/dist/commands/user-sync.js.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/mysql-query.d.ts +15 -0
- package/dist/lib/mysql-query.d.ts.map +1 -0
- package/dist/lib/mysql-query.js +68 -0
- package/dist/lib/mysql-query.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Correct User Sync command - Detect and fix cascading user ID mismatches
|
|
3
|
+
*
|
|
4
|
+
* When a user is created on PROD but fails to sync to another environment,
|
|
5
|
+
* every subsequent user ends up with the wrong auto-increment ID (off by 1
|
|
6
|
+
* or off by N if multiple users are missing). This command detects the full
|
|
7
|
+
* cascade and fixes everything in one batch operation.
|
|
8
|
+
*
|
|
9
|
+
* Algorithm:
|
|
10
|
+
* 1. Fetch recent users from both environments, keyed by email
|
|
11
|
+
* 2. Compare to find missing, mismatched, and extra users
|
|
12
|
+
* 3. Batch delete all affected users from target
|
|
13
|
+
* 4. Batch insert correct data from source using HEX/UNHEX
|
|
14
|
+
* 5. Fix AUTO_INCREMENT and verify
|
|
15
|
+
*
|
|
16
|
+
* Usage: wfu-migrate correct-user-sync --from <env> --to <env> [--dry-run] [--yes] [--lookback N]
|
|
17
|
+
*/
|
|
18
|
+
import { Command } from 'commander';
|
|
19
|
+
export declare const correctUserSyncCommand: Command;
|
|
20
|
+
//# sourceMappingURL=correct-user-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correct-user-sync.d.ts","sourceRoot":"","sources":["../../src/commands/correct-user-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmZpC,eAAO,MAAM,sBAAsB,SAS/B,CAAC"}
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Correct User Sync command - Detect and fix cascading user ID mismatches
|
|
3
|
+
*
|
|
4
|
+
* When a user is created on PROD but fails to sync to another environment,
|
|
5
|
+
* every subsequent user ends up with the wrong auto-increment ID (off by 1
|
|
6
|
+
* or off by N if multiple users are missing). This command detects the full
|
|
7
|
+
* cascade and fixes everything in one batch operation.
|
|
8
|
+
*
|
|
9
|
+
* Algorithm:
|
|
10
|
+
* 1. Fetch recent users from both environments, keyed by email
|
|
11
|
+
* 2. Compare to find missing, mismatched, and extra users
|
|
12
|
+
* 3. Batch delete all affected users from target
|
|
13
|
+
* 4. Batch insert correct data from source using HEX/UNHEX
|
|
14
|
+
* 5. Fix AUTO_INCREMENT and verify
|
|
15
|
+
*
|
|
16
|
+
* Usage: wfu-migrate correct-user-sync --from <env> --to <env> [--dry-run] [--yes] [--lookback N]
|
|
17
|
+
*/
|
|
18
|
+
import { Command } from 'commander';
|
|
19
|
+
import { createInterface } from 'readline';
|
|
20
|
+
import chalk from 'chalk';
|
|
21
|
+
import { readConfig } from '../lib/config-manager.js';
|
|
22
|
+
import { testDbConnection, checkMySqlAvailable } from '../lib/database.js';
|
|
23
|
+
import { runMysqlQuery, runMysqlStdin } from '../lib/mysql-query.js';
|
|
24
|
+
import { withBell } from '../lib/prompt.js';
|
|
25
|
+
const VALID_ENVS = ['dev', 'uat', 'pprd', 'prod'];
|
|
26
|
+
async function fetchRecentUsers(config, lookback, useDocker) {
|
|
27
|
+
const query = `SELECT ID, user_email, user_login FROM wp_users WHERE ID >= (SELECT MAX(ID) - ${lookback} FROM wp_users) ORDER BY ID ASC`;
|
|
28
|
+
const result = await runMysqlQuery(config, query, useDocker);
|
|
29
|
+
if (!result.success) {
|
|
30
|
+
throw new Error(`Failed to fetch users: ${result.stderr}`);
|
|
31
|
+
}
|
|
32
|
+
const lines = result.stdout.trim().split('\n').filter(Boolean);
|
|
33
|
+
return lines.map((line) => {
|
|
34
|
+
const parts = line.split('\t');
|
|
35
|
+
return { id: parseInt(parts[0], 10), email: parts[1], login: parts[2] };
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function buildSyncPlan(sourceUsers, targetUsers) {
|
|
39
|
+
const sourceByEmail = new Map();
|
|
40
|
+
for (const u of sourceUsers) {
|
|
41
|
+
sourceByEmail.set(u.email, u);
|
|
42
|
+
}
|
|
43
|
+
const targetByEmail = new Map();
|
|
44
|
+
for (const u of targetUsers) {
|
|
45
|
+
targetByEmail.set(u.email, u);
|
|
46
|
+
}
|
|
47
|
+
const missing = [];
|
|
48
|
+
const mismatched = [];
|
|
49
|
+
const extraOnTarget = [];
|
|
50
|
+
for (const [email, sourceUser] of sourceByEmail) {
|
|
51
|
+
const targetUser = targetByEmail.get(email);
|
|
52
|
+
if (!targetUser) {
|
|
53
|
+
missing.push(sourceUser);
|
|
54
|
+
}
|
|
55
|
+
else if (targetUser.id !== sourceUser.id) {
|
|
56
|
+
mismatched.push({ source: sourceUser, target: targetUser });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
for (const [email, targetUser] of targetByEmail) {
|
|
60
|
+
if (!sourceByEmail.has(email)) {
|
|
61
|
+
extraOnTarget.push(targetUser);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const idsToDeleteFromTarget = mismatched.map((m) => m.target.id);
|
|
65
|
+
const idsToInsertFromSource = [
|
|
66
|
+
...missing.map((m) => m.id),
|
|
67
|
+
...mismatched.map((m) => m.source.id),
|
|
68
|
+
];
|
|
69
|
+
const sourceIdsNeeded = new Set(idsToInsertFromSource);
|
|
70
|
+
const targetByIdMap = new Map();
|
|
71
|
+
for (const u of targetUsers) {
|
|
72
|
+
targetByIdMap.set(u.id, u);
|
|
73
|
+
}
|
|
74
|
+
for (const sourceId of sourceIdsNeeded) {
|
|
75
|
+
const occupant = targetByIdMap.get(sourceId);
|
|
76
|
+
if (!occupant)
|
|
77
|
+
continue;
|
|
78
|
+
const isAlreadyInDeleteSet = idsToDeleteFromTarget.includes(occupant.id);
|
|
79
|
+
if (isAlreadyInDeleteSet)
|
|
80
|
+
continue;
|
|
81
|
+
const sourceRecord = sourceByEmail.get(occupant.email);
|
|
82
|
+
if (sourceRecord && sourceRecord.id === occupant.id) {
|
|
83
|
+
throw new Error(`Conflict: source ID ${sourceId} is occupied on target by a correctly-mapped user (${occupant.email}). ` +
|
|
84
|
+
`This scenario should not happen with auto-increment cascades. Manual investigation required.`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return { missing, mismatched, extraOnTarget, idsToDeleteFromTarget, idsToInsertFromSource };
|
|
88
|
+
}
|
|
89
|
+
function displaySyncPlan(plan, fromEnv, toEnv) {
|
|
90
|
+
if (plan.missing.length > 0) {
|
|
91
|
+
console.log(chalk.bold(`\nMissing on ${toEnv} (${plan.missing.length}):`));
|
|
92
|
+
for (const u of plan.missing) {
|
|
93
|
+
console.log(` ${chalk.yellow('MISSING')} ID ${u.id} ${u.email}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (plan.mismatched.length > 0) {
|
|
97
|
+
console.log(chalk.bold(`\nMismatched IDs (${plan.mismatched.length}):`));
|
|
98
|
+
for (const m of plan.mismatched) {
|
|
99
|
+
console.log(` ${chalk.red('WRONG ID')} ${m.source.email} ` +
|
|
100
|
+
`${fromEnv}=${m.source.id} ${toEnv}=${m.target.id}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (plan.extraOnTarget.length > 0) {
|
|
104
|
+
console.log(chalk.bold(`\nExtra on ${toEnv} only (${plan.extraOnTarget.length}):`));
|
|
105
|
+
for (const u of plan.extraOnTarget) {
|
|
106
|
+
console.log(` ${chalk.gray('EXTRA')} ID ${u.id} ${u.email} ${chalk.gray('(no action)')}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const totalFixes = plan.missing.length + plan.mismatched.length;
|
|
110
|
+
console.log(chalk.bold(`\nActions:`));
|
|
111
|
+
console.log(` ${chalk.red('DELETE')} ${plan.idsToDeleteFromTarget.length} user(s) from ${toEnv} (mismatched IDs)`);
|
|
112
|
+
console.log(` ${chalk.green('INSERT')} ${plan.idsToInsertFromSource.length} user(s) from ${fromEnv} (missing + corrected)`);
|
|
113
|
+
console.log(` Total users to fix: ${chalk.bold(String(totalFixes))}\n`);
|
|
114
|
+
}
|
|
115
|
+
async function executeSyncPlan(plan, sourceConfig, targetConfig, useDocker) {
|
|
116
|
+
if (plan.idsToDeleteFromTarget.length > 0) {
|
|
117
|
+
const idList = plan.idsToDeleteFromTarget.join(',');
|
|
118
|
+
console.log(chalk.gray(`Deleting ${plan.idsToDeleteFromTarget.length} mismatched user(s) from target...`));
|
|
119
|
+
const deleteMetaResult = await runMysqlQuery(targetConfig, `DELETE FROM wp_usermeta WHERE user_id IN (${idList})`, useDocker);
|
|
120
|
+
if (!deleteMetaResult.success) {
|
|
121
|
+
throw new Error(`Failed to delete target usermeta: ${deleteMetaResult.stderr}`);
|
|
122
|
+
}
|
|
123
|
+
const deleteUserResult = await runMysqlQuery(targetConfig, `DELETE FROM wp_users WHERE ID IN (${idList})`, useDocker);
|
|
124
|
+
if (!deleteUserResult.success) {
|
|
125
|
+
throw new Error(`Failed to delete target users: ${deleteUserResult.stderr}`);
|
|
126
|
+
}
|
|
127
|
+
console.log(chalk.green(` Deleted ${plan.idsToDeleteFromTarget.length} user(s) and their usermeta\n`));
|
|
128
|
+
}
|
|
129
|
+
if (plan.idsToInsertFromSource.length === 0)
|
|
130
|
+
return;
|
|
131
|
+
const sourceIdList = plan.idsToInsertFromSource.join(',');
|
|
132
|
+
console.log(chalk.gray(`Reading ${plan.idsToInsertFromSource.length} user row(s) from source (HEX-encoded)...`));
|
|
133
|
+
const sourceRowsResult = await runMysqlQuery(sourceConfig, `SELECT ID, HEX(user_login), HEX(user_pass), HEX(user_nicename), HEX(user_email), HEX(user_url), HEX(user_registered), HEX(user_activation_key), user_status, HEX(display_name) FROM wp_users WHERE ID IN (${sourceIdList}) ORDER BY ID ASC`, useDocker);
|
|
134
|
+
if (!sourceRowsResult.success) {
|
|
135
|
+
throw new Error(`Failed to read source users: ${sourceRowsResult.stderr}`);
|
|
136
|
+
}
|
|
137
|
+
const userLines = sourceRowsResult.stdout.trim().split('\n').filter(Boolean);
|
|
138
|
+
if (userLines.length === 0) {
|
|
139
|
+
throw new Error('No user rows returned from source');
|
|
140
|
+
}
|
|
141
|
+
const userValues = userLines.map((line) => {
|
|
142
|
+
const cols = line.split('\t');
|
|
143
|
+
return `(${cols[0]}, UNHEX('${cols[1]}'), UNHEX('${cols[2]}'), UNHEX('${cols[3]}'), UNHEX('${cols[4]}'), UNHEX('${cols[5]}'), UNHEX('${cols[6]}'), UNHEX('${cols[7]}'), ${cols[8]}, UNHEX('${cols[9]}'))`;
|
|
144
|
+
});
|
|
145
|
+
console.log(chalk.gray(`Inserting ${userValues.length} user row(s) into target...`));
|
|
146
|
+
const insertUserSql = `INSERT INTO wp_users (ID, user_login, user_pass, user_nicename, user_email, user_url, user_registered, user_activation_key, user_status, display_name) VALUES ${userValues.join(', ')};`;
|
|
147
|
+
const insertUserResult = await runMysqlStdin(targetConfig, insertUserSql, useDocker);
|
|
148
|
+
if (!insertUserResult.success) {
|
|
149
|
+
throw new Error(`Failed to insert users: ${insertUserResult.stderr}`);
|
|
150
|
+
}
|
|
151
|
+
console.log(chalk.green(` Inserted ${userValues.length} user row(s)\n`));
|
|
152
|
+
console.log(chalk.gray(`Reading usermeta for ${plan.idsToInsertFromSource.length} user(s) from source...`));
|
|
153
|
+
const sourceMetaResult = await runMysqlQuery(sourceConfig, `SELECT user_id, HEX(meta_key), HEX(meta_value) FROM wp_usermeta WHERE user_id IN (${sourceIdList})`, useDocker);
|
|
154
|
+
if (!sourceMetaResult.success) {
|
|
155
|
+
throw new Error(`Failed to read source usermeta: ${sourceMetaResult.stderr}`);
|
|
156
|
+
}
|
|
157
|
+
const metaLines = sourceMetaResult.stdout.trim().split('\n').filter(Boolean);
|
|
158
|
+
if (metaLines.length > 0) {
|
|
159
|
+
console.log(chalk.gray(`Inserting ${metaLines.length} usermeta row(s) into target...`));
|
|
160
|
+
const BATCH_SIZE = 100;
|
|
161
|
+
for (let i = 0; i < metaLines.length; i += BATCH_SIZE) {
|
|
162
|
+
const batch = metaLines.slice(i, i + BATCH_SIZE);
|
|
163
|
+
const valuesClauses = batch.map((line) => {
|
|
164
|
+
const parts = line.split('\t');
|
|
165
|
+
const metaUserId = parts[0];
|
|
166
|
+
const hexKey = parts[1];
|
|
167
|
+
const hexValue = parts[2];
|
|
168
|
+
if (!hexValue || hexValue === 'NULL') {
|
|
169
|
+
return `(${metaUserId}, UNHEX('${hexKey}'), NULL)`;
|
|
170
|
+
}
|
|
171
|
+
return `(${metaUserId}, UNHEX('${hexKey}'), UNHEX('${hexValue}'))`;
|
|
172
|
+
});
|
|
173
|
+
const insertMetaSql = `INSERT INTO wp_usermeta (user_id, meta_key, meta_value) VALUES ${valuesClauses.join(', ')};`;
|
|
174
|
+
const insertMetaResult = await runMysqlStdin(targetConfig, insertMetaSql, useDocker);
|
|
175
|
+
if (!insertMetaResult.success) {
|
|
176
|
+
throw new Error(`Failed to insert usermeta batch: ${insertMetaResult.stderr}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
console.log(chalk.green(` Inserted ${metaLines.length} usermeta row(s)\n`));
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
console.log(chalk.yellow(' No usermeta rows to insert\n'));
|
|
183
|
+
}
|
|
184
|
+
console.log(chalk.gray('Fixing AUTO_INCREMENT on target wp_users...'));
|
|
185
|
+
const maxIdResult = await runMysqlQuery(targetConfig, `SELECT COALESCE(MAX(ID), 0) + 1 FROM wp_users`, useDocker);
|
|
186
|
+
if (maxIdResult.success) {
|
|
187
|
+
const nextId = maxIdResult.stdout.trim();
|
|
188
|
+
await runMysqlQuery(targetConfig, `ALTER TABLE wp_users AUTO_INCREMENT = ${nextId}`, useDocker);
|
|
189
|
+
console.log(chalk.green(` Set to ${nextId}\n`));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async function verifySyncResults(plan, targetConfig, useDocker) {
|
|
193
|
+
const allEmails = [
|
|
194
|
+
...plan.missing.map((u) => u.email),
|
|
195
|
+
...plan.mismatched.map((m) => m.source.email),
|
|
196
|
+
];
|
|
197
|
+
const expectedIds = new Map();
|
|
198
|
+
for (const u of plan.missing) {
|
|
199
|
+
expectedIds.set(u.email, u.id);
|
|
200
|
+
}
|
|
201
|
+
for (const m of plan.mismatched) {
|
|
202
|
+
expectedIds.set(m.source.email, m.source.id);
|
|
203
|
+
}
|
|
204
|
+
if (allEmails.length === 0)
|
|
205
|
+
return true;
|
|
206
|
+
const escapedEmails = allEmails.map((e) => `'${e.replace(/'/g, "\\'")}'`).join(',');
|
|
207
|
+
const verifyResult = await runMysqlQuery(targetConfig, `SELECT ID, user_email FROM wp_users WHERE user_email IN (${escapedEmails})`, useDocker);
|
|
208
|
+
if (!verifyResult.success) {
|
|
209
|
+
console.error(chalk.red(`Verification query failed: ${verifyResult.stderr}`));
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
const verifyLines = verifyResult.stdout.trim().split('\n').filter(Boolean);
|
|
213
|
+
const verifiedMap = new Map();
|
|
214
|
+
for (const line of verifyLines) {
|
|
215
|
+
const parts = line.split('\t');
|
|
216
|
+
verifiedMap.set(parts[1], parseInt(parts[0], 10));
|
|
217
|
+
}
|
|
218
|
+
let allGood = true;
|
|
219
|
+
for (const [email, expectedId] of expectedIds) {
|
|
220
|
+
const actualId = verifiedMap.get(email);
|
|
221
|
+
if (actualId === expectedId) {
|
|
222
|
+
console.log(` ${email}: ID ${actualId} ${chalk.green('OK')}`);
|
|
223
|
+
}
|
|
224
|
+
else if (actualId === undefined) {
|
|
225
|
+
console.log(` ${email}: ${chalk.red('NOT FOUND')}`);
|
|
226
|
+
allGood = false;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
console.log(` ${email}: ID ${actualId} ${chalk.red(`expected ${expectedId}`)}`);
|
|
230
|
+
allGood = false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return allGood;
|
|
234
|
+
}
|
|
235
|
+
async function askConfirmation(message) {
|
|
236
|
+
return new Promise((resolve) => {
|
|
237
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
238
|
+
rl.question(withBell(message), (answer) => {
|
|
239
|
+
rl.close();
|
|
240
|
+
const normalized = answer.trim().toLowerCase();
|
|
241
|
+
resolve(normalized === 'y' || normalized === 'yes');
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
async function runCorrectUserSync(options) {
|
|
246
|
+
const fromEnv = options.from;
|
|
247
|
+
const toEnv = options.to;
|
|
248
|
+
const lookback = parseInt(options.lookback, 10);
|
|
249
|
+
if (!VALID_ENVS.includes(fromEnv)) {
|
|
250
|
+
console.error(chalk.red(`Error: Invalid source environment: ${fromEnv}`));
|
|
251
|
+
console.error(chalk.gray(`Valid environments: ${VALID_ENVS.join(', ')}`));
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
if (!VALID_ENVS.includes(toEnv)) {
|
|
255
|
+
console.error(chalk.red(`Error: Invalid target environment: ${toEnv}`));
|
|
256
|
+
console.error(chalk.gray(`Valid environments: ${VALID_ENVS.join(', ')}`));
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
if (fromEnv === toEnv) {
|
|
260
|
+
console.error(chalk.red('Error: Source and target environments must be different'));
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
if (isNaN(lookback) || lookback <= 0) {
|
|
264
|
+
console.error(chalk.red('Error: --lookback must be a positive integer'));
|
|
265
|
+
process.exit(1);
|
|
266
|
+
}
|
|
267
|
+
const config = readConfig();
|
|
268
|
+
if (!config) {
|
|
269
|
+
console.error(chalk.red('Error: Configuration not found'));
|
|
270
|
+
console.error(chalk.gray('Run "wfu-migrate config wizard" to set up configuration'));
|
|
271
|
+
process.exit(1);
|
|
272
|
+
}
|
|
273
|
+
const sourceConfig = config.environments[fromEnv];
|
|
274
|
+
const targetConfig = config.environments[toEnv];
|
|
275
|
+
if (!sourceConfig.host) {
|
|
276
|
+
console.error(chalk.red(`Error: Environment ${fromEnv} is not configured`));
|
|
277
|
+
process.exit(1);
|
|
278
|
+
}
|
|
279
|
+
if (!targetConfig.host) {
|
|
280
|
+
console.error(chalk.red(`Error: Environment ${toEnv} is not configured`));
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
console.log(chalk.bold(`\nCorrect User Sync: ${fromEnv} -> ${toEnv} (lookback ${lookback})\n`));
|
|
284
|
+
console.log(chalk.gray('Testing database connections...'));
|
|
285
|
+
const [sourceConn, targetConn] = await Promise.all([
|
|
286
|
+
testDbConnection(sourceConfig, fromEnv),
|
|
287
|
+
testDbConnection(targetConfig, toEnv),
|
|
288
|
+
]);
|
|
289
|
+
if (!sourceConn.success) {
|
|
290
|
+
console.error(chalk.red(`Error: ${sourceConn.error}`));
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
if (!targetConn.success) {
|
|
294
|
+
console.error(chalk.red(`Error: ${targetConn.error}`));
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
console.log(chalk.green(' Both connections OK\n'));
|
|
298
|
+
const useDocker = !checkMySqlAvailable().available;
|
|
299
|
+
console.log(chalk.gray(`Fetching last ${lookback} users from both environments...`));
|
|
300
|
+
let sourceUsers;
|
|
301
|
+
let targetUsers;
|
|
302
|
+
try {
|
|
303
|
+
[sourceUsers, targetUsers] = await Promise.all([
|
|
304
|
+
fetchRecentUsers(sourceConfig, lookback, useDocker),
|
|
305
|
+
fetchRecentUsers(targetConfig, lookback, useDocker),
|
|
306
|
+
]);
|
|
307
|
+
}
|
|
308
|
+
catch (err) {
|
|
309
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
console.log(chalk.green(` ${fromEnv}: ${sourceUsers.length} users, ${toEnv}: ${targetUsers.length} users\n`));
|
|
313
|
+
let plan;
|
|
314
|
+
try {
|
|
315
|
+
plan = buildSyncPlan(sourceUsers, targetUsers);
|
|
316
|
+
}
|
|
317
|
+
catch (err) {
|
|
318
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
319
|
+
process.exit(1);
|
|
320
|
+
}
|
|
321
|
+
const totalFixes = plan.missing.length + plan.mismatched.length;
|
|
322
|
+
if (totalFixes === 0) {
|
|
323
|
+
console.log(chalk.green('Environments are in sync — no fixes needed'));
|
|
324
|
+
if (plan.extraOnTarget.length > 0) {
|
|
325
|
+
console.log(chalk.gray(` (${plan.extraOnTarget.length} user(s) exist only on ${toEnv}, no action taken)`));
|
|
326
|
+
}
|
|
327
|
+
process.exit(0);
|
|
328
|
+
}
|
|
329
|
+
displaySyncPlan(plan, fromEnv, toEnv);
|
|
330
|
+
if (options.dryRun) {
|
|
331
|
+
console.log(chalk.yellow('Dry run — no changes made'));
|
|
332
|
+
process.exit(0);
|
|
333
|
+
}
|
|
334
|
+
if (!options.yes) {
|
|
335
|
+
const confirmed = await askConfirmation(`Proceed with fixing ${totalFixes} user(s) on ${toEnv}? (y/n): `);
|
|
336
|
+
if (!confirmed) {
|
|
337
|
+
console.log(chalk.yellow('\nAborted by user'));
|
|
338
|
+
process.exit(0);
|
|
339
|
+
}
|
|
340
|
+
console.log();
|
|
341
|
+
}
|
|
342
|
+
try {
|
|
343
|
+
await executeSyncPlan(plan, sourceConfig, targetConfig, useDocker);
|
|
344
|
+
}
|
|
345
|
+
catch (err) {
|
|
346
|
+
console.error(chalk.red(`Error during sync: ${err.message}`));
|
|
347
|
+
process.exit(1);
|
|
348
|
+
}
|
|
349
|
+
console.log(chalk.gray('Verifying...'));
|
|
350
|
+
const verified = await verifySyncResults(plan, targetConfig, useDocker);
|
|
351
|
+
if (!verified) {
|
|
352
|
+
console.error(chalk.red('\nVerification FAILED — some users may need manual attention'));
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
console.log(chalk.green(`\nAll ${totalFixes} user(s) synced from ${fromEnv} to ${toEnv}`));
|
|
356
|
+
}
|
|
357
|
+
export const correctUserSyncCommand = new Command('correct-user-sync')
|
|
358
|
+
.description('Detect and fix cascading user ID mismatches between environments')
|
|
359
|
+
.requiredOption('--from <env>', 'Source environment (dev, uat, pprd, prod)')
|
|
360
|
+
.requiredOption('--to <env>', 'Target environment (dev, uat, pprd, prod)')
|
|
361
|
+
.option('--dry-run', 'Show what would be done without making changes', false)
|
|
362
|
+
.option('--yes', 'Skip confirmation prompt', false)
|
|
363
|
+
.option('--lookback <n>', 'Number of recent users to compare', '500')
|
|
364
|
+
.action(async (options) => {
|
|
365
|
+
await runCorrectUserSync(options);
|
|
366
|
+
});
|
|
367
|
+
//# sourceMappingURL=correct-user-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correct-user-sync.js","sourceRoot":"","sources":["../../src/commands/correct-user-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Sync command - Fix user ID mismatches between environments
|
|
3
|
+
*
|
|
4
|
+
* When users are auto-synced from PROD to PPRD, they can end up with
|
|
5
|
+
* different auto-increment IDs. This command copies the user row and
|
|
6
|
+
* all usermeta from a source environment to a target, ensuring the
|
|
7
|
+
* user ID matches.
|
|
8
|
+
*
|
|
9
|
+
* Uses MySQL HEX()/UNHEX() for all string data transfer to safely
|
|
10
|
+
* handle serialized PHP, HTML, special characters, and passwords
|
|
11
|
+
* without any escaping issues.
|
|
12
|
+
*
|
|
13
|
+
* Usage: wfu-migrate user-sync --from <env> --to <env> --user-id <id> [--dry-run]
|
|
14
|
+
*/
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
export declare const userSyncCommand: Command;
|
|
17
|
+
//# sourceMappingURL=user-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-sync.d.ts","sourceRoot":"","sources":["../../src/commands/user-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmPpC,eAAO,MAAM,eAAe,SAQxB,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Sync command - Fix user ID mismatches between environments
|
|
3
|
+
*
|
|
4
|
+
* When users are auto-synced from PROD to PPRD, they can end up with
|
|
5
|
+
* different auto-increment IDs. This command copies the user row and
|
|
6
|
+
* all usermeta from a source environment to a target, ensuring the
|
|
7
|
+
* user ID matches.
|
|
8
|
+
*
|
|
9
|
+
* Uses MySQL HEX()/UNHEX() for all string data transfer to safely
|
|
10
|
+
* handle serialized PHP, HTML, special characters, and passwords
|
|
11
|
+
* without any escaping issues.
|
|
12
|
+
*
|
|
13
|
+
* Usage: wfu-migrate user-sync --from <env> --to <env> --user-id <id> [--dry-run]
|
|
14
|
+
*/
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
import chalk from 'chalk';
|
|
17
|
+
import { readConfig } from '../lib/config-manager.js';
|
|
18
|
+
import { testDbConnection, checkMySqlAvailable } from '../lib/database.js';
|
|
19
|
+
import { runMysqlQuery, runMysqlStdin } from '../lib/mysql-query.js';
|
|
20
|
+
const VALID_ENVS = ['dev', 'uat', 'pprd', 'prod'];
|
|
21
|
+
async function runUserSync(options) {
|
|
22
|
+
const fromEnv = options.from;
|
|
23
|
+
const toEnv = options.to;
|
|
24
|
+
const userId = parseInt(options.userId, 10);
|
|
25
|
+
if (!VALID_ENVS.includes(fromEnv)) {
|
|
26
|
+
console.error(chalk.red(`Error: Invalid source environment: ${fromEnv}`));
|
|
27
|
+
console.error(chalk.gray(`Valid environments: ${VALID_ENVS.join(', ')}`));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
if (!VALID_ENVS.includes(toEnv)) {
|
|
31
|
+
console.error(chalk.red(`Error: Invalid target environment: ${toEnv}`));
|
|
32
|
+
console.error(chalk.gray(`Valid environments: ${VALID_ENVS.join(', ')}`));
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
if (fromEnv === toEnv) {
|
|
36
|
+
console.error(chalk.red('Error: Source and target environments must be different'));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
if (isNaN(userId) || userId <= 0) {
|
|
40
|
+
console.error(chalk.red('Error: --user-id must be a positive integer'));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
const config = readConfig();
|
|
44
|
+
if (!config) {
|
|
45
|
+
console.error(chalk.red('Error: Configuration not found'));
|
|
46
|
+
console.error(chalk.gray('Run "wfu-migrate config wizard" to set up configuration'));
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const sourceConfig = config.environments[fromEnv];
|
|
50
|
+
const targetConfig = config.environments[toEnv];
|
|
51
|
+
if (!sourceConfig.host) {
|
|
52
|
+
console.error(chalk.red(`Error: Environment ${fromEnv} is not configured`));
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
if (!targetConfig.host) {
|
|
56
|
+
console.error(chalk.red(`Error: Environment ${toEnv} is not configured`));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
console.log(chalk.bold(`\nUser Sync: ${fromEnv} → ${toEnv} (user ID ${userId})\n`));
|
|
60
|
+
console.log(chalk.gray('Testing database connections...'));
|
|
61
|
+
const [sourceConn, targetConn] = await Promise.all([
|
|
62
|
+
testDbConnection(sourceConfig, fromEnv),
|
|
63
|
+
testDbConnection(targetConfig, toEnv),
|
|
64
|
+
]);
|
|
65
|
+
if (!sourceConn.success) {
|
|
66
|
+
console.error(chalk.red(`Error: ${sourceConn.error}`));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
if (!targetConn.success) {
|
|
70
|
+
console.error(chalk.red(`Error: ${targetConn.error}`));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
console.log(chalk.green(' Both connections OK\n'));
|
|
74
|
+
const useDocker = !checkMySqlAvailable().available;
|
|
75
|
+
console.log(chalk.gray(`Looking up user ID ${userId} on ${fromEnv}...`));
|
|
76
|
+
const sourceUserResult = await runMysqlQuery(sourceConfig, `SELECT ID, user_email FROM wp_users WHERE ID = ${userId}`, useDocker);
|
|
77
|
+
if (!sourceUserResult.success) {
|
|
78
|
+
console.error(chalk.red(`Error querying source: ${sourceUserResult.stderr}`));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const sourceUserLine = sourceUserResult.stdout.trim();
|
|
82
|
+
if (!sourceUserLine) {
|
|
83
|
+
console.error(chalk.red(`Error: User ID ${userId} not found on ${fromEnv}`));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
const sourceUserParts = sourceUserLine.split('\t');
|
|
87
|
+
const userEmail = sourceUserParts[1];
|
|
88
|
+
console.log(chalk.green(` Found: ${userEmail}\n`));
|
|
89
|
+
console.log(chalk.gray(`Looking up "${userEmail}" on ${toEnv}...`));
|
|
90
|
+
const targetUserResult = await runMysqlQuery(targetConfig, `SELECT ID, user_email FROM wp_users WHERE user_email = '${userEmail.replace(/'/g, "\\'")}'`, useDocker);
|
|
91
|
+
if (!targetUserResult.success) {
|
|
92
|
+
console.error(chalk.red(`Error querying target: ${targetUserResult.stderr}`));
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
const targetUserLine = targetUserResult.stdout.trim();
|
|
96
|
+
if (!targetUserLine) {
|
|
97
|
+
console.log(chalk.yellow(` User not found on ${toEnv} — nothing to fix`));
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
const targetUserParts = targetUserLine.split('\t');
|
|
101
|
+
const targetUserId = parseInt(targetUserParts[0], 10);
|
|
102
|
+
if (targetUserId === userId) {
|
|
103
|
+
console.log(chalk.green(` User ID already matches (${userId}) — nothing to fix`));
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
console.log(chalk.yellow(` Found with wrong ID: ${targetUserId} (should be ${userId})\n`));
|
|
107
|
+
const [sourceMetaResult, targetMetaResult] = await Promise.all([
|
|
108
|
+
runMysqlQuery(sourceConfig, `SELECT COUNT(*) FROM wp_usermeta WHERE user_id = ${userId}`, useDocker),
|
|
109
|
+
runMysqlQuery(targetConfig, `SELECT COUNT(*) FROM wp_usermeta WHERE user_id = ${targetUserId}`, useDocker),
|
|
110
|
+
]);
|
|
111
|
+
const sourceMetaCount = sourceMetaResult.success ? parseInt(sourceMetaResult.stdout.trim(), 10) : 0;
|
|
112
|
+
const targetMetaCount = targetMetaResult.success ? parseInt(targetMetaResult.stdout.trim(), 10) : 0;
|
|
113
|
+
console.log(chalk.bold('Sync Plan:'));
|
|
114
|
+
console.log(` ${chalk.red('DELETE')} target wp_users row (ID ${targetUserId})`);
|
|
115
|
+
console.log(` ${chalk.red('DELETE')} target wp_usermeta rows for user_id ${targetUserId} (${targetMetaCount} rows)`);
|
|
116
|
+
console.log(` ${chalk.green('INSERT')} source wp_users row (ID ${userId})`);
|
|
117
|
+
console.log(` ${chalk.green('INSERT')} source wp_usermeta rows (${sourceMetaCount} rows)\n`);
|
|
118
|
+
if (options.dryRun) {
|
|
119
|
+
console.log(chalk.yellow('Dry run — no changes made'));
|
|
120
|
+
process.exit(0);
|
|
121
|
+
}
|
|
122
|
+
console.log(chalk.gray('Deleting wrong user from target...'));
|
|
123
|
+
const deleteUserResult = await runMysqlQuery(targetConfig, `DELETE FROM wp_users WHERE ID = ${targetUserId}`, useDocker);
|
|
124
|
+
if (!deleteUserResult.success) {
|
|
125
|
+
console.error(chalk.red(`Error deleting target user: ${deleteUserResult.stderr}`));
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
const deleteMetaResult = await runMysqlQuery(targetConfig, `DELETE FROM wp_usermeta WHERE user_id = ${targetUserId}`, useDocker);
|
|
129
|
+
if (!deleteMetaResult.success) {
|
|
130
|
+
console.error(chalk.red(`Error deleting target usermeta: ${deleteMetaResult.stderr}`));
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
console.log(chalk.green(' Deleted\n'));
|
|
134
|
+
console.log(chalk.gray('Reading source user row (HEX-encoded)...'));
|
|
135
|
+
const sourceRowResult = await runMysqlQuery(sourceConfig, `SELECT ID, HEX(user_login), HEX(user_pass), HEX(user_nicename), HEX(user_email), HEX(user_url), HEX(user_registered), HEX(user_activation_key), user_status, HEX(display_name) FROM wp_users WHERE ID = ${userId}`, useDocker);
|
|
136
|
+
if (!sourceRowResult.success || !sourceRowResult.stdout.trim()) {
|
|
137
|
+
console.error(chalk.red(`Error reading source user: ${sourceRowResult.stderr}`));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
const cols = sourceRowResult.stdout.trim().split('\t');
|
|
141
|
+
const insertUserSql = `INSERT INTO wp_users (ID, user_login, user_pass, user_nicename, user_email, user_url, user_registered, user_activation_key, user_status, display_name) VALUES (${cols[0]}, UNHEX('${cols[1]}'), UNHEX('${cols[2]}'), UNHEX('${cols[3]}'), UNHEX('${cols[4]}'), UNHEX('${cols[5]}'), UNHEX('${cols[6]}'), UNHEX('${cols[7]}'), ${cols[8]}, UNHEX('${cols[9]}'));`;
|
|
142
|
+
console.log(chalk.gray('Inserting user row into target...'));
|
|
143
|
+
const insertUserResult = await runMysqlStdin(targetConfig, insertUserSql, useDocker);
|
|
144
|
+
if (!insertUserResult.success) {
|
|
145
|
+
console.error(chalk.red(`Error inserting user: ${insertUserResult.stderr}`));
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
console.log(chalk.green(' Inserted\n'));
|
|
149
|
+
console.log(chalk.gray('Reading source usermeta (HEX-encoded)...'));
|
|
150
|
+
const sourceMetaRows = await runMysqlQuery(sourceConfig, `SELECT user_id, HEX(meta_key), HEX(meta_value) FROM wp_usermeta WHERE user_id = ${userId}`, useDocker);
|
|
151
|
+
if (!sourceMetaRows.success) {
|
|
152
|
+
console.error(chalk.red(`Error reading source usermeta: ${sourceMetaRows.stderr}`));
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
const metaLines = sourceMetaRows.stdout.trim().split('\n').filter(Boolean);
|
|
156
|
+
if (metaLines.length > 0) {
|
|
157
|
+
console.log(chalk.gray(`Inserting ${metaLines.length} usermeta rows into target...`));
|
|
158
|
+
const valuesClauses = [];
|
|
159
|
+
for (const line of metaLines) {
|
|
160
|
+
const parts = line.split('\t');
|
|
161
|
+
const metaUserId = parts[0];
|
|
162
|
+
const hexKey = parts[1];
|
|
163
|
+
const hexValue = parts[2];
|
|
164
|
+
if (!hexValue || hexValue === 'NULL') {
|
|
165
|
+
valuesClauses.push(`(${metaUserId}, UNHEX('${hexKey}'), NULL)`);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
valuesClauses.push(`(${metaUserId}, UNHEX('${hexKey}'), UNHEX('${hexValue}'))`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const BATCH_SIZE = 100;
|
|
172
|
+
for (let i = 0; i < valuesClauses.length; i += BATCH_SIZE) {
|
|
173
|
+
const batch = valuesClauses.slice(i, i + BATCH_SIZE);
|
|
174
|
+
const insertMetaSql = `INSERT INTO wp_usermeta (user_id, meta_key, meta_value) VALUES ${batch.join(', ')};`;
|
|
175
|
+
const insertMetaResult = await runMysqlStdin(targetConfig, insertMetaSql, useDocker);
|
|
176
|
+
if (!insertMetaResult.success) {
|
|
177
|
+
console.error(chalk.red(`Error inserting usermeta batch: ${insertMetaResult.stderr}`));
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
console.log(chalk.green(` Inserted ${metaLines.length} rows\n`));
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
console.log(chalk.yellow(' No usermeta rows to insert\n'));
|
|
185
|
+
}
|
|
186
|
+
console.log(chalk.gray('Fixing AUTO_INCREMENT on target wp_users...'));
|
|
187
|
+
const fixAutoIncResult = await runMysqlQuery(targetConfig, `SELECT COALESCE(MAX(ID), 0) + 1 FROM wp_users`, useDocker);
|
|
188
|
+
if (fixAutoIncResult.success) {
|
|
189
|
+
const nextId = fixAutoIncResult.stdout.trim();
|
|
190
|
+
await runMysqlQuery(targetConfig, `ALTER TABLE wp_users AUTO_INCREMENT = ${nextId}`, useDocker);
|
|
191
|
+
console.log(chalk.green(` Set to ${nextId}\n`));
|
|
192
|
+
}
|
|
193
|
+
console.log(chalk.gray('Verifying...'));
|
|
194
|
+
const [verifyUser, verifyMeta] = await Promise.all([
|
|
195
|
+
runMysqlQuery(targetConfig, `SELECT ID, user_email FROM wp_users WHERE ID = ${userId}`, useDocker),
|
|
196
|
+
runMysqlQuery(targetConfig, `SELECT COUNT(*) FROM wp_usermeta WHERE user_id = ${userId}`, useDocker),
|
|
197
|
+
]);
|
|
198
|
+
const verifyUserLine = verifyUser.success ? verifyUser.stdout.trim() : '';
|
|
199
|
+
const verifyMetaCount = verifyMeta.success ? parseInt(verifyMeta.stdout.trim(), 10) : 0;
|
|
200
|
+
if (!verifyUserLine) {
|
|
201
|
+
console.error(chalk.red('Verification FAILED: User not found on target after sync'));
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const verifyParts = verifyUserLine.split('\t');
|
|
205
|
+
const verifiedId = parseInt(verifyParts[0], 10);
|
|
206
|
+
const verifiedEmail = verifyParts[1];
|
|
207
|
+
if (verifiedId !== userId) {
|
|
208
|
+
console.error(chalk.red(`Verification FAILED: Expected ID ${userId}, got ${verifiedId}`));
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
console.log(chalk.green('\nVerification passed:'));
|
|
212
|
+
console.log(` User ID: ${chalk.bold(String(verifiedId))} ${chalk.green('✓')}`);
|
|
213
|
+
console.log(` Email: ${chalk.bold(verifiedEmail)} ${chalk.green('✓')}`);
|
|
214
|
+
console.log(` Meta: ${chalk.bold(String(verifyMetaCount))} rows (source had ${sourceMetaCount}) ${verifyMetaCount === sourceMetaCount ? chalk.green('✓') : chalk.yellow('~')}`);
|
|
215
|
+
console.log(chalk.green(`\nUser ${userId} synced from ${fromEnv} to ${toEnv}`));
|
|
216
|
+
}
|
|
217
|
+
export const userSyncCommand = new Command('user-sync')
|
|
218
|
+
.description('Fix user ID mismatch between environments by syncing wp_users and wp_usermeta')
|
|
219
|
+
.requiredOption('--from <env>', 'Source environment (dev, uat, pprd, prod)')
|
|
220
|
+
.requiredOption('--to <env>', 'Target environment (dev, uat, pprd, prod)')
|
|
221
|
+
.requiredOption('--user-id <id>', 'User ID on the source environment')
|
|
222
|
+
.option('--dry-run', 'Show what would be done without making changes', false)
|
|
223
|
+
.action(async (options) => {
|
|
224
|
+
await runUserSync(options);
|
|
225
|
+
});
|
|
226
|
+
//# sourceMappingURL=user-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-sync.js","sourceRoot":"","sources":["../../src/commands/user-sync.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,8 @@ import { configCommand } from './commands/config.js';
|
|
|
21
21
|
import { doctorCommand } from './commands/doctor.js';
|
|
22
22
|
import { cleanupCommand } from './commands/cleanup.js';
|
|
23
23
|
import { listSitesCommand } from './commands/list-sites.js';
|
|
24
|
+
import { userSyncCommand } from './commands/user-sync.js';
|
|
25
|
+
import { correctUserSyncCommand } from './commands/correct-user-sync.js';
|
|
24
26
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
25
27
|
const packageJson = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
26
28
|
const VERSION = packageJson.version;
|
|
@@ -34,5 +36,7 @@ program.addCommand(configCommand);
|
|
|
34
36
|
program.addCommand(doctorCommand);
|
|
35
37
|
program.addCommand(cleanupCommand);
|
|
36
38
|
program.addCommand(listSitesCommand);
|
|
39
|
+
program.addCommand(userSyncCommand);
|
|
40
|
+
program.addCommand(correctUserSyncCommand);
|
|
37
41
|
program.parse();
|
|
38
42
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7F,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;AAEpC,OAAO;KACJ,IAAI,CAAC,aAAa,CAAC;KACnB,WAAW,CAAC,+EAA+E,CAAC;KAC5F,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,4BAA4B,CAAC,CAAC;AAEnE,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACrC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;AAE3C,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MySQL query utilities for WFU-Migrate
|
|
3
|
+
*
|
|
4
|
+
* Shared helpers for running MySQL queries via CLI (native or Docker fallback).
|
|
5
|
+
* Uses spawn for non-blocking execution with stdout/stderr capture.
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseConfig } from '../types/index.js';
|
|
8
|
+
export interface QueryResult {
|
|
9
|
+
success: boolean;
|
|
10
|
+
stdout: string;
|
|
11
|
+
stderr: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function runMysqlQuery(config: DatabaseConfig, query: string, useDocker: boolean): Promise<QueryResult>;
|
|
14
|
+
export declare function runMysqlStdin(config: DatabaseConfig, sql: string, useDocker: boolean): Promise<QueryResult>;
|
|
15
|
+
//# sourceMappingURL=mysql-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql-query.d.ts","sourceRoot":"","sources":["../../src/lib/mysql-query.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CA4B7G;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CA8B3G"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MySQL query utilities for WFU-Migrate
|
|
3
|
+
*
|
|
4
|
+
* Shared helpers for running MySQL queries via CLI (native or Docker fallback).
|
|
5
|
+
* Uses spawn for non-blocking execution with stdout/stderr capture.
|
|
6
|
+
*/
|
|
7
|
+
import { spawn } from 'child_process';
|
|
8
|
+
export function runMysqlQuery(config, query, useDocker) {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
const baseArgs = [
|
|
11
|
+
'-h', config.host,
|
|
12
|
+
'-P', String(config.port),
|
|
13
|
+
'-u', config.user,
|
|
14
|
+
`-p${config.password}`,
|
|
15
|
+
config.database,
|
|
16
|
+
'-N',
|
|
17
|
+
'-e', query,
|
|
18
|
+
'--connect-timeout=10',
|
|
19
|
+
];
|
|
20
|
+
const args = useDocker
|
|
21
|
+
? ['run', '--rm', '--network', 'host', 'mysql:8.0', 'mysql', ...baseArgs]
|
|
22
|
+
: baseArgs;
|
|
23
|
+
const cmd = useDocker ? 'docker' : 'mysql';
|
|
24
|
+
const proc = spawn(cmd, args, { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
25
|
+
let stdout = '';
|
|
26
|
+
let stderr = '';
|
|
27
|
+
proc.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
28
|
+
proc.stderr.on('data', (data) => { stderr += data.toString(); });
|
|
29
|
+
proc.on('close', (code) => {
|
|
30
|
+
resolve({ success: code === 0, stdout, stderr });
|
|
31
|
+
});
|
|
32
|
+
proc.on('error', (err) => {
|
|
33
|
+
resolve({ success: false, stdout: '', stderr: err.message });
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export function runMysqlStdin(config, sql, useDocker) {
|
|
38
|
+
return new Promise((resolve) => {
|
|
39
|
+
const baseArgs = [
|
|
40
|
+
'-h', config.host,
|
|
41
|
+
'-P', String(config.port),
|
|
42
|
+
'-u', config.user,
|
|
43
|
+
`-p${config.password}`,
|
|
44
|
+
config.database,
|
|
45
|
+
'--connect-timeout=10',
|
|
46
|
+
];
|
|
47
|
+
const args = useDocker
|
|
48
|
+
? ['run', '--rm', '--network', 'host', '-i', 'mysql:8.0', 'mysql', ...baseArgs]
|
|
49
|
+
: baseArgs;
|
|
50
|
+
const cmd = useDocker ? 'docker' : 'mysql';
|
|
51
|
+
const proc = spawn(cmd, args, { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
52
|
+
let stdout = '';
|
|
53
|
+
let stderr = '';
|
|
54
|
+
let stdinError = '';
|
|
55
|
+
proc.stdin.on('error', (err) => { stdinError = err.message; });
|
|
56
|
+
proc.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
57
|
+
proc.stderr.on('data', (data) => { stderr += data.toString(); });
|
|
58
|
+
proc.on('close', (code) => {
|
|
59
|
+
resolve({ success: code === 0, stdout, stderr: stderr || stdinError });
|
|
60
|
+
});
|
|
61
|
+
proc.on('error', (err) => {
|
|
62
|
+
resolve({ success: false, stdout: '', stderr: err.message });
|
|
63
|
+
});
|
|
64
|
+
proc.stdin.write(sql);
|
|
65
|
+
proc.stdin.end();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=mysql-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql-query.js","sourceRoot":"","sources":["../../src/lib/mysql-query.ts"],"names":[],"mappings":"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"}
|