@expo/fingerprint 0.4.1 → 0.5.0

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.
Files changed (53) hide show
  1. package/README.md +10 -0
  2. package/bin/cli.js +26 -5
  3. package/build/sourcer/Bare.js +13 -7
  4. package/build/sourcer/Bare.js.map +1 -1
  5. package/package.json +16 -9
  6. package/.eslintignore +0 -1
  7. package/CHANGELOG.md +0 -55
  8. package/__mocks__/@expo/spawn-async.ts +0 -30
  9. package/__mocks__/fs/promises.ts +0 -17
  10. package/__mocks__/fs.ts +0 -2
  11. package/__mocks__/resolve-from.ts +0 -24
  12. package/babel.config.js +0 -6
  13. package/e2e/__tests__/__snapshots__/managed-test.ts.snap +0 -242
  14. package/e2e/__tests__/bare-test.ts +0 -72
  15. package/e2e/__tests__/managed-test.ts +0 -165
  16. package/e2e/jest.config.js +0 -11
  17. package/jest.config.js +0 -10
  18. package/scripts/createFixture.ts +0 -81
  19. package/src/Dedup.ts +0 -97
  20. package/src/Fingerprint.ts +0 -60
  21. package/src/Fingerprint.types.ts +0 -110
  22. package/src/Options.ts +0 -81
  23. package/src/Sort.ts +0 -22
  24. package/src/__tests__/Dedup-test.ts +0 -177
  25. package/src/__tests__/Fingerprint-test.ts +0 -143
  26. package/src/__tests__/Sort-test.ts +0 -56
  27. package/src/hash/Hash.ts +0 -203
  28. package/src/hash/__tests__/Hash-test.ts +0 -238
  29. package/src/index.ts +0 -2
  30. package/src/sourcer/Bare.ts +0 -115
  31. package/src/sourcer/Expo.ts +0 -223
  32. package/src/sourcer/ExpoConfigLoader.ts +0 -84
  33. package/src/sourcer/PatchPackage.ts +0 -18
  34. package/src/sourcer/Sourcer.ts +0 -58
  35. package/src/sourcer/Utils.ts +0 -62
  36. package/src/sourcer/__tests__/Bare-test.ts +0 -88
  37. package/src/sourcer/__tests__/Expo-test.ts +0 -305
  38. package/src/sourcer/__tests__/PatchPackage-test.ts +0 -57
  39. package/src/sourcer/__tests__/Sourcer-test.ts +0 -21
  40. package/src/sourcer/__tests__/Utils-test.ts +0 -41
  41. package/src/sourcer/__tests__/__snapshots__/Bare-test.ts.snap +0 -21
  42. package/src/sourcer/__tests__/__snapshots__/Expo-test.ts.snap +0 -139
  43. package/src/sourcer/__tests__/fixtures/BareReactNative70Project.json +0 -47
  44. package/src/sourcer/__tests__/fixtures/ExpoAutolinkingAndroid.json +0 -82
  45. package/src/sourcer/__tests__/fixtures/ExpoAutolinkingIos.json +0 -114
  46. package/src/sourcer/__tests__/fixtures/ExpoManaged47Project.json +0 -6
  47. package/src/sourcer/__tests__/fixtures/PatchPackage.json +0 -4
  48. package/src/sourcer/__tests__/fixtures/RncliAutoLinking.json +0 -165
  49. package/src/utils/Path.ts +0 -26
  50. package/src/utils/Profile.ts +0 -47
  51. package/src/utils/__tests__/Path-test.ts +0 -36
  52. package/src/utils/__tests__/Profile-test.ts +0 -11
  53. package/tsconfig.json +0 -9
@@ -1,238 +0,0 @@
1
- import { createHash } from 'crypto';
2
- import { vol } from 'memfs';
3
- import pLimit from 'p-limit';
4
- import path from 'path';
5
-
6
- import { HashSource } from '../../Fingerprint.types';
7
- import { normalizeOptionsAsync } from '../../Options';
8
- import {
9
- createContentsHashResultsAsync,
10
- createDirHashResultsAsync,
11
- createFileHashResultsAsync,
12
- createFingerprintFromSourcesAsync,
13
- createFingerprintSourceAsync,
14
- createSourceId,
15
- } from '../Hash';
16
-
17
- jest.mock('fs');
18
- jest.mock('fs/promises');
19
-
20
- describe(createFingerprintFromSourcesAsync, () => {
21
- afterEach(() => {
22
- vol.reset();
23
- });
24
-
25
- it('snapshot', async () => {
26
- const filePath = 'assets/icon.png';
27
- vol.mkdirSync('/app');
28
- vol.mkdirSync('/app/assets');
29
- vol.writeFileSync(path.join('/app', filePath), '{}');
30
-
31
- const sources: HashSource[] = [
32
- { type: 'contents', id: 'foo', contents: 'HelloWorld', reasons: ['foo'] },
33
- { type: 'file', filePath, reasons: ['icon'] },
34
- ];
35
-
36
- expect(
37
- await createFingerprintFromSourcesAsync(sources, '/app', await normalizeOptionsAsync('/app'))
38
- ).toMatchInlineSnapshot(`
39
- {
40
- "hash": "ca7d58cd60289daa5cddcf99fcaa1d339bfc2c1a",
41
- "sources": [
42
- {
43
- "contents": "HelloWorld",
44
- "hash": "db8ac1c259eb89d4a131b253bacfca5f319d54f2",
45
- "id": "foo",
46
- "reasons": [
47
- "foo",
48
- ],
49
- "type": "contents",
50
- },
51
- {
52
- "filePath": "assets/icon.png",
53
- "hash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f",
54
- "reasons": [
55
- "icon",
56
- ],
57
- "type": "file",
58
- },
59
- ],
60
- }
61
- `);
62
- });
63
- });
64
-
65
- describe(createFingerprintSourceAsync, () => {
66
- it('should merge hash value to original source', async () => {
67
- const source: HashSource = {
68
- type: 'contents',
69
- id: 'foo',
70
- contents: 'HelloWorld',
71
- reasons: ['foo'],
72
- };
73
- const expectedResult = {
74
- ...source,
75
- hash: 'db8ac1c259eb89d4a131b253bacfca5f319d54f2',
76
- };
77
- expect(
78
- await createFingerprintSourceAsync(
79
- source,
80
- pLimit(1),
81
- '/app',
82
- await normalizeOptionsAsync('/app')
83
- )
84
- ).toEqual(expectedResult);
85
- });
86
- });
87
-
88
- describe(createContentsHashResultsAsync, () => {
89
- it('should return {id, hex} result', async () => {
90
- const id = 'foo';
91
- const contents = '{}';
92
- const options = await normalizeOptionsAsync('/app');
93
- const result = await createContentsHashResultsAsync(
94
- {
95
- type: 'contents',
96
- id,
97
- contents,
98
- reasons: [id],
99
- },
100
- options
101
- );
102
-
103
- const expectHex = createHash(options.hashAlgorithm).update(contents).digest('hex');
104
- expect(result.id).toEqual(id);
105
- expect(result.hex).toEqual(expectHex);
106
- });
107
- });
108
-
109
- describe(createFileHashResultsAsync, () => {
110
- afterEach(() => {
111
- vol.reset();
112
- });
113
-
114
- it('should return {id, hex} result', async () => {
115
- const filePath = 'assets/icon.png';
116
- const contents = '{}';
117
- const limiter = pLimit(1);
118
- const options = await normalizeOptionsAsync('/app');
119
- vol.mkdirSync('/app');
120
- vol.mkdirSync('/app/assets');
121
- vol.writeFileSync(path.join('/app', filePath), contents);
122
-
123
- const result = await createFileHashResultsAsync(filePath, limiter, '/app', options);
124
-
125
- const expectHex = createHash(options.hashAlgorithm).update(contents).digest('hex');
126
- expect(result?.id).toEqual(filePath);
127
- expect(result?.hex).toEqual(expectHex);
128
- });
129
-
130
- it('should ignore file if it is in options.ignorePaths', async () => {
131
- const filePath = 'app.json';
132
- const contents = '{}';
133
- const limiter = pLimit(1);
134
- const options = await normalizeOptionsAsync('/app');
135
- options.ignorePaths = ['*.json'];
136
- vol.mkdirSync('/app');
137
- vol.writeFileSync(path.join('/app', filePath), contents);
138
-
139
- const result = await createFileHashResultsAsync(filePath, limiter, '/app', options);
140
- expect(result).toBe(null);
141
- });
142
- });
143
-
144
- describe(createDirHashResultsAsync, () => {
145
- afterEach(() => {
146
- vol.reset();
147
- });
148
-
149
- it('should return {id, hex} result', async () => {
150
- const limiter = pLimit(3);
151
- const options = await normalizeOptionsAsync('/app');
152
- const volJSON = {
153
- '/app/ios/Podfile': '...',
154
- '/app/eas.json': '{}',
155
- '/app/app.json': '{}',
156
- '/app/android/build.gradle': '...',
157
- };
158
- vol.fromJSON(volJSON);
159
- const result = await createDirHashResultsAsync('.', limiter, '/app', options);
160
-
161
- expect(result?.id).toEqual('.');
162
- expect(result?.hex).not.toBe('');
163
- });
164
-
165
- it('should ignore dir if it is in options.ignorePaths', async () => {
166
- const limiter = pLimit(3);
167
- const options = await normalizeOptionsAsync('/app');
168
- options.ignorePaths = ['ios/**/*', 'android/**/*'];
169
- const volJSON = {
170
- '/app/ios/Podfile': '...',
171
- '/app/eas.json': '{}',
172
- '/app/app.json': '{}',
173
- '/app/android/build.gradle': '...',
174
- };
175
- vol.fromJSON(volJSON);
176
-
177
- const fingerprint1 = await createDirHashResultsAsync('.', limiter, '/app', options);
178
-
179
- vol.reset();
180
- const volJSONIgnoreNativeProjects = {
181
- '/app/eas.json': '{}',
182
- '/app/app.json': '{}',
183
- };
184
- vol.fromJSON(volJSONIgnoreNativeProjects);
185
- const fingerprint2 = await createDirHashResultsAsync('.', limiter, '/app', options);
186
- expect(fingerprint1).toEqual(fingerprint2);
187
- });
188
-
189
- it('should return stable result from sorted files', async () => {
190
- const limiter = pLimit(3);
191
- const options = await normalizeOptionsAsync('/app');
192
- const volJSON = {
193
- '/app/ios/Podfile': '...',
194
- '/app/eas.json': '{}',
195
- '/app/app.json': '{}',
196
- '/app/android/build.gradle': '...',
197
- };
198
- vol.fromJSON(volJSON);
199
- const result = await createDirHashResultsAsync('.', limiter, '/app', options);
200
-
201
- vol.reset();
202
- const sortedVolJSON = {
203
- '/app/app.json': '{}',
204
- '/app/eas.json': '{}',
205
- '/app/android/build.gradle': '...',
206
- '/app/ios/Podfile': '...',
207
- };
208
- vol.fromJSON(sortedVolJSON);
209
- const sortedResult = await createDirHashResultsAsync('.', limiter, '/app', options);
210
-
211
- expect(result?.id).toEqual(sortedResult?.id);
212
- expect(result?.hex).toEqual(sortedResult?.hex);
213
- });
214
- });
215
-
216
- describe(createSourceId, () => {
217
- it(`should use filePath as id for file or dir`, () => {
218
- const fileSource: HashSource = {
219
- type: 'file',
220
- filePath: '/app/app.json',
221
- reasons: ['expoConfig'],
222
- };
223
- expect(createSourceId(fileSource)).toBe('/app/app.json');
224
-
225
- const dirSource: HashSource = { type: 'dir', filePath: '/app/ios', reasons: ['bareNativeDir'] };
226
- expect(createSourceId(dirSource)).toBe('/app/ios');
227
- });
228
-
229
- it(`should use given id for contents`, () => {
230
- const source: HashSource = {
231
- type: 'contents',
232
- id: 'foo',
233
- contents: 'HelloWorld',
234
- reasons: ['foo'],
235
- };
236
- expect(createSourceId(source)).toBe('foo');
237
- });
238
- });
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './Fingerprint';
2
- export * from './Fingerprint.types';
@@ -1,115 +0,0 @@
1
- import spawnAsync from '@expo/spawn-async';
2
- import assert from 'assert';
3
- import chalk from 'chalk';
4
- import path from 'path';
5
- import resolveFrom from 'resolve-from';
6
-
7
- import { getFileBasedHashSourceAsync } from './Utils';
8
- import type { HashSource, NormalizedOptions } from '../Fingerprint.types';
9
-
10
- const debug = require('debug')('expo:fingerprint:sourcer:Bare');
11
-
12
- export async function getBareAndroidSourcesAsync(
13
- projectRoot: string,
14
- options: NormalizedOptions
15
- ): Promise<HashSource[]> {
16
- if (options.platforms.includes('android')) {
17
- const result = await getFileBasedHashSourceAsync(projectRoot, 'android', 'bareNativeDir');
18
- if (result != null) {
19
- debug(`Adding bare native dir - ${chalk.dim('android')}`);
20
- return [result];
21
- }
22
- }
23
- return [];
24
- }
25
-
26
- export async function getBareIosSourcesAsync(
27
- projectRoot: string,
28
- options: NormalizedOptions
29
- ): Promise<HashSource[]> {
30
- if (options.platforms.includes('ios')) {
31
- const result = await getFileBasedHashSourceAsync(projectRoot, 'ios', 'bareNativeDir');
32
- if (result != null) {
33
- debug(`Adding bare native dir - ${chalk.dim('ios')}`);
34
- return [result];
35
- }
36
- }
37
- return [];
38
- }
39
-
40
- export async function getPackageJsonScriptSourcesAsync(
41
- projectRoot: string,
42
- options: NormalizedOptions
43
- ) {
44
- let packageJson;
45
- try {
46
- packageJson = require(resolveFrom(path.resolve(projectRoot), './package.json'));
47
- } catch (e: unknown) {
48
- debug(`Unable to read package.json from ${path.resolve(projectRoot)}/package.json: ` + e);
49
- return [];
50
- }
51
- const results: HashSource[] = [];
52
- if (packageJson.scripts) {
53
- debug(`Adding package.json contents - ${chalk.dim('scripts')}`);
54
- const id = 'packageJson:scripts';
55
- results.push({
56
- type: 'contents',
57
- id,
58
- contents: JSON.stringify(packageJson.scripts),
59
- reasons: [id],
60
- });
61
- }
62
- return results;
63
- }
64
-
65
- export async function getGitIgnoreSourcesAsync(projectRoot: string, options: NormalizedOptions) {
66
- const result = await getFileBasedHashSourceAsync(projectRoot, '.gitignore', 'bareGitIgnore');
67
- if (result != null) {
68
- debug(`Adding file - ${chalk.dim('.gitignore')}`);
69
- return [result];
70
- }
71
- return [];
72
- }
73
-
74
- export async function getRncliAutolinkingSourcesAsync(
75
- projectRoot: string,
76
- options: NormalizedOptions
77
- ): Promise<HashSource[]> {
78
- try {
79
- const results: HashSource[] = [];
80
- const { stdout } = await spawnAsync('npx', ['react-native', 'config'], { cwd: projectRoot });
81
- const config = JSON.parse(stdout);
82
- const { root } = config;
83
- const reasons = ['bareRncliAutolinking'];
84
- const autolinkingConfig: Record<string, any> = {};
85
- for (const [depName, depData] of Object.entries<any>(config.dependencies)) {
86
- stripRncliAutolinkingAbsolutePaths(depData, root);
87
- const filePath = depData.root;
88
- debug(`Adding react-native-cli autolinking dir - ${chalk.dim(filePath)}`);
89
- results.push({ type: 'dir', filePath, reasons });
90
-
91
- autolinkingConfig[depName] = depData;
92
- }
93
-
94
- results.push({
95
- type: 'contents',
96
- id: 'rncliAutolinkingConfig',
97
- contents: JSON.stringify(autolinkingConfig),
98
- reasons,
99
- });
100
- return results;
101
- } catch {
102
- return [];
103
- }
104
- }
105
-
106
- function stripRncliAutolinkingAbsolutePaths(dependency: any, root: string): void {
107
- assert(dependency.root);
108
- const dependencyRoot = dependency.root;
109
- dependency.root = path.relative(root, dependencyRoot);
110
- for (const platformData of Object.values<any>(dependency.platforms)) {
111
- for (const [key, value] of Object.entries<any>(platformData)) {
112
- platformData[key] = value.startsWith?.(dependencyRoot) ? path.relative(root, value) : value;
113
- }
114
- }
115
- }
@@ -1,223 +0,0 @@
1
- import spawnAsync from '@expo/spawn-async';
2
- import chalk from 'chalk';
3
- import type { ExpoConfig, ProjectConfig } from 'expo/config';
4
- import fs from 'fs/promises';
5
- import os from 'os';
6
- import path from 'path';
7
- import resolveFrom from 'resolve-from';
8
-
9
- import { getExpoConfigLoaderPath } from './ExpoConfigLoader';
10
- import { getFileBasedHashSourceAsync, stringifyJsonSorted } from './Utils';
11
- import type { HashSource, NormalizedOptions } from '../Fingerprint.types';
12
-
13
- const debug = require('debug')('expo:fingerprint:sourcer:Expo');
14
-
15
- export async function getExpoConfigSourcesAsync(
16
- projectRoot: string,
17
- options: NormalizedOptions
18
- ): Promise<HashSource[]> {
19
- if (!resolveFrom.silent(path.resolve(projectRoot), 'expo/config')) {
20
- return [];
21
- }
22
-
23
- const results: HashSource[] = [];
24
- let config: ProjectConfig;
25
- let loadedModules: string[] = [];
26
- const ignoredFile = await createTempIgnoredFileAsync(options);
27
- try {
28
- const { stdout } = await spawnAsync(
29
- 'node',
30
- [getExpoConfigLoaderPath(), path.resolve(projectRoot), ignoredFile],
31
- { cwd: __dirname }
32
- );
33
- const stdoutJson = JSON.parse(stdout);
34
- config = stdoutJson.config;
35
- loadedModules = stdoutJson.loadedModules;
36
- results.push({
37
- type: 'contents',
38
- id: 'expoConfig',
39
- contents: normalizeExpoConfig(config.exp),
40
- reasons: ['expoConfig'],
41
- });
42
- } catch (e: unknown) {
43
- if (e instanceof Error) {
44
- console.warn(`Cannot get Expo config from an Expo project - ${e.message}: `, e.stack);
45
- }
46
- return [];
47
- }
48
-
49
- // external files in config
50
- const isAndroid = options.platforms.includes('android');
51
- const isIos = options.platforms.includes('ios');
52
- const externalFiles = [
53
- // icons
54
- config.exp.icon,
55
- isAndroid ? config.exp.android?.icon : undefined,
56
- isIos ? config.exp.ios?.icon : undefined,
57
- isAndroid ? config.exp.android?.adaptiveIcon?.foregroundImage : undefined,
58
- isAndroid ? config.exp.android?.adaptiveIcon?.backgroundImage : undefined,
59
- config.exp.notification?.icon,
60
-
61
- // splash images
62
- config.exp.splash?.image,
63
- isAndroid ? config.exp.android?.splash?.image : undefined,
64
- isAndroid ? config.exp.android?.splash?.mdpi : undefined,
65
- isAndroid ? config.exp.android?.splash?.hdpi : undefined,
66
- isAndroid ? config.exp.android?.splash?.xhdpi : undefined,
67
- isAndroid ? config.exp.android?.splash?.xxhdpi : undefined,
68
- isAndroid ? config.exp.android?.splash?.xxxhdpi : undefined,
69
- isIos ? config.exp.ios?.splash?.image : undefined,
70
- isIos ? config.exp.ios?.splash?.tabletImage : undefined,
71
-
72
- // google service files
73
- isAndroid ? config.exp.android?.googleServicesFile : undefined,
74
- isIos ? config.exp.ios?.googleServicesFile : undefined,
75
- ].filter(Boolean) as string[];
76
- const externalFileSources = (
77
- await Promise.all(
78
- externalFiles.map(async (file) => {
79
- const result = await getFileBasedHashSourceAsync(
80
- projectRoot,
81
- file,
82
- 'expoConfigExternalFile'
83
- );
84
- if (result != null) {
85
- debug(`Adding config external file - ${chalk.dim(file)}`);
86
- }
87
- return result;
88
- })
89
- )
90
- ).filter(Boolean) as HashSource[];
91
- results.push(...externalFileSources);
92
-
93
- // config plugins
94
- const configPluginModules: HashSource[] = loadedModules.map((modulePath) => ({
95
- type: 'file',
96
- filePath: modulePath,
97
- reasons: ['expoConfigPlugins'],
98
- }));
99
- results.push(...configPluginModules);
100
-
101
- return results;
102
- }
103
-
104
- function normalizeExpoConfig(config: ExpoConfig): string {
105
- // Deep clone by JSON.parse/stringify that assumes the config is serializable.
106
- const normalizedConfig: ExpoConfig = JSON.parse(JSON.stringify(config));
107
- delete normalizedConfig.runtimeVersion;
108
- delete normalizedConfig._internal;
109
- return stringifyJsonSorted(normalizedConfig);
110
- }
111
-
112
- /**
113
- * Create a temporary file with ignored paths from options that will be read by the ExpoConfigLoader.
114
- */
115
- async function createTempIgnoredFileAsync(options: NormalizedOptions): Promise<string> {
116
- await fs.mkdtemp(path.join(os.tmpdir(), 'expo-fingerprint-'));
117
- const ignoredFile = path.join(os.tmpdir(), '.fingerprintignore');
118
- await fs.writeFile(ignoredFile, options.ignorePaths.join('\n'));
119
- return ignoredFile;
120
- }
121
-
122
- export async function getEasBuildSourcesAsync(projectRoot: string, options: NormalizedOptions) {
123
- const files = ['eas.json', '.easignore'];
124
- const results = (
125
- await Promise.all(
126
- files.map(async (file) => {
127
- const result = await getFileBasedHashSourceAsync(projectRoot, file, 'easBuild');
128
- if (result != null) {
129
- debug(`Adding eas file - ${chalk.dim(file)}`);
130
- }
131
- return result;
132
- })
133
- )
134
- ).filter(Boolean) as HashSource[];
135
- return results;
136
- }
137
-
138
- export async function getExpoAutolinkingAndroidSourcesAsync(
139
- projectRoot: string,
140
- options: NormalizedOptions
141
- ): Promise<HashSource[]> {
142
- if (!options.platforms.includes('android')) {
143
- return [];
144
- }
145
-
146
- try {
147
- const reasons = ['expoAutolinkingAndroid'];
148
- const results: HashSource[] = [];
149
- const { stdout } = await spawnAsync(
150
- 'npx',
151
- ['expo-modules-autolinking', 'resolve', '-p', 'android', '--json'],
152
- { cwd: projectRoot }
153
- );
154
- const config = sortExpoAutolinkingAndroidConfig(JSON.parse(stdout));
155
- for (const module of config.modules) {
156
- for (const project of module.projects) {
157
- const filePath = path.relative(projectRoot, project.sourceDir);
158
- project.sourceDir = filePath; // use relative path for the dir
159
- debug(`Adding expo-modules-autolinking android dir - ${chalk.dim(filePath)}`);
160
- results.push({ type: 'dir', filePath, reasons });
161
- }
162
- }
163
- results.push({
164
- type: 'contents',
165
- id: 'expoAutolinkingConfig:android',
166
- contents: JSON.stringify(config),
167
- reasons,
168
- });
169
- return results;
170
- } catch {
171
- return [];
172
- }
173
- }
174
-
175
- export async function getExpoAutolinkingIosSourcesAsync(
176
- projectRoot: string,
177
- options: NormalizedOptions
178
- ): Promise<HashSource[]> {
179
- if (!options.platforms.includes('ios')) {
180
- return [];
181
- }
182
-
183
- try {
184
- const reasons = ['expoAutolinkingIos'];
185
- const results: HashSource[] = [];
186
- const { stdout } = await spawnAsync(
187
- 'npx',
188
- ['expo-modules-autolinking', 'resolve', '-p', 'ios', '--json'],
189
- { cwd: projectRoot }
190
- );
191
- const config = JSON.parse(stdout);
192
- for (const module of config.modules) {
193
- for (const pod of module.pods) {
194
- const filePath = path.relative(projectRoot, pod.podspecDir);
195
- pod.podspecDir = filePath; // use relative path for the dir
196
- debug(`Adding expo-modules-autolinking ios dir - ${chalk.dim(filePath)}`);
197
- results.push({ type: 'dir', filePath, reasons });
198
- }
199
- }
200
- results.push({
201
- type: 'contents',
202
- id: 'expoAutolinkingConfig:ios',
203
- contents: JSON.stringify(config),
204
- reasons,
205
- });
206
- return results;
207
- } catch {
208
- return [];
209
- }
210
- }
211
-
212
- /**
213
- * Sort the expo-modules-autolinking android config to make it stable from hashing.
214
- */
215
- export function sortExpoAutolinkingAndroidConfig(config: Record<string, any>): Record<string, any> {
216
- for (const module of config.modules) {
217
- // Sort the projects by project.name
218
- module.projects.sort((a: Record<string, any>, b: Record<string, any>) =>
219
- a.name < b.name ? -1 : a.name > b.name ? 1 : 0
220
- );
221
- }
222
- return config;
223
- }
@@ -1,84 +0,0 @@
1
- /**
2
- * A helper script to load the Expo config and loaded plugins from a project
3
- */
4
-
5
- import fs from 'fs/promises';
6
- import module from 'module';
7
- import path from 'path';
8
- import resolveFrom from 'resolve-from';
9
-
10
- import { DEFAULT_IGNORE_PATHS } from '../Options';
11
- import { isIgnoredPath } from '../utils/Path';
12
-
13
- async function runAsync(programName: string, args: string[] = []) {
14
- if (args.length < 1) {
15
- console.log(`Usage: ${programName} <projectRoot> [ignoredFile]`);
16
- return;
17
- }
18
-
19
- const projectRoot = path.resolve(args[0]);
20
- const ignoredFile = args[1] ? path.resolve(args[1]) : null;
21
-
22
- // @ts-expect-error: module internal _cache
23
- const loadedModulesBefore = new Set(Object.keys(module._cache));
24
-
25
- const { getConfig } = require(resolveFrom(path.resolve(projectRoot), 'expo/config'));
26
- const config = await getConfig(projectRoot, { skipSDKVersionRequirement: true });
27
- // @ts-expect-error: module internal _cache
28
- const loadedModules = Object.keys(module._cache)
29
- .filter((modulePath) => !loadedModulesBefore.has(modulePath))
30
- .map((modulePath) => path.relative(projectRoot, modulePath));
31
-
32
- const ignoredPaths = await loadIgnoredPathsAsync(ignoredFile);
33
- const filteredLoadedModules = loadedModules.filter(
34
- (modulePath) => !isIgnoredPath(modulePath, ignoredPaths)
35
- );
36
- console.log(JSON.stringify({ config, loadedModules: filteredLoadedModules }));
37
- }
38
-
39
- // If running from the command line
40
- if (require.main?.filename === __filename) {
41
- (async () => {
42
- const programIndex = process.argv.findIndex((arg) => arg === __filename);
43
- try {
44
- await runAsync(process.argv[programIndex], process.argv.slice(programIndex + 1));
45
- } catch (e) {
46
- console.error('Uncaught Error', e);
47
- process.exit(1);
48
- }
49
- })();
50
- }
51
-
52
- /**
53
- * Load the generated ignored paths file from caller and remove the file after loading
54
- */
55
- async function loadIgnoredPathsAsync(ignoredFile: string | null) {
56
- if (!ignoredFile) {
57
- return DEFAULT_IGNORE_PATHS;
58
- }
59
-
60
- const ignorePaths = [];
61
- try {
62
- const fingerprintIgnore = await fs.readFile(ignoredFile, 'utf8');
63
- const fingerprintIgnoreLines = fingerprintIgnore.split('\n');
64
- for (const line of fingerprintIgnoreLines) {
65
- const trimmedLine = line.trim();
66
- if (trimmedLine) {
67
- ignorePaths.push(trimmedLine);
68
- }
69
- }
70
- } catch {}
71
-
72
- try {
73
- await fs.rm(ignoredFile);
74
- } catch {}
75
-
76
- return ignorePaths;
77
- }
78
-
79
- /**
80
- * Get the path to the ExpoConfigLoader file.
81
- */
82
- export function getExpoConfigLoaderPath() {
83
- return path.join(__dirname, 'ExpoConfigLoader.js');
84
- }
@@ -1,18 +0,0 @@
1
- import chalk from 'chalk';
2
-
3
- import { getFileBasedHashSourceAsync } from './Utils';
4
- import type { HashSource, NormalizedOptions } from '../Fingerprint.types';
5
-
6
- const debug = require('debug')('expo:fingerprint:sourcer:PatchPackage');
7
-
8
- export async function getPatchPackageSourcesAsync(
9
- projectRoot: string,
10
- options: NormalizedOptions
11
- ): Promise<HashSource[]> {
12
- const result = await getFileBasedHashSourceAsync(projectRoot, 'patches', 'patchPackage');
13
- if (result != null) {
14
- debug(`Adding dir - ${chalk.dim('patches')}`);
15
- return [result];
16
- }
17
- return [];
18
- }