react-native-update-cli 2.7.0 → 2.7.2
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/cli.json +1 -0
- package/lib/api.js +3 -0
- package/lib/esm/api..mjs +183 -0
- package/lib/esm/app..mjs +130 -0
- package/lib/esm/bundle..mjs +823 -0
- package/lib/esm/exports..mjs +11 -0
- package/lib/esm/index..mjs +122 -0
- package/lib/esm/install..mjs +18 -0
- package/lib/esm/locales/en..mjs +131 -0
- package/lib/esm/locales/zh..mjs +130 -0
- package/lib/esm/module-manager..mjs +109 -0
- package/lib/esm/modules/app-module..mjs +213 -0
- package/lib/esm/modules/bundle-module..mjs +178 -0
- package/lib/esm/modules/index..mjs +17 -0
- package/lib/esm/modules/package-module..mjs +6 -0
- package/lib/esm/modules/user-module..mjs +351 -0
- package/lib/esm/modules/version-module..mjs +6 -0
- package/lib/esm/package..mjs +316 -0
- package/lib/esm/provider..mjs +293 -0
- package/lib/esm/types..mjs +1 -0
- package/lib/esm/user..mjs +36 -0
- package/lib/esm/utils/add-gitignore..mjs +32 -0
- package/lib/esm/utils/app-info-parser/aab..mjs +215 -0
- package/lib/esm/utils/app-info-parser/apk..mjs +75 -0
- package/lib/esm/utils/app-info-parser/app..mjs +3 -0
- package/lib/esm/utils/app-info-parser/index..mjs +44 -0
- package/lib/esm/utils/app-info-parser/ipa..mjs +73 -0
- package/lib/esm/utils/app-info-parser/resource-finder..mjs +401 -0
- package/lib/esm/utils/app-info-parser/utils..mjs +121 -0
- package/lib/esm/utils/app-info-parser/xml-parser/binary..mjs +569 -0
- package/lib/esm/utils/app-info-parser/xml-parser/manifest..mjs +200 -0
- package/lib/esm/utils/app-info-parser/zip..mjs +65 -0
- package/lib/esm/utils/check-lockfile..mjs +78 -0
- package/lib/esm/utils/check-plugin..mjs +25 -0
- package/lib/esm/utils/constants..mjs +19 -0
- package/lib/esm/utils/dep-versions..mjs +33 -0
- package/lib/esm/utils/git..mjs +43 -0
- package/lib/esm/utils/http-helper..mjs +70 -0
- package/lib/esm/utils/i18n..mjs +23 -0
- package/lib/esm/utils/index..mjs +316 -0
- package/lib/esm/utils/latest-version/cli..mjs +294 -0
- package/lib/esm/utils/latest-version/index..mjs +238 -0
- package/lib/esm/utils/plugin-config..mjs +23 -0
- package/lib/esm/versions..mjs +290 -0
- package/lib/package.js +1 -1
- package/package.json +19 -2
- package/src/api.ts +3 -0
- package/src/package.ts +1 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// From https://github.com/openstf/adbkit-apkreader
|
|
2
|
+
import { BinaryXmlParser } from "./binary";
|
|
3
|
+
const INTENT_MAIN = 'android.intent.action.MAIN';
|
|
4
|
+
const CATEGORY_LAUNCHER = 'android.intent.category.LAUNCHER';
|
|
5
|
+
export class ManifestParser {
|
|
6
|
+
collapseAttributes(element) {
|
|
7
|
+
const collapsed = Object.create(null);
|
|
8
|
+
for (const attr of Array.from(element.attributes)){
|
|
9
|
+
collapsed[attr.name] = attr.typedValue.value;
|
|
10
|
+
}
|
|
11
|
+
return collapsed;
|
|
12
|
+
}
|
|
13
|
+
parseIntents(element, target) {
|
|
14
|
+
target.intentFilters = [];
|
|
15
|
+
target.metaData = [];
|
|
16
|
+
for (const child of element.childNodes){
|
|
17
|
+
switch(child.nodeName){
|
|
18
|
+
case 'intent-filter':
|
|
19
|
+
{
|
|
20
|
+
const intentFilter = this.collapseAttributes(child);
|
|
21
|
+
intentFilter.actions = [];
|
|
22
|
+
intentFilter.categories = [];
|
|
23
|
+
intentFilter.data = [];
|
|
24
|
+
for (const item of child.childNodes){
|
|
25
|
+
switch(item.nodeName){
|
|
26
|
+
case 'action':
|
|
27
|
+
intentFilter.actions.push(this.collapseAttributes(item));
|
|
28
|
+
break;
|
|
29
|
+
case 'category':
|
|
30
|
+
intentFilter.categories.push(this.collapseAttributes(item));
|
|
31
|
+
break;
|
|
32
|
+
case 'data':
|
|
33
|
+
intentFilter.data.push(this.collapseAttributes(item));
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
target.intentFilters.push(intentFilter);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
case 'meta-data':
|
|
41
|
+
target.metaData.push(this.collapseAttributes(child));
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
parseApplication(element) {
|
|
47
|
+
const app = this.collapseAttributes(element);
|
|
48
|
+
app.activities = [];
|
|
49
|
+
app.activityAliases = [];
|
|
50
|
+
app.launcherActivities = [];
|
|
51
|
+
app.services = [];
|
|
52
|
+
app.receivers = [];
|
|
53
|
+
app.providers = [];
|
|
54
|
+
app.usesLibraries = [];
|
|
55
|
+
app.metaData = [];
|
|
56
|
+
for (const child of element.childNodes){
|
|
57
|
+
switch(child.nodeName){
|
|
58
|
+
case 'activity':
|
|
59
|
+
{
|
|
60
|
+
const activity = this.collapseAttributes(child);
|
|
61
|
+
this.parseIntents(child, activity);
|
|
62
|
+
app.activities.push(activity);
|
|
63
|
+
if (this.isLauncherActivity(activity)) {
|
|
64
|
+
app.launcherActivities.push(activity);
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case 'activity-alias':
|
|
69
|
+
{
|
|
70
|
+
const activityAlias = this.collapseAttributes(child);
|
|
71
|
+
this.parseIntents(child, activityAlias);
|
|
72
|
+
app.activityAliases.push(activityAlias);
|
|
73
|
+
if (this.isLauncherActivity(activityAlias)) {
|
|
74
|
+
app.launcherActivities.push(activityAlias);
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case 'service':
|
|
79
|
+
{
|
|
80
|
+
const service = this.collapseAttributes(child);
|
|
81
|
+
this.parseIntents(child, service);
|
|
82
|
+
app.services.push(service);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case 'receiver':
|
|
86
|
+
{
|
|
87
|
+
const receiver = this.collapseAttributes(child);
|
|
88
|
+
this.parseIntents(child, receiver);
|
|
89
|
+
app.receivers.push(receiver);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
case 'provider':
|
|
93
|
+
{
|
|
94
|
+
const provider = this.collapseAttributes(child);
|
|
95
|
+
provider.grantUriPermissions = [];
|
|
96
|
+
provider.metaData = [];
|
|
97
|
+
provider.pathPermissions = [];
|
|
98
|
+
for (const item of child.childNodes){
|
|
99
|
+
switch(item.nodeName){
|
|
100
|
+
case 'grant-uri-permission':
|
|
101
|
+
provider.grantUriPermissions.push(this.collapseAttributes(item));
|
|
102
|
+
break;
|
|
103
|
+
case 'meta-data':
|
|
104
|
+
provider.metaData.push(this.collapseAttributes(item));
|
|
105
|
+
break;
|
|
106
|
+
case 'path-permission':
|
|
107
|
+
provider.pathPermissions.push(this.collapseAttributes(item));
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
app.providers.push(provider);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
case 'uses-library':
|
|
115
|
+
app.usesLibraries.push(this.collapseAttributes(child));
|
|
116
|
+
break;
|
|
117
|
+
case 'meta-data':
|
|
118
|
+
app.metaData.push(this.collapseAttributes(child));
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return app;
|
|
123
|
+
}
|
|
124
|
+
isLauncherActivity(activity) {
|
|
125
|
+
return activity.intentFilters.some((filter)=>{
|
|
126
|
+
const hasMain = filter.actions.some((action)=>action.name === INTENT_MAIN);
|
|
127
|
+
if (!hasMain) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return filter.categories.some((category)=>category.name === CATEGORY_LAUNCHER);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
parse() {
|
|
134
|
+
const document = this.xmlParser.parse();
|
|
135
|
+
const manifest = this.collapseAttributes(document);
|
|
136
|
+
manifest.usesPermissions = [];
|
|
137
|
+
manifest.usesPermissionsSDK23 = [];
|
|
138
|
+
manifest.permissions = [];
|
|
139
|
+
manifest.permissionTrees = [];
|
|
140
|
+
manifest.permissionGroups = [];
|
|
141
|
+
manifest.instrumentation = null;
|
|
142
|
+
manifest.usesSdk = null;
|
|
143
|
+
manifest.usesConfiguration = null;
|
|
144
|
+
manifest.usesFeatures = [];
|
|
145
|
+
manifest.supportsScreens = null;
|
|
146
|
+
manifest.compatibleScreens = [];
|
|
147
|
+
manifest.supportsGlTextures = [];
|
|
148
|
+
manifest.application = Object.create(null);
|
|
149
|
+
for (const element of document.childNodes){
|
|
150
|
+
switch(element.nodeName){
|
|
151
|
+
case 'uses-permission':
|
|
152
|
+
manifest.usesPermissions.push(this.collapseAttributes(element));
|
|
153
|
+
break;
|
|
154
|
+
case 'uses-permission-sdk-23':
|
|
155
|
+
manifest.usesPermissionsSDK23.push(this.collapseAttributes(element));
|
|
156
|
+
break;
|
|
157
|
+
case 'permission':
|
|
158
|
+
manifest.permissions.push(this.collapseAttributes(element));
|
|
159
|
+
break;
|
|
160
|
+
case 'permission-tree':
|
|
161
|
+
manifest.permissionTrees.push(this.collapseAttributes(element));
|
|
162
|
+
break;
|
|
163
|
+
case 'permission-group':
|
|
164
|
+
manifest.permissionGroups.push(this.collapseAttributes(element));
|
|
165
|
+
break;
|
|
166
|
+
case 'instrumentation':
|
|
167
|
+
manifest.instrumentation = this.collapseAttributes(element);
|
|
168
|
+
break;
|
|
169
|
+
case 'uses-sdk':
|
|
170
|
+
manifest.usesSdk = this.collapseAttributes(element);
|
|
171
|
+
break;
|
|
172
|
+
case 'uses-configuration':
|
|
173
|
+
manifest.usesConfiguration = this.collapseAttributes(element);
|
|
174
|
+
break;
|
|
175
|
+
case 'uses-feature':
|
|
176
|
+
manifest.usesFeatures.push(this.collapseAttributes(element));
|
|
177
|
+
break;
|
|
178
|
+
case 'supports-screens':
|
|
179
|
+
manifest.supportsScreens = this.collapseAttributes(element);
|
|
180
|
+
break;
|
|
181
|
+
case 'compatible-screens':
|
|
182
|
+
for (const screen of element.childNodes){
|
|
183
|
+
manifest.compatibleScreens.push(this.collapseAttributes(screen));
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
case 'supports-gl-texture':
|
|
187
|
+
manifest.supportsGlTextures.push(this.collapseAttributes(element));
|
|
188
|
+
break;
|
|
189
|
+
case 'application':
|
|
190
|
+
manifest.application = this.parseApplication(element);
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return manifest;
|
|
195
|
+
}
|
|
196
|
+
constructor(buffer, options = {}){
|
|
197
|
+
this.buffer = buffer;
|
|
198
|
+
this.xmlParser = new BinaryXmlParser(this.buffer, options);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const Unzip = require('isomorphic-unzip');
|
|
2
|
+
import { decodeNullUnicode, isBrowser } from "./utils";
|
|
3
|
+
let bundleZipUtils;
|
|
4
|
+
export class Zip {
|
|
5
|
+
/**
|
|
6
|
+
* get entries by regexps, the return format is: { <filename>: <Buffer|Blob> }
|
|
7
|
+
* @param {Array} regexps // regexps for matching files
|
|
8
|
+
* @param {String} type // return type, can be buffer or blob, default buffer
|
|
9
|
+
*/ getEntries(regexps, type = 'buffer') {
|
|
10
|
+
const decoded = regexps.map((regex)=>decodeNullUnicode(regex));
|
|
11
|
+
return new Promise((resolve, reject)=>{
|
|
12
|
+
this.unzip.getBuffer(decoded, {
|
|
13
|
+
type
|
|
14
|
+
}, (err, buffers)=>{
|
|
15
|
+
err ? reject(err) : resolve(buffers);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* get entry by regex, return an instance of Buffer or Blob
|
|
21
|
+
* @param {Regex} regex // regex for matching file
|
|
22
|
+
* @param {String} type // return type, can be buffer or blob, default buffer
|
|
23
|
+
*/ getEntry(regex, type = 'buffer') {
|
|
24
|
+
const decoded = decodeNullUnicode(regex);
|
|
25
|
+
return new Promise((resolve, reject)=>{
|
|
26
|
+
this.unzip.getBuffer([
|
|
27
|
+
decoded
|
|
28
|
+
], {
|
|
29
|
+
type
|
|
30
|
+
}, (err, buffers)=>{
|
|
31
|
+
err ? reject(err) : resolve(buffers[decoded]);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async getEntryFromHarmonyApp(regex) {
|
|
36
|
+
try {
|
|
37
|
+
const { enumZipEntries, readEntry } = bundleZipUtils != null ? bundleZipUtils : bundleZipUtils = require('../../bundle');
|
|
38
|
+
let originSource;
|
|
39
|
+
await enumZipEntries(this.file, (entry, zipFile)=>{
|
|
40
|
+
if (regex.test(entry.fileName)) {
|
|
41
|
+
return readEntry(entry, zipFile).then((value)=>{
|
|
42
|
+
originSource = value;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return originSource;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error('Error in getEntryFromHarmonyApp:', error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
constructor(file){
|
|
52
|
+
if (isBrowser()) {
|
|
53
|
+
if (!(file instanceof window.Blob || typeof file.size !== 'undefined')) {
|
|
54
|
+
throw new Error('Param error: [file] must be an instance of Blob or File in browser.');
|
|
55
|
+
}
|
|
56
|
+
this.file = file;
|
|
57
|
+
} else {
|
|
58
|
+
if (typeof file !== 'string') {
|
|
59
|
+
throw new Error('Param error: [file] must be file path in Node.');
|
|
60
|
+
}
|
|
61
|
+
this.file = require('path').resolve(file);
|
|
62
|
+
}
|
|
63
|
+
this.unzip = new Unzip(this.file);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { t } from "./i18n";
|
|
4
|
+
const lockFiles = [
|
|
5
|
+
'package-lock.json',
|
|
6
|
+
'yarn.lock',
|
|
7
|
+
'pnpm-lock.yaml',
|
|
8
|
+
'bun.lockb',
|
|
9
|
+
'bun.lock'
|
|
10
|
+
];
|
|
11
|
+
// Function to check if a package.json has a workspaces field
|
|
12
|
+
function hasWorkspaces(dir) {
|
|
13
|
+
const pkgPath = path.join(dir, 'package.json');
|
|
14
|
+
if (fs.existsSync(pkgPath)) {
|
|
15
|
+
try {
|
|
16
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
17
|
+
return !!pkg.workspaces;
|
|
18
|
+
} catch (e) {
|
|
19
|
+
// Ignore parsing errors
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
// Helper function to find lock files in a specific directory
|
|
25
|
+
function findLockFilesInDir(directory) {
|
|
26
|
+
const found = [];
|
|
27
|
+
for (const file of lockFiles){
|
|
28
|
+
const filePath = path.join(directory, file);
|
|
29
|
+
if (fs.existsSync(filePath)) {
|
|
30
|
+
found.push(filePath);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return found;
|
|
34
|
+
}
|
|
35
|
+
export function checkLockFiles() {
|
|
36
|
+
const cwd = process.cwd();
|
|
37
|
+
let searchDir = cwd;
|
|
38
|
+
let foundLockFiles = findLockFilesInDir(searchDir);
|
|
39
|
+
// If no lock file in cwd, try to find monorepo root and check there
|
|
40
|
+
if (foundLockFiles.length === 0) {
|
|
41
|
+
// Search upwards for package.json with workspaces
|
|
42
|
+
let currentDir = path.dirname(cwd); // Start searching from parent
|
|
43
|
+
let projectRootDir = null;
|
|
44
|
+
while(true){
|
|
45
|
+
if (hasWorkspaces(currentDir)) {
|
|
46
|
+
projectRootDir = currentDir;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
const parentDir = path.dirname(currentDir);
|
|
50
|
+
if (parentDir === currentDir) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
currentDir = parentDir;
|
|
54
|
+
}
|
|
55
|
+
// If a potential root was found, switch search directory and re-check
|
|
56
|
+
if (projectRootDir) {
|
|
57
|
+
searchDir = projectRootDir;
|
|
58
|
+
foundLockFiles = findLockFilesInDir(searchDir);
|
|
59
|
+
}
|
|
60
|
+
// If no projectRootDir found, foundLockFiles remains empty and searchDir remains cwd
|
|
61
|
+
}
|
|
62
|
+
// Handle results based on findings in the final searchDir
|
|
63
|
+
if (foundLockFiles.length === 1) {
|
|
64
|
+
// Successfully found one lock file in the determined searchDir
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (foundLockFiles.length > 1) {
|
|
68
|
+
// Found multiple lock files in the determined searchDir
|
|
69
|
+
console.warn(t('lockBestPractice'));
|
|
70
|
+
throw new Error(t('multipleLocksFound', {
|
|
71
|
+
lockFiles: foundLockFiles.join(', ')
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
// If we reach here, foundLockFiles.length === 0
|
|
75
|
+
console.warn(t('lockBestPractice'));
|
|
76
|
+
// Warn instead of throwing an error if no lock file is found
|
|
77
|
+
console.warn(t('lockNotFound'));
|
|
78
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { t } from "./i18n";
|
|
2
|
+
import { plugins } from "./plugin-config";
|
|
3
|
+
export async function checkPlugins() {
|
|
4
|
+
const params = {
|
|
5
|
+
sentry: false,
|
|
6
|
+
sourcemap: false
|
|
7
|
+
};
|
|
8
|
+
for (const plugin of plugins){
|
|
9
|
+
try {
|
|
10
|
+
const isEnabled = await plugin.detect();
|
|
11
|
+
if (isEnabled && plugin.bundleParams) {
|
|
12
|
+
Object.assign(params, plugin.bundleParams);
|
|
13
|
+
console.log(t('pluginDetected', {
|
|
14
|
+
name: plugin.name
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
} catch (err) {
|
|
18
|
+
console.warn(t('pluginDetectionError', {
|
|
19
|
+
name: plugin.name,
|
|
20
|
+
error: err
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return params;
|
|
25
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
export const scriptName = path.basename(process.argv[1]);
|
|
3
|
+
export const IS_CRESC = scriptName === 'cresc';
|
|
4
|
+
export const ppkBundleFileNames = [
|
|
5
|
+
'index.bundlejs',
|
|
6
|
+
'bundle.harmony.js'
|
|
7
|
+
];
|
|
8
|
+
export const isPPKBundleFileName = (fileName)=>ppkBundleFileNames.includes(fileName);
|
|
9
|
+
export const credentialFile = IS_CRESC ? '.cresc.token' : '.update';
|
|
10
|
+
export const updateJson = IS_CRESC ? 'cresc.config.json' : 'update.json';
|
|
11
|
+
export const tempDir = IS_CRESC ? '.cresc.temp' : '.pushy';
|
|
12
|
+
export const pricingPageUrl = IS_CRESC ? 'https://cresc.dev/pricing' : 'https://pushy.reactnative.cn/pricing.html';
|
|
13
|
+
export const defaultEndpoints = IS_CRESC ? [
|
|
14
|
+
'https://api.cresc.dev',
|
|
15
|
+
'https://api.cresc.app'
|
|
16
|
+
] : [
|
|
17
|
+
'https://update.reactnative.cn/api',
|
|
18
|
+
'https://update.react-native.cn/api'
|
|
19
|
+
];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
let currentPackage = null;
|
|
2
|
+
try {
|
|
3
|
+
currentPackage = require(`${process.cwd()}/package.json`);
|
|
4
|
+
} catch (e) {
|
|
5
|
+
// console.warn('No package.json file were found');
|
|
6
|
+
}
|
|
7
|
+
const _depVersions = {};
|
|
8
|
+
if (currentPackage) {
|
|
9
|
+
const depKeys = currentPackage.dependencies ? Object.keys(currentPackage.dependencies) : [];
|
|
10
|
+
const devDepKeys = currentPackage.devDependencies ? Object.keys(currentPackage.devDependencies) : [];
|
|
11
|
+
const dedupedDeps = [
|
|
12
|
+
...new Set([
|
|
13
|
+
...depKeys,
|
|
14
|
+
...devDepKeys
|
|
15
|
+
])
|
|
16
|
+
];
|
|
17
|
+
for (const dep of dedupedDeps){
|
|
18
|
+
try {
|
|
19
|
+
const packageJsonPath = require.resolve(`${dep}/package.json`, {
|
|
20
|
+
paths: [
|
|
21
|
+
process.cwd()
|
|
22
|
+
]
|
|
23
|
+
});
|
|
24
|
+
const version = require(packageJsonPath).version;
|
|
25
|
+
_depVersions[dep] = version;
|
|
26
|
+
} catch (e) {}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export const depVersions = Object.keys(_depVersions).sort() // Sort the keys alphabetically
|
|
30
|
+
.reduce((obj, key)=>{
|
|
31
|
+
obj[key] = _depVersions[key]; // Rebuild the object with sorted keys
|
|
32
|
+
return obj;
|
|
33
|
+
}, {}); // console.log({ depVersions });
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import git from "isomorphic-git";
|
|
4
|
+
function findGitRoot(dir = process.cwd()) {
|
|
5
|
+
const gitRoot = fs.readdirSync(dir).find((dir)=>dir === '.git');
|
|
6
|
+
if (gitRoot) {
|
|
7
|
+
// console.log({ gitRoot });
|
|
8
|
+
return path.join(dir, gitRoot);
|
|
9
|
+
}
|
|
10
|
+
const parentDir = path.dirname(dir);
|
|
11
|
+
if (parentDir === dir) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return findGitRoot(parentDir);
|
|
15
|
+
}
|
|
16
|
+
const gitRoot = findGitRoot();
|
|
17
|
+
export async function getCommitInfo() {
|
|
18
|
+
if (!gitRoot) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const remotes = await git.listRemotes({
|
|
23
|
+
fs,
|
|
24
|
+
gitdir: gitRoot
|
|
25
|
+
});
|
|
26
|
+
const origin = remotes.find((remote)=>remote.remote === 'origin') || remotes[0];
|
|
27
|
+
const { commit, oid } = (await git.log({
|
|
28
|
+
fs,
|
|
29
|
+
gitdir: gitRoot,
|
|
30
|
+
depth: 1
|
|
31
|
+
}))[0];
|
|
32
|
+
return {
|
|
33
|
+
hash: oid,
|
|
34
|
+
message: commit.message,
|
|
35
|
+
author: commit.author.name || commit.committer.name,
|
|
36
|
+
timestamp: String(commit.committer.timestamp),
|
|
37
|
+
origin: origin == null ? void 0 : origin.url
|
|
38
|
+
};
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error(error);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fetch from "node-fetch";
|
|
2
|
+
import { defaultEndpoints } from "./constants";
|
|
3
|
+
// const baseUrl = `http://localhost:9000`;
|
|
4
|
+
// let baseUrl = SERVER.main[0];
|
|
5
|
+
// const baseUrl = `https://p.reactnative.cn/api`;
|
|
6
|
+
export function promiseAny(promises) {
|
|
7
|
+
return new Promise((resolve, reject)=>{
|
|
8
|
+
let count = 0;
|
|
9
|
+
for (const promise of promises){
|
|
10
|
+
Promise.resolve(promise).then(resolve).catch(()=>{
|
|
11
|
+
count++;
|
|
12
|
+
if (count === promises.length) {
|
|
13
|
+
reject(new Error('All promises were rejected'));
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export const ping = async (url)=>{
|
|
20
|
+
let pingFinished = false;
|
|
21
|
+
return Promise.race([
|
|
22
|
+
fetch(url, {
|
|
23
|
+
method: 'HEAD'
|
|
24
|
+
}).then(({ status, statusText })=>{
|
|
25
|
+
pingFinished = true;
|
|
26
|
+
if (status === 200) {
|
|
27
|
+
// console.log('ping success', url);
|
|
28
|
+
return url;
|
|
29
|
+
}
|
|
30
|
+
// console.log('ping failed', url, status, statusText);
|
|
31
|
+
throw new Error('ping failed');
|
|
32
|
+
}).catch((e)=>{
|
|
33
|
+
pingFinished = true;
|
|
34
|
+
// console.log('ping error', url, e);
|
|
35
|
+
throw new Error('ping error');
|
|
36
|
+
}),
|
|
37
|
+
new Promise((_, reject)=>setTimeout(()=>{
|
|
38
|
+
reject(new Error('ping timeout'));
|
|
39
|
+
if (!pingFinished) {
|
|
40
|
+
// console.log('ping timeout', url);
|
|
41
|
+
}
|
|
42
|
+
}, 2000))
|
|
43
|
+
]);
|
|
44
|
+
};
|
|
45
|
+
export const testUrls = async (urls)=>{
|
|
46
|
+
if (!(urls == null ? void 0 : urls.length)) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const ret = await promiseAny(urls.map(ping));
|
|
50
|
+
if (ret) {
|
|
51
|
+
return ret;
|
|
52
|
+
}
|
|
53
|
+
// console.log('all ping failed, use first url:', urls[0]);
|
|
54
|
+
return urls[0];
|
|
55
|
+
};
|
|
56
|
+
export const getBaseUrl = (async ()=>{
|
|
57
|
+
const testEndpoint = process.env.PUSHY_REGISTRY || process.env.RNU_API;
|
|
58
|
+
if (testEndpoint) {
|
|
59
|
+
return testEndpoint;
|
|
60
|
+
}
|
|
61
|
+
return testUrls(defaultEndpoints.map((url)=>`${url}/status`)).then((ret)=>{
|
|
62
|
+
let baseUrl = defaultEndpoints[0];
|
|
63
|
+
if (ret) {
|
|
64
|
+
// remove /status
|
|
65
|
+
baseUrl = ret.replace('/status', '');
|
|
66
|
+
}
|
|
67
|
+
// console.log('baseUrl', baseUrl);
|
|
68
|
+
return baseUrl;
|
|
69
|
+
});
|
|
70
|
+
})();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import i18next from "i18next";
|
|
2
|
+
import en from "../locales/en";
|
|
3
|
+
import zh from "../locales/zh";
|
|
4
|
+
import { IS_CRESC } from "./constants";
|
|
5
|
+
i18next.init({
|
|
6
|
+
lng: IS_CRESC ? 'en' : 'zh',
|
|
7
|
+
// debug: process.env.NODE_ENV !== 'production',
|
|
8
|
+
// debug: true,
|
|
9
|
+
resources: {
|
|
10
|
+
en: {
|
|
11
|
+
translation: en
|
|
12
|
+
},
|
|
13
|
+
zh: {
|
|
14
|
+
translation: zh
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
interpolation: {
|
|
18
|
+
escapeValue: false
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
export function t(key, options) {
|
|
22
|
+
return i18next.t(key, options);
|
|
23
|
+
}
|