@expo/fingerprint 0.0.1
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/.eslintignore +1 -0
- package/LICENSE +22 -0
- package/README.md +118 -0
- package/__mocks__/fs/promises.ts +2 -0
- package/__mocks__/fs.ts +2 -0
- package/babel.config.js +6 -0
- package/bin/cli.js +27 -0
- package/build/Dedup.d.ts +9 -0
- package/build/Dedup.js +83 -0
- package/build/Dedup.js.map +1 -0
- package/build/Fingerprint.d.ts +13 -0
- package/build/Fingerprint.js +42 -0
- package/build/Fingerprint.js.map +1 -0
- package/build/Fingerprint.types.d.ts +78 -0
- package/build/Fingerprint.types.js +4 -0
- package/build/Fingerprint.types.js.map +1 -0
- package/build/Options.d.ts +2 -0
- package/build/Options.js +23 -0
- package/build/Options.js.map +1 -0
- package/build/Sort.d.ts +2 -0
- package/build/Sort.js +27 -0
- package/build/Sort.js.map +1 -0
- package/build/hash/Hash.d.ts +28 -0
- package/build/hash/Hash.js +166 -0
- package/build/hash/Hash.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +22 -0
- package/build/index.js.map +1 -0
- package/build/sourcer/Bare.d.ts +6 -0
- package/build/sourcer/Bare.js +107 -0
- package/build/sourcer/Bare.js.map +1 -0
- package/build/sourcer/Expo.d.ts +5 -0
- package/build/sourcer/Expo.js +175 -0
- package/build/sourcer/Expo.js.map +1 -0
- package/build/sourcer/PatchPackage.d.ts +2 -0
- package/build/sourcer/PatchPackage.js +19 -0
- package/build/sourcer/PatchPackage.js.map +1 -0
- package/build/sourcer/Sourcer.d.ts +2 -0
- package/build/sourcer/Sourcer.js +42 -0
- package/build/sourcer/Sourcer.js.map +1 -0
- package/build/sourcer/Utils.d.ts +2 -0
- package/build/sourcer/Utils.js +25 -0
- package/build/sourcer/Utils.js.map +1 -0
- package/build/utils/Profile.d.ts +8 -0
- package/build/utils/Profile.js +43 -0
- package/build/utils/Profile.js.map +1 -0
- package/e2e/__tests__/__snapshots__/managed-test.ts.snap +200 -0
- package/e2e/__tests__/bare-test.ts +66 -0
- package/e2e/__tests__/managed-test.ts +162 -0
- package/e2e/jest.config.js +10 -0
- package/jest.config.js +10 -0
- package/package.json +70 -0
- package/scripts/createFixture.ts +81 -0
- package/src/Dedup.ts +97 -0
- package/src/Fingerprint.ts +51 -0
- package/src/Fingerprint.types.ts +98 -0
- package/src/Options.ts +18 -0
- package/src/Sort.ts +22 -0
- package/src/__tests__/Dedup-test.ts +177 -0
- package/src/__tests__/Fingerprint-test.ts +116 -0
- package/src/__tests__/Sort-test.ts +56 -0
- package/src/hash/Hash.ts +204 -0
- package/src/hash/__tests__/Hash-test.ts +192 -0
- package/src/index.ts +3 -0
- package/src/sourcer/Bare.ts +114 -0
- package/src/sourcer/Expo.ts +216 -0
- package/src/sourcer/PatchPackage.ts +18 -0
- package/src/sourcer/Sourcer.ts +58 -0
- package/src/sourcer/Utils.ts +23 -0
- package/src/sourcer/__tests__/Bare-test.ts +59 -0
- package/src/sourcer/__tests__/Expo-test.ts +265 -0
- package/src/sourcer/__tests__/PatchPackage-test.ts +54 -0
- package/src/sourcer/__tests__/Sourcer-test.ts +14 -0
- package/src/sourcer/__tests__/__snapshots__/Bare-test.ts.snap +29 -0
- package/src/sourcer/__tests__/__snapshots__/Expo-test.ts.snap +139 -0
- package/src/sourcer/__tests__/fixtures/BareReactNative70Project.json +47 -0
- package/src/sourcer/__tests__/fixtures/ExpoAutolinkingAndroid.json +82 -0
- package/src/sourcer/__tests__/fixtures/ExpoAutolinkingIos.json +114 -0
- package/src/sourcer/__tests__/fixtures/ExpoManaged47Project.json +6 -0
- package/src/sourcer/__tests__/fixtures/PatchPackage.json +4 -0
- package/src/sourcer/__tests__/fixtures/RncliAutoLinking.json +165 -0
- package/src/utils/Profile.ts +47 -0
- package/src/utils/__tests__/Profile-test.ts +11 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrap a method and profile the time it takes to execute the method using `EXPO_PROFILE`.
|
|
3
|
+
* Works best with named functions (i.e. not arrow functions).
|
|
4
|
+
*
|
|
5
|
+
* @param fn function to profile.
|
|
6
|
+
* @param functionName optional name of the function to display in the profile output.
|
|
7
|
+
*/
|
|
8
|
+
export declare function profile<IArgs extends any[], T extends (...args: IArgs) => any>(fn: T, functionName?: string): T;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.profile = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
/**
|
|
9
|
+
* Wrap a method and profile the time it takes to execute the method using `EXPO_PROFILE`.
|
|
10
|
+
* Works best with named functions (i.e. not arrow functions).
|
|
11
|
+
*
|
|
12
|
+
* @param fn function to profile.
|
|
13
|
+
* @param functionName optional name of the function to display in the profile output.
|
|
14
|
+
*/
|
|
15
|
+
function profile(fn, functionName = fn.name) {
|
|
16
|
+
if (!process.env['DEBUG']) {
|
|
17
|
+
return fn;
|
|
18
|
+
}
|
|
19
|
+
const name = chalk_1.default.dim(`⏱ [profile] ${functionName ?? 'unknown'}`);
|
|
20
|
+
return ((...args) => {
|
|
21
|
+
// Start the timer.
|
|
22
|
+
console.time(name);
|
|
23
|
+
// Invoke the method.
|
|
24
|
+
const results = fn(...args);
|
|
25
|
+
// If non-promise then return as-is.
|
|
26
|
+
if (!(results instanceof Promise)) {
|
|
27
|
+
console.timeEnd(name);
|
|
28
|
+
return results;
|
|
29
|
+
}
|
|
30
|
+
// Otherwise await to profile after the promise resolves.
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
results.then((results) => {
|
|
33
|
+
resolve(results);
|
|
34
|
+
console.timeEnd(name);
|
|
35
|
+
}, (reason) => {
|
|
36
|
+
reject(reason);
|
|
37
|
+
console.timeEnd(name);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
exports.profile = profile;
|
|
43
|
+
//# sourceMappingURL=Profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Profile.js","sourceRoot":"","sources":["../../src/utils/Profile.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAE1B;;;;;;GAMG;AACH,SAAgB,OAAO,CACrB,EAAK,EACL,eAAuB,EAAE,CAAC,IAAI;IAE9B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;QACzB,OAAO,EAAE,CAAC;KACX;IAED,MAAM,IAAI,GAAG,eAAK,CAAC,GAAG,CAAC,gBAAgB,YAAY,IAAI,SAAS,EAAE,CAAC,CAAC;IAEpE,OAAO,CAAC,CAAC,GAAG,IAAW,EAAE,EAAE;QACzB,mBAAmB;QACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEnB,qBAAqB;QACrB,MAAM,OAAO,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAE5B,oCAAoC;QACpC,IAAI,CAAC,CAAC,OAAO,YAAY,OAAO,CAAC,EAAE;YACjC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO,OAAO,CAAC;SAChB;QAED,yDAAyD;QACzD,OAAO,IAAI,OAAO,CAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7D,OAAO,CAAC,IAAI,CACV,CAAC,OAAO,EAAE,EAAE;gBACV,OAAO,CAAC,OAAO,CAAC,CAAC;gBACjB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC,EACD,CAAC,MAAM,EAAE,EAAE;gBACT,MAAM,CAAC,MAAM,CAAC,CAAC;gBACf,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAM,CAAC;AACV,CAAC;AArCD,0BAqCC"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`getHashSourcesAsync - managed project should match snapshot 1`] = `
|
|
4
|
+
Array [
|
|
5
|
+
Object {
|
|
6
|
+
"filePath": "node_modules/expo/android",
|
|
7
|
+
"reasons": Array [
|
|
8
|
+
"expoAutolinkingAndroid",
|
|
9
|
+
],
|
|
10
|
+
"type": "dir",
|
|
11
|
+
},
|
|
12
|
+
Object {
|
|
13
|
+
"filePath": "node_modules/expo-application/android",
|
|
14
|
+
"reasons": Array [
|
|
15
|
+
"expoAutolinkingAndroid",
|
|
16
|
+
],
|
|
17
|
+
"type": "dir",
|
|
18
|
+
},
|
|
19
|
+
Object {
|
|
20
|
+
"filePath": "node_modules/expo-constants/android",
|
|
21
|
+
"reasons": Array [
|
|
22
|
+
"expoAutolinkingAndroid",
|
|
23
|
+
],
|
|
24
|
+
"type": "dir",
|
|
25
|
+
},
|
|
26
|
+
Object {
|
|
27
|
+
"filePath": "node_modules/expo-error-recovery/android",
|
|
28
|
+
"reasons": Array [
|
|
29
|
+
"expoAutolinkingAndroid",
|
|
30
|
+
],
|
|
31
|
+
"type": "dir",
|
|
32
|
+
},
|
|
33
|
+
Object {
|
|
34
|
+
"filePath": "node_modules/expo-file-system/android",
|
|
35
|
+
"reasons": Array [
|
|
36
|
+
"expoAutolinkingAndroid",
|
|
37
|
+
],
|
|
38
|
+
"type": "dir",
|
|
39
|
+
},
|
|
40
|
+
Object {
|
|
41
|
+
"filePath": "node_modules/expo-font/android",
|
|
42
|
+
"reasons": Array [
|
|
43
|
+
"expoAutolinkingAndroid",
|
|
44
|
+
],
|
|
45
|
+
"type": "dir",
|
|
46
|
+
},
|
|
47
|
+
Object {
|
|
48
|
+
"filePath": "node_modules/expo-keep-awake/android",
|
|
49
|
+
"reasons": Array [
|
|
50
|
+
"expoAutolinkingAndroid",
|
|
51
|
+
],
|
|
52
|
+
"type": "dir",
|
|
53
|
+
},
|
|
54
|
+
Object {
|
|
55
|
+
"filePath": "node_modules/expo-modules-core/android",
|
|
56
|
+
"reasons": Array [
|
|
57
|
+
"expoAutolinkingAndroid",
|
|
58
|
+
],
|
|
59
|
+
"type": "dir",
|
|
60
|
+
},
|
|
61
|
+
Object {
|
|
62
|
+
"contents": "{\\"modules\\":[{\\"packageName\\":\\"expo\\",\\"packageVersion\\":\\"47.0.8\\",\\"projects\\":[{\\"name\\":\\"expo\\",\\"sourceDir\\":\\"node_modules/expo/android\\"}],\\"modules\\":[]},{\\"packageName\\":\\"expo-application\\",\\"packageVersion\\":\\"5.0.1\\",\\"projects\\":[{\\"name\\":\\"expo-application\\",\\"sourceDir\\":\\"node_modules/expo-application/android\\"}],\\"modules\\":[]},{\\"packageName\\":\\"expo-constants\\",\\"packageVersion\\":\\"14.0.2\\",\\"projects\\":[{\\"name\\":\\"expo-constants\\",\\"sourceDir\\":\\"node_modules/expo-constants/android\\"}],\\"modules\\":[]},{\\"packageName\\":\\"expo-error-recovery\\",\\"packageVersion\\":\\"4.0.1\\",\\"projects\\":[{\\"name\\":\\"expo-error-recovery\\",\\"sourceDir\\":\\"node_modules/expo-error-recovery/android\\"}],\\"modules\\":[]},{\\"packageName\\":\\"expo-file-system\\",\\"packageVersion\\":\\"15.1.1\\",\\"projects\\":[{\\"name\\":\\"expo-file-system\\",\\"sourceDir\\":\\"node_modules/expo-file-system/android\\"}],\\"modules\\":[]},{\\"packageName\\":\\"expo-font\\",\\"packageVersion\\":\\"11.0.1\\",\\"projects\\":[{\\"name\\":\\"expo-font\\",\\"sourceDir\\":\\"node_modules/expo-font/android\\"}],\\"modules\\":[]},{\\"packageName\\":\\"expo-keep-awake\\",\\"packageVersion\\":\\"11.0.1\\",\\"projects\\":[{\\"name\\":\\"expo-keep-awake\\",\\"sourceDir\\":\\"node_modules/expo-keep-awake/android\\"}],\\"modules\\":[]},{\\"packageName\\":\\"expo-modules-core\\",\\"packageVersion\\":\\"1.0.3\\",\\"projects\\":[{\\"name\\":\\"expo-modules-core\\",\\"sourceDir\\":\\"node_modules/expo-modules-core/android\\"}],\\"modules\\":[]}]}",
|
|
63
|
+
"id": "expoAutolinkingConfig:android",
|
|
64
|
+
"reasons": Array [
|
|
65
|
+
"expoAutolinkingAndroid",
|
|
66
|
+
],
|
|
67
|
+
"type": "contents",
|
|
68
|
+
},
|
|
69
|
+
Object {
|
|
70
|
+
"filePath": "node_modules/expo",
|
|
71
|
+
"reasons": Array [
|
|
72
|
+
"expoAutolinkingIos",
|
|
73
|
+
],
|
|
74
|
+
"type": "dir",
|
|
75
|
+
},
|
|
76
|
+
Object {
|
|
77
|
+
"filePath": "node_modules/expo-application/ios",
|
|
78
|
+
"reasons": Array [
|
|
79
|
+
"expoAutolinkingIos",
|
|
80
|
+
],
|
|
81
|
+
"type": "dir",
|
|
82
|
+
},
|
|
83
|
+
Object {
|
|
84
|
+
"filePath": "node_modules/expo-constants/ios",
|
|
85
|
+
"reasons": Array [
|
|
86
|
+
"expoAutolinkingIos",
|
|
87
|
+
],
|
|
88
|
+
"type": "dir",
|
|
89
|
+
},
|
|
90
|
+
Object {
|
|
91
|
+
"filePath": "node_modules/expo-error-recovery/ios",
|
|
92
|
+
"reasons": Array [
|
|
93
|
+
"expoAutolinkingIos",
|
|
94
|
+
],
|
|
95
|
+
"type": "dir",
|
|
96
|
+
},
|
|
97
|
+
Object {
|
|
98
|
+
"filePath": "node_modules/expo-file-system/ios",
|
|
99
|
+
"reasons": Array [
|
|
100
|
+
"expoAutolinkingIos",
|
|
101
|
+
],
|
|
102
|
+
"type": "dir",
|
|
103
|
+
},
|
|
104
|
+
Object {
|
|
105
|
+
"filePath": "node_modules/expo-font/ios",
|
|
106
|
+
"reasons": Array [
|
|
107
|
+
"expoAutolinkingIos",
|
|
108
|
+
],
|
|
109
|
+
"type": "dir",
|
|
110
|
+
},
|
|
111
|
+
Object {
|
|
112
|
+
"filePath": "node_modules/expo-keep-awake/ios",
|
|
113
|
+
"reasons": Array [
|
|
114
|
+
"expoAutolinkingIos",
|
|
115
|
+
],
|
|
116
|
+
"type": "dir",
|
|
117
|
+
},
|
|
118
|
+
Object {
|
|
119
|
+
"filePath": "node_modules/expo-modules-core",
|
|
120
|
+
"reasons": Array [
|
|
121
|
+
"expoAutolinkingIos",
|
|
122
|
+
],
|
|
123
|
+
"type": "dir",
|
|
124
|
+
},
|
|
125
|
+
Object {
|
|
126
|
+
"contents": "{\\"modules\\":[{\\"packageName\\":\\"expo\\",\\"packageVersion\\":\\"47.0.8\\",\\"pods\\":[{\\"podName\\":\\"Expo\\",\\"podspecDir\\":\\"node_modules/expo\\"}],\\"swiftModuleNames\\":[\\"Expo\\"],\\"modules\\":[],\\"appDelegateSubscribers\\":[],\\"reactDelegateHandlers\\":[],\\"debugOnly\\":false},{\\"packageName\\":\\"expo-application\\",\\"packageVersion\\":\\"5.0.1\\",\\"pods\\":[{\\"podName\\":\\"EXApplication\\",\\"podspecDir\\":\\"node_modules/expo-application/ios\\"}],\\"swiftModuleNames\\":[\\"EXApplication\\"],\\"modules\\":[],\\"appDelegateSubscribers\\":[],\\"reactDelegateHandlers\\":[],\\"debugOnly\\":false},{\\"packageName\\":\\"expo-constants\\",\\"packageVersion\\":\\"14.0.2\\",\\"pods\\":[{\\"podName\\":\\"EXConstants\\",\\"podspecDir\\":\\"node_modules/expo-constants/ios\\"}],\\"swiftModuleNames\\":[\\"EXConstants\\"],\\"modules\\":[],\\"appDelegateSubscribers\\":[],\\"reactDelegateHandlers\\":[],\\"debugOnly\\":false},{\\"packageName\\":\\"expo-error-recovery\\",\\"packageVersion\\":\\"4.0.1\\",\\"pods\\":[{\\"podName\\":\\"EXErrorRecovery\\",\\"podspecDir\\":\\"node_modules/expo-error-recovery/ios\\"}],\\"swiftModuleNames\\":[\\"EXErrorRecovery\\"],\\"modules\\":[],\\"appDelegateSubscribers\\":[],\\"reactDelegateHandlers\\":[],\\"debugOnly\\":false},{\\"packageName\\":\\"expo-file-system\\",\\"packageVersion\\":\\"15.1.1\\",\\"pods\\":[{\\"podName\\":\\"EXFileSystem\\",\\"podspecDir\\":\\"node_modules/expo-file-system/ios\\"}],\\"swiftModuleNames\\":[\\"EXFileSystem\\"],\\"modules\\":[],\\"appDelegateSubscribers\\":[],\\"reactDelegateHandlers\\":[],\\"debugOnly\\":false},{\\"packageName\\":\\"expo-font\\",\\"packageVersion\\":\\"11.0.1\\",\\"pods\\":[{\\"podName\\":\\"EXFont\\",\\"podspecDir\\":\\"node_modules/expo-font/ios\\"}],\\"swiftModuleNames\\":[\\"EXFont\\"],\\"modules\\":[],\\"appDelegateSubscribers\\":[],\\"reactDelegateHandlers\\":[],\\"debugOnly\\":false},{\\"packageName\\":\\"expo-keep-awake\\",\\"packageVersion\\":\\"11.0.1\\",\\"pods\\":[{\\"podName\\":\\"ExpoKeepAwake\\",\\"podspecDir\\":\\"node_modules/expo-keep-awake/ios\\"}],\\"swiftModuleNames\\":[\\"ExpoKeepAwake\\"],\\"modules\\":[\\"KeepAwakeModule\\"],\\"appDelegateSubscribers\\":[],\\"reactDelegateHandlers\\":[],\\"debugOnly\\":false},{\\"packageName\\":\\"expo-modules-core\\",\\"packageVersion\\":\\"1.0.3\\",\\"pods\\":[{\\"podName\\":\\"ExpoModulesCore\\",\\"podspecDir\\":\\"node_modules/expo-modules-core\\"}],\\"swiftModuleNames\\":[\\"ExpoModulesCore\\"],\\"modules\\":[],\\"appDelegateSubscribers\\":[],\\"reactDelegateHandlers\\":[],\\"debugOnly\\":false}]}",
|
|
127
|
+
"id": "expoAutolinkingConfig:ios",
|
|
128
|
+
"reasons": Array [
|
|
129
|
+
"expoAutolinkingIos",
|
|
130
|
+
],
|
|
131
|
+
"type": "contents",
|
|
132
|
+
},
|
|
133
|
+
Object {
|
|
134
|
+
"filePath": "app.json",
|
|
135
|
+
"reasons": Array [
|
|
136
|
+
"expoConfig",
|
|
137
|
+
],
|
|
138
|
+
"type": "file",
|
|
139
|
+
},
|
|
140
|
+
Object {
|
|
141
|
+
"filePath": "./assets/icon.png",
|
|
142
|
+
"reasons": Array [
|
|
143
|
+
"expoConfigExternalFile",
|
|
144
|
+
],
|
|
145
|
+
"type": "file",
|
|
146
|
+
},
|
|
147
|
+
Object {
|
|
148
|
+
"filePath": "./assets/adaptive-icon.png",
|
|
149
|
+
"reasons": Array [
|
|
150
|
+
"expoConfigExternalFile",
|
|
151
|
+
],
|
|
152
|
+
"type": "file",
|
|
153
|
+
},
|
|
154
|
+
Object {
|
|
155
|
+
"filePath": "./assets/splash.png",
|
|
156
|
+
"reasons": Array [
|
|
157
|
+
"expoConfigExternalFile",
|
|
158
|
+
],
|
|
159
|
+
"type": "file",
|
|
160
|
+
},
|
|
161
|
+
Object {
|
|
162
|
+
"filePath": ".gitignore",
|
|
163
|
+
"reasons": Array [
|
|
164
|
+
"bareGitIgnore",
|
|
165
|
+
],
|
|
166
|
+
"type": "file",
|
|
167
|
+
},
|
|
168
|
+
Object {
|
|
169
|
+
"contents": "{\\"start\\":\\"expo start\\",\\"android\\":\\"expo start --android\\",\\"ios\\":\\"expo start --ios\\",\\"web\\":\\"expo start --web\\"}",
|
|
170
|
+
"id": "packageJson:scripts",
|
|
171
|
+
"reasons": Array [
|
|
172
|
+
"packageJson:scripts",
|
|
173
|
+
],
|
|
174
|
+
"type": "contents",
|
|
175
|
+
},
|
|
176
|
+
Object {
|
|
177
|
+
"filePath": "node_modules/expo",
|
|
178
|
+
"reasons": Array [
|
|
179
|
+
"bareRncliAutolinking",
|
|
180
|
+
],
|
|
181
|
+
"type": "dir",
|
|
182
|
+
},
|
|
183
|
+
Object {
|
|
184
|
+
"contents": "{\\"sourceDir\\":\\"node_modules/expo/android\\",\\"packageImportPath\\":\\"import expo.modules.ExpoModulesPackage;\\",\\"packageInstance\\":\\"new ExpoModulesPackage()\\",\\"buildTypes\\":[],\\"componentDescriptors\\":[],\\"androidMkPath\\":\\"node_modules/expo/android/build/generated/source/codegen/jni/Android.mk\\",\\"cmakeListsPath\\":\\"node_modules/expo/android/build/generated/source/codegen/jni/CMakeLists.txt\\"}",
|
|
185
|
+
"id": "rncliAutolinkingConfig:expo:android",
|
|
186
|
+
"reasons": Array [
|
|
187
|
+
"bareRncliAutolinking",
|
|
188
|
+
],
|
|
189
|
+
"type": "contents",
|
|
190
|
+
},
|
|
191
|
+
Object {
|
|
192
|
+
"contents": "{\\"podspecPath\\":\\"node_modules/expo/Expo.podspec\\",\\"configurations\\":[],\\"scriptPhases\\":[]}",
|
|
193
|
+
"id": "rncliAutolinkingConfig:expo:ios",
|
|
194
|
+
"reasons": Array [
|
|
195
|
+
"bareRncliAutolinking",
|
|
196
|
+
],
|
|
197
|
+
"type": "contents",
|
|
198
|
+
},
|
|
199
|
+
]
|
|
200
|
+
`;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import spawnAsync from '@expo/spawn-async';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import rimraf from 'rimraf';
|
|
6
|
+
|
|
7
|
+
import { createProjectHashAsync } from '../../src/Fingerprint';
|
|
8
|
+
|
|
9
|
+
describe('bare project test', () => {
|
|
10
|
+
jest.setTimeout(600000);
|
|
11
|
+
const tmpDir = os.tmpdir();
|
|
12
|
+
const projectName = 'fingerprint-e2e-bare';
|
|
13
|
+
const projectRoot = path.join(tmpDir, projectName);
|
|
14
|
+
|
|
15
|
+
beforeAll(async () => {
|
|
16
|
+
rimraf.sync(projectRoot);
|
|
17
|
+
await spawnAsync('npx', ['create-expo-app', '-t', 'bare-minimum', projectName], {
|
|
18
|
+
stdio: 'inherit',
|
|
19
|
+
cwd: tmpDir,
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterAll(async () => {
|
|
24
|
+
rimraf.sync(projectRoot);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should have same hash after adding js only library', async () => {
|
|
28
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
29
|
+
await spawnAsync('npm', ['install', '--save', '@react-navigation/core'], {
|
|
30
|
+
stdio: 'ignore',
|
|
31
|
+
cwd: projectRoot,
|
|
32
|
+
});
|
|
33
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
34
|
+
expect(hash).toBe(hash2);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should have different hash after adding native library', async () => {
|
|
38
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
39
|
+
await spawnAsync('npm', ['install', '--save', 'react-native-reanimated'], {
|
|
40
|
+
stdio: 'ignore',
|
|
41
|
+
cwd: projectRoot,
|
|
42
|
+
});
|
|
43
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
44
|
+
expect(hash).not.toBe(hash2);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should have different hash after changing podfile', async () => {
|
|
48
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
49
|
+
const filePath = path.join(projectRoot, 'ios', 'Podfile');
|
|
50
|
+
let contents = await fs.readFile(filePath, 'utf8');
|
|
51
|
+
contents = contents.replace(/(:fabric_enabled)\s*=>.*,$/gm, '$1 => true,');
|
|
52
|
+
await fs.writeFile(filePath, contents);
|
|
53
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
54
|
+
expect(hash).not.toBe(hash2);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should have same hash for specifing android platform after changing podfile', async () => {
|
|
58
|
+
const hash = await createProjectHashAsync(projectRoot, { platforms: ['android'] });
|
|
59
|
+
const filePath = path.join(projectRoot, 'ios', 'Podfile');
|
|
60
|
+
let contents = await fs.readFile(filePath, 'utf8');
|
|
61
|
+
contents = contents.replace(/(:fabric_enabled)\s*=>.*$/gm, '$1 => false,');
|
|
62
|
+
await fs.writeFile(filePath, contents);
|
|
63
|
+
const hash2 = await createProjectHashAsync(projectRoot, { platforms: ['android'] });
|
|
64
|
+
expect(hash).toBe(hash2);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import spawnAsync from '@expo/spawn-async';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import rimraf from 'rimraf';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
createFingerprintAsync,
|
|
8
|
+
createProjectHashAsync,
|
|
9
|
+
diffFingerprintChangesAsync,
|
|
10
|
+
} from '../../src/Fingerprint';
|
|
11
|
+
import { normalizeOptions } from '../../src/Options';
|
|
12
|
+
import { getHashSourcesAsync } from '../../src/sourcer/Sourcer';
|
|
13
|
+
|
|
14
|
+
describe('managed project test', () => {
|
|
15
|
+
jest.setTimeout(600000);
|
|
16
|
+
const tmpDir = require('temp-dir');
|
|
17
|
+
const projectName = 'fingerprint-e2e-managed';
|
|
18
|
+
const projectRoot = path.join(tmpDir, projectName);
|
|
19
|
+
|
|
20
|
+
beforeAll(async () => {
|
|
21
|
+
rimraf.sync(projectRoot);
|
|
22
|
+
await spawnAsync('npx', ['create-expo-app', '-t', 'blank', projectName], {
|
|
23
|
+
stdio: 'inherit',
|
|
24
|
+
cwd: tmpDir,
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterAll(async () => {
|
|
29
|
+
rimraf.sync(projectRoot);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should have same hash after adding js only library', async () => {
|
|
33
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
34
|
+
await spawnAsync('npx', ['expo', 'install', '@react-navigation/core'], {
|
|
35
|
+
stdio: 'ignore',
|
|
36
|
+
cwd: projectRoot,
|
|
37
|
+
});
|
|
38
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
39
|
+
expect(hash).toBe(hash2);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should have same hash after updating js code', async () => {
|
|
43
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
44
|
+
|
|
45
|
+
const jsPath = path.join(projectRoot, 'App.js');
|
|
46
|
+
const js = await fs.readFile(jsPath, 'utf8');
|
|
47
|
+
await fs.writeFile(jsPath, `${js}\n// adding comments`);
|
|
48
|
+
|
|
49
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
50
|
+
expect(hash).toBe(hash2);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should have different hash after adding native library', async () => {
|
|
54
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
55
|
+
await spawnAsync('npx', ['expo', 'install', 'expo-updates'], {
|
|
56
|
+
stdio: 'ignore',
|
|
57
|
+
cwd: projectRoot,
|
|
58
|
+
});
|
|
59
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
60
|
+
expect(hash).not.toBe(hash2);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should have different hash after updating `jsEngine`', async () => {
|
|
64
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
65
|
+
|
|
66
|
+
const configPath = path.join(projectRoot, 'app.json');
|
|
67
|
+
const config = JSON.parse(await fs.readFile(configPath, 'utf8'));
|
|
68
|
+
config.jsEngine = 'hermes';
|
|
69
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
70
|
+
|
|
71
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
72
|
+
expect(hash).not.toBe(hash2);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should have different hash after updating icon file', async () => {
|
|
76
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
77
|
+
|
|
78
|
+
const iconPath = path.join(projectRoot, 'assets', 'icon.png');
|
|
79
|
+
await fs.writeFile(iconPath, '');
|
|
80
|
+
|
|
81
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
82
|
+
expect(hash).not.toBe(hash2);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should have different hash after adding js only config-plugin', async () => {
|
|
86
|
+
const hash = await createProjectHashAsync(projectRoot);
|
|
87
|
+
await spawnAsync('npx', ['expo', 'install', 'expo-build-properties'], {
|
|
88
|
+
stdio: 'ignore',
|
|
89
|
+
cwd: projectRoot,
|
|
90
|
+
});
|
|
91
|
+
const hash2 = await createProjectHashAsync(projectRoot);
|
|
92
|
+
expect(hash).not.toBe(hash2);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('diffFingerprintChangesAsync - should return diff after adding native library', async () => {
|
|
96
|
+
const fingerprint = await createFingerprintAsync(projectRoot);
|
|
97
|
+
await spawnAsync('npm', ['install', '--save', '@react-native-community/netinfo@9.3.7'], {
|
|
98
|
+
stdio: 'ignore',
|
|
99
|
+
cwd: projectRoot,
|
|
100
|
+
});
|
|
101
|
+
const diff = await diffFingerprintChangesAsync(fingerprint, projectRoot);
|
|
102
|
+
expect(diff).toMatchInlineSnapshot(`
|
|
103
|
+
Array [
|
|
104
|
+
Object {
|
|
105
|
+
"filePath": "node_modules/@react-native-community/netinfo",
|
|
106
|
+
"hash": "9864bf3bf95283fe99774aaeec91965d70f3eab3",
|
|
107
|
+
"reasons": Array [
|
|
108
|
+
"bareRncliAutolinking",
|
|
109
|
+
],
|
|
110
|
+
"type": "dir",
|
|
111
|
+
},
|
|
112
|
+
Object {
|
|
113
|
+
"contents": "{\\"sourceDir\\":\\"node_modules/@react-native-community/netinfo/android\\",\\"packageImportPath\\":\\"import com.reactnativecommunity.netinfo.NetInfoPackage;\\",\\"packageInstance\\":\\"new NetInfoPackage()\\",\\"buildTypes\\":[],\\"componentDescriptors\\":[],\\"androidMkPath\\":\\"node_modules/@react-native-community/netinfo/android/build/generated/source/codegen/jni/Android.mk\\",\\"cmakeListsPath\\":\\"node_modules/@react-native-community/netinfo/android/build/generated/source/codegen/jni/CMakeLists.txt\\"}",
|
|
114
|
+
"hash": "cb4dfbb38f9151ecd6621bc9e36055540495c463",
|
|
115
|
+
"id": "rncliAutolinkingConfig:@react-native-community/netinfo:android",
|
|
116
|
+
"reasons": Array [
|
|
117
|
+
"bareRncliAutolinking",
|
|
118
|
+
],
|
|
119
|
+
"type": "contents",
|
|
120
|
+
},
|
|
121
|
+
Object {
|
|
122
|
+
"contents": "{\\"podspecPath\\":\\"node_modules/@react-native-community/netinfo/react-native-netinfo.podspec\\",\\"configurations\\":[],\\"scriptPhases\\":[]}",
|
|
123
|
+
"hash": "40eebce5caf94df11096238a5a2ca648ea9f242e",
|
|
124
|
+
"id": "rncliAutolinkingConfig:@react-native-community/netinfo:ios",
|
|
125
|
+
"reasons": Array [
|
|
126
|
+
"bareRncliAutolinking",
|
|
127
|
+
],
|
|
128
|
+
"type": "contents",
|
|
129
|
+
},
|
|
130
|
+
]
|
|
131
|
+
`);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe(`getHashSourcesAsync - managed project`, () => {
|
|
136
|
+
jest.setTimeout(600000);
|
|
137
|
+
const tmpDir = require('temp-dir');
|
|
138
|
+
const projectName = 'fingerprint-e2e-managed';
|
|
139
|
+
const projectRoot = path.join(tmpDir, projectName);
|
|
140
|
+
|
|
141
|
+
beforeAll(async () => {
|
|
142
|
+
rimraf.sync(projectRoot);
|
|
143
|
+
await spawnAsync('npx', ['create-expo-app', '-t', 'blank@sdk-47', projectName], {
|
|
144
|
+
stdio: 'inherit',
|
|
145
|
+
cwd: tmpDir,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Pin the `expo` package version to prevent the latest version and break snapshot
|
|
149
|
+
await spawnAsync('npm', ['install', '--save', 'expo@47.0.8'], {
|
|
150
|
+
cwd: projectRoot,
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
afterAll(async () => {
|
|
155
|
+
rimraf.sync(projectRoot);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should match snapshot', async () => {
|
|
159
|
+
const sources = await getHashSourcesAsync(projectRoot, normalizeOptions());
|
|
160
|
+
expect(sources).toMatchSnapshot();
|
|
161
|
+
});
|
|
162
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
testEnvironment: 'node',
|
|
5
|
+
testRegex: '/__tests__/.*(test|spec)\\.[jt]sx?$',
|
|
6
|
+
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
|
|
7
|
+
rootDir: path.resolve(__dirname),
|
|
8
|
+
displayName: require('../package').name,
|
|
9
|
+
roots: ['.'],
|
|
10
|
+
};
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
testEnvironment: 'node',
|
|
5
|
+
testRegex: '/__tests__/.*(test|spec)\\.[jt]sx?$',
|
|
6
|
+
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
|
|
7
|
+
rootDir: path.resolve(__dirname),
|
|
8
|
+
displayName: require('./package').name,
|
|
9
|
+
roots: ['__mocks__', 'src'],
|
|
10
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@expo/fingerprint",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A library to generate a fingerprint from a React Native project",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"types": "build/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"watch": "tsc --watch --preserveWatchOutput",
|
|
9
|
+
"build": "tsc --sourceMap",
|
|
10
|
+
"prepare": "yarn run clean && yarn build",
|
|
11
|
+
"clean": "rimraf build ./tsconfig.tsbuildinfo",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"test": "jest",
|
|
14
|
+
"test:e2e": "jest --config e2e/jest.config.js"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"fingerprint": "bin/cli.js"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"expo",
|
|
21
|
+
"react-native",
|
|
22
|
+
"fingerprint",
|
|
23
|
+
"hash",
|
|
24
|
+
"node"
|
|
25
|
+
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/expo/expo.git",
|
|
29
|
+
"directory": "packages/@expo/fingerprint"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/expo/expo/issues"
|
|
33
|
+
},
|
|
34
|
+
"author": "650 Industries, Inc.",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"homepage": "https://github.com/expo/expo/tree/main/packages/@expo/fingerprint#readme",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@expo/spawn-async": "^1.5.0",
|
|
39
|
+
"chalk": "^4.1.2",
|
|
40
|
+
"debug": "^4.3.4",
|
|
41
|
+
"find-up": "^5.0.0",
|
|
42
|
+
"minimatch": "^3.0.4",
|
|
43
|
+
"p-limit": "^3.1.0",
|
|
44
|
+
"resolve-from": "^5.0.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/find-up": "^4.0.0",
|
|
48
|
+
"@types/jest": "^26.0.24",
|
|
49
|
+
"@types/rimraf": "^3.0.0",
|
|
50
|
+
"eslint": "^8.20.0",
|
|
51
|
+
"eslint-config-universe": "^11.1.0",
|
|
52
|
+
"expo": "^47.0.0",
|
|
53
|
+
"glob": "^7.1.7",
|
|
54
|
+
"jest": "^26.6.3",
|
|
55
|
+
"jest-watch-typeahead": "0.6.4",
|
|
56
|
+
"memfs": "^3.4.12",
|
|
57
|
+
"rimraf": "^3.0.2",
|
|
58
|
+
"temp-dir": "^2.0.0",
|
|
59
|
+
"typescript": "^4.3.5"
|
|
60
|
+
},
|
|
61
|
+
"peerDependencies": {
|
|
62
|
+
"expo": ">=47.0.0"
|
|
63
|
+
},
|
|
64
|
+
"peerDependenciesMeta": {
|
|
65
|
+
"expo": {
|
|
66
|
+
"optional": true
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"gitHead": "d422f8b881cc113962c7c00ce7ea9be75e24caa4"
|
|
70
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool to generate vol JSON fixture from a project.
|
|
3
|
+
*
|
|
4
|
+
* Usage: npx ts-node scripts/createFixture /path/to/app /path/to/output.json
|
|
5
|
+
*/
|
|
6
|
+
import realFS from 'fs';
|
|
7
|
+
import glob from 'glob';
|
|
8
|
+
import { fs, vol } from 'memfs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
function globAsync(pattern: string, options: Parameters<typeof glob>[1]): Promise<string[]> {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
glob(pattern, options, (err, matches) => {
|
|
14
|
+
if (err != null) {
|
|
15
|
+
reject(err);
|
|
16
|
+
} else {
|
|
17
|
+
resolve(matches);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function createFixtureAsync(targetDir: string, outputFile: string) {
|
|
24
|
+
const files = await globAsync('**/*', {
|
|
25
|
+
cwd: targetDir,
|
|
26
|
+
ignore: [
|
|
27
|
+
// binary files
|
|
28
|
+
'**/*.{jpg,png}',
|
|
29
|
+
|
|
30
|
+
// lock files
|
|
31
|
+
'**/*.lock',
|
|
32
|
+
|
|
33
|
+
// node files
|
|
34
|
+
'**/node_modules/**',
|
|
35
|
+
|
|
36
|
+
// generated files
|
|
37
|
+
'**/build/**',
|
|
38
|
+
|
|
39
|
+
// ios files
|
|
40
|
+
'ios/Pods/**',
|
|
41
|
+
'vendor/**',
|
|
42
|
+
'**/xcuserdata/**',
|
|
43
|
+
'**/*.xcassets/**',
|
|
44
|
+
'**/IDEWorkspaceChecks.plist',
|
|
45
|
+
|
|
46
|
+
// android files
|
|
47
|
+
'**/*.jar',
|
|
48
|
+
'**/*.keystore',
|
|
49
|
+
'**/gradlew',
|
|
50
|
+
'**/gradlew.bat',
|
|
51
|
+
'**/gradle/wrapper/**',
|
|
52
|
+
],
|
|
53
|
+
nodir: true,
|
|
54
|
+
});
|
|
55
|
+
for (const file of files) {
|
|
56
|
+
const content = realFS.readFileSync(path.join(targetDir, file), 'utf8');
|
|
57
|
+
fs.mkdirSync(path.join('/', path.dirname(file)), { recursive: true });
|
|
58
|
+
fs.writeFileSync(path.join('/', file), content);
|
|
59
|
+
}
|
|
60
|
+
const resultJSON: Record<string, string | null> = {};
|
|
61
|
+
for (const [key, value] of Object.entries(vol.toJSON())) {
|
|
62
|
+
resultJSON[path.join('/app', path.relative('/', key))] = value;
|
|
63
|
+
}
|
|
64
|
+
realFS.writeFileSync(outputFile, JSON.stringify(resultJSON, null, 2));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
(async () => {
|
|
68
|
+
if (process.argv.length !== 4) {
|
|
69
|
+
console.log(`Usage: ${path.basename(process.argv[1])} targetDir outputFile`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
const targetDir = process.argv[2];
|
|
73
|
+
const outputFile = process.argv[3];
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await createFixtureAsync(targetDir, outputFile);
|
|
77
|
+
} catch (e) {
|
|
78
|
+
console.error('Uncaught Error', e);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
})();
|