react-native-debug-toolkit 3.3.3 → 3.3.4

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.
@@ -1,119 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const pbxproj = require('pbxproj');
6
-
7
- const BUNDLE_PHASE_NAME = 'Bundle React Native code and images';
8
- const FORCE_BUNDLING_LINE = 'export FORCE_BUNDLING=1';
9
- const CONFIG_FILE = '.debug-toolkit-embed.json';
10
-
11
- function findXcodeproj(projectRoot) {
12
- const iosDir = path.join(projectRoot, 'ios');
13
- if (!fs.existsSync(iosDir)) {
14
- return null;
15
- }
16
- const entries = fs.readdirSync(iosDir).filter(
17
- (e) => e.endsWith('.xcodeproj') && e !== 'Pods.xcodeproj'
18
- );
19
- if (entries.length === 0) {
20
- return null;
21
- }
22
- return entries;
23
- }
24
-
25
- function findPbxproj(xcodeprojPath) {
26
- const pbxPath = path.join(xcodeprojPath, 'project.pbxproj');
27
- if (!fs.existsSync(pbxPath)) {
28
- throw new Error(`project.pbxproj not found at ${pbxPath}`);
29
- }
30
- return pbxPath;
31
- }
32
-
33
- function getBundleScriptPhase(pbxFile) {
34
- const proj = new pbxproj(pbxFile).parseSync();
35
- const sections = proj.hash.project.objects.PBXShellScriptBuildPhase;
36
- if (!sections) {
37
- return null;
38
- }
39
- for (const [key, section] of Object.entries(sections)) {
40
- if (
41
- section.name === BUNDLE_PHASE_NAME ||
42
- section.name === `"${BUNDLE_PHASE_NAME}"`
43
- ) {
44
- return { id: key, section, proj, pbxFile };
45
- }
46
- }
47
- return null;
48
- }
49
-
50
- function injectForceBundling(projectRoot, xcodeprojRelPath, entryFile, options) {
51
- const xcodeprojPath = path.join(projectRoot, xcodeprojRelPath);
52
- const pbxFile = findPbxproj(xcodeprojPath);
53
- const result = getBundleScriptPhase(pbxFile);
54
- if (!result) {
55
- throw new Error(
56
- `"${BUNDLE_PHASE_NAME}" script phase not found in ${xcodeprojRelPath}`
57
- );
58
- }
59
-
60
- const scriptBody = result.section.shellScript;
61
- // Already injected — idempotent
62
- if (scriptBody && scriptBody.includes(FORCE_BUNDLING_LINE)) {
63
- console.log(` ${xcodeprojRelPath}: FORCE_BUNDLING already set. Skipping.`);
64
- return { xcodeproj: xcodeprojRelPath, scriptPhaseId: result.id, entryFile };
65
- }
66
-
67
- // Decode shellScript (it's usually a quoted string)
68
- let decoded = scriptBody;
69
- try {
70
- decoded = JSON.parse(scriptBody);
71
- } catch (_) {
72
- // Not JSON-encoded, use as-is
73
- }
74
-
75
- const newScript = FORCE_BUNDLING_LINE + '\n' + decoded;
76
- result.section.shellScript = JSON.stringify(newScript);
77
-
78
- fs.writeFileSync(pbxFile, result.proj.writeSync());
79
- console.log(` ${xcodeprojRelPath}: Injected FORCE_BUNDLING=1`);
80
-
81
- return { xcodeproj: xcodeprojRelPath, scriptPhaseId: result.id, entryFile };
82
- }
83
-
84
- function undoForceBundling(projectRoot, config) {
85
- if (!config.ios) {
86
- console.log(' No iOS configuration found. Skipping.');
87
- return;
88
- }
89
-
90
- const xcodeprojPath = path.join(projectRoot, config.ios.xcodeproj);
91
- const pbxFile = findPbxproj(xcodeprojPath);
92
- const result = getBundleScriptPhase(pbxFile);
93
- if (!result) {
94
- console.log(' Bundle script phase not found. Skipping.');
95
- return;
96
- }
97
-
98
- const scriptBody = result.section.shellScript;
99
- let decoded = scriptBody;
100
- try {
101
- decoded = JSON.parse(scriptBody);
102
- } catch (_) {}
103
-
104
- if (!decoded.includes(FORCE_BUNDLING_LINE)) {
105
- console.log(' FORCE_BUNDLING not found in script. Skipping.');
106
- return;
107
- }
108
-
109
- const newScript = decoded
110
- .split('\n')
111
- .filter((line) => line !== FORCE_BUNDLING_LINE)
112
- .join('\n');
113
- result.section.shellScript = JSON.stringify(newScript);
114
-
115
- fs.writeFileSync(pbxFile, result.proj.writeSync());
116
- console.log(' Removed FORCE_BUNDLING=1 from script phase.');
117
- }
118
-
119
- module.exports = { findXcodeproj, injectForceBundling, undoForceBundling };
package/scripts/embed.js DELETED
@@ -1,224 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const readline = require('readline');
6
-
7
- const ios = require('./embed-ios');
8
- const android = require('./embed-android');
9
- const expo = require('./embed-expo');
10
-
11
- const CONFIG_FILE = '.debug-toolkit-embed.json';
12
-
13
- function readConfig(projectRoot) {
14
- const configPath = path.join(projectRoot, CONFIG_FILE);
15
- if (!fs.existsSync(configPath)) {
16
- return null;
17
- }
18
- return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
19
- }
20
-
21
- function writeConfig(projectRoot, config) {
22
- const configPath = path.join(projectRoot, CONFIG_FILE);
23
- const payload = { version: 1, ...config };
24
- fs.writeFileSync(configPath, JSON.stringify(payload, null, 2) + '\n');
25
- }
26
-
27
- function deleteConfig(projectRoot) {
28
- const configPath = path.join(projectRoot, CONFIG_FILE);
29
- if (fs.existsSync(configPath)) {
30
- fs.unlinkSync(configPath);
31
- }
32
- }
33
-
34
- function detectEntryFile(projectRoot) {
35
- const candidates = [
36
- 'index.js',
37
- 'index.ts',
38
- 'index.tsx',
39
- ];
40
-
41
- for (const candidate of candidates) {
42
- if (fs.existsSync(path.join(projectRoot, candidate))) {
43
- return candidate;
44
- }
45
- }
46
-
47
- // Expo virtual entry
48
- if (fs.existsSync(path.join(projectRoot, '.expo', '.virtual-metro-entry'))) {
49
- return '.expo/.virtual-metro-entry';
50
- }
51
-
52
- return 'index.js';
53
- }
54
-
55
- function prompt(question, options) {
56
- if (options && options.yes) {
57
- return Promise.resolve(true);
58
- }
59
-
60
- const rl = readline.createInterface({
61
- input: process.stdin,
62
- output: process.stdout,
63
- });
64
-
65
- return new Promise((resolve) => {
66
- rl.question(question + ' [Y/n] ', (answer) => {
67
- rl.close();
68
- resolve(answer.toLowerCase() !== 'n');
69
- });
70
- });
71
- }
72
-
73
- async function embed(projectRoot, argv) {
74
- const args = argv || [];
75
- const yes = args.includes('--yes');
76
- const platformIdx = args.indexOf('--platform');
77
- const platform =
78
- platformIdx >= 0 ? args[platformIdx + 1] : null; // 'ios' | 'android'
79
-
80
- console.log('debug-toolkit embed');
81
- console.log('---');
82
-
83
- // Check Expo
84
- const expoResult = expo.checkExpo(projectRoot, { yes });
85
- if (expoResult.expo) {
86
- console.log('Detected Expo project.');
87
- if (expoResult.skip) {
88
- console.log(` Skipping: ${expoResult.reason}`);
89
- if (platform === null || platform === 'ios') {
90
- // nothing
91
- }
92
- return;
93
- }
94
- console.log(' Native directories found — proceeding.');
95
- }
96
-
97
- const existingConfig = readConfig(projectRoot);
98
- const config = {};
99
-
100
- // Entry file
101
- const entryFile =
102
- (expoResult.entryPoint) || detectEntryFile(projectRoot);
103
- console.log(`Entry file: ${entryFile}`);
104
-
105
- // iOS
106
- if (platform === null || platform === 'ios') {
107
- const xcodeprojEntries = ios.findXcodeproj(projectRoot);
108
- if (xcodeprojEntries && xcodeprojEntries.length > 0) {
109
- let chosen = xcodeprojEntries[0];
110
- if (xcodeprojEntries.length > 1) {
111
- if (yes) {
112
- console.log(
113
- ` Multiple Xcode projects found. Using: ${chosen}`
114
- );
115
- } else {
116
- console.log(' Multiple Xcode projects found:');
117
- xcodeprojEntries.forEach((e, i) =>
118
- console.log(` ${i + 1}. ${e}`)
119
- );
120
- const idx = await prompt(
121
- ` Select project [1-${xcodeprojEntries.length}]`,
122
- { yes }
123
- );
124
- // Default to first
125
- chosen = xcodeprojEntries[0];
126
- }
127
- }
128
-
129
- const xcodeprojRelPath = path.join('ios', chosen);
130
- const shouldEmbed =
131
- yes ||
132
- (await prompt(
133
- ` Inject FORCE_BUNDLING into ${xcodeprojRelPath}?`,
134
- { yes }
135
- ));
136
-
137
- if (shouldEmbed !== false) {
138
- config.ios = ios.injectForceBundling(
139
- projectRoot,
140
- xcodeprojRelPath,
141
- entryFile,
142
- { yes }
143
- );
144
- }
145
- } else {
146
- console.log(' No Xcode project found. Skipping iOS.');
147
- }
148
- }
149
-
150
- // Android
151
- if (platform === null || platform === 'android') {
152
- const buildGradle = android.findBuildGradle(projectRoot);
153
- if (buildGradle) {
154
- const shouldEmbed =
155
- yes ||
156
- (await prompt(
157
- ` Inject debug bundle task into ${buildGradle}?`,
158
- { yes }
159
- ));
160
-
161
- if (shouldEmbed !== false) {
162
- config.android = android.injectGradleApply(
163
- projectRoot,
164
- buildGradle,
165
- entryFile,
166
- { yes }
167
- );
168
- }
169
- } else {
170
- console.log(' No Android build.gradle found. Skipping Android.');
171
- }
172
- }
173
-
174
- // Write config
175
- if (Object.keys(config).length > 0) {
176
- writeConfig(projectRoot, config);
177
- console.log(`\nConfiguration saved to ${CONFIG_FILE}`);
178
- }
179
-
180
- console.log('\nDone. Debug builds will now embed a JS bundle.');
181
- console.log('Use DevConnect to switch Metro hosts at runtime.');
182
- }
183
-
184
- async function undo(projectRoot, argv) {
185
- const args = argv || [];
186
- const yes = args.includes('--yes');
187
-
188
- console.log('debug-toolkit embed --undo');
189
- console.log('---');
190
-
191
- const config = readConfig(projectRoot);
192
- if (!config) {
193
- console.log(`No ${CONFIG_FILE} found. Nothing to undo.`);
194
- return;
195
- }
196
-
197
- const shouldUndo =
198
- yes || (await prompt('Remove all debug-toolkit embed injections?', { yes }));
199
-
200
- if (shouldUndo === false) {
201
- console.log('Cancelled.');
202
- return;
203
- }
204
-
205
- ios.undoForceBundling(projectRoot, config);
206
- android.undoGradleApply(projectRoot, config);
207
-
208
- deleteConfig(projectRoot);
209
- console.log(`\nRemoved ${CONFIG_FILE}.`);
210
- console.log('Done.');
211
- }
212
-
213
- function main(argv) {
214
- const projectRoot = process.cwd();
215
- const args = argv || [];
216
-
217
- if (args.includes('--undo')) {
218
- return undo(projectRoot, args);
219
- }
220
-
221
- return embed(projectRoot, args);
222
- }
223
-
224
- module.exports = { main, embed, undo };