react-native-update 10.37.15 → 10.37.16

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 (68) hide show
  1. package/README-CN.md +72 -0
  2. package/README.md +61 -49
  3. package/bunfig.toml +2 -0
  4. package/harmony/har-wrapper/AppScope/app.json5 +8 -0
  5. package/harmony/har-wrapper/build-profile.json5 +35 -0
  6. package/harmony/har-wrapper/hvigor/hvigor-config.json5 +5 -0
  7. package/harmony/har-wrapper/hvigorfile.ts +6 -0
  8. package/harmony/har-wrapper/oh-package.json5 +4 -0
  9. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/cache-v2-77b153ce45aba0ed28ef.json +1415 -0
  10. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-b65a07793384e0ce3e08.json +809 -0
  11. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-ce0e89410afd8bf3a057.json +60 -0
  12. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/directory-.-Release-f5ebdc15457944623624.json +14 -0
  13. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/index-2026-03-16T14-00-08-0134.json +89 -0
  14. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.cmake/api/v1/reply/target-rnupdate-Release-267153624504c9c3ffdd.json +222 -0
  15. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.ninja_deps +0 -0
  16. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/.ninja_log +8 -0
  17. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeCache.txt +415 -0
  18. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeCCompiler.cmake +74 -0
  19. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeCXXCompiler.cmake +85 -0
  20. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeDetermineCompilerABI_C.bin +0 -0
  21. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeDetermineCompilerABI_CXX.bin +0 -0
  22. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CMakeSystem.cmake +15 -0
  23. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CompilerIdC/CMakeCCompilerId.c +880 -0
  24. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CompilerIdC/CMakeCCompilerId.o +0 -0
  25. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CompilerIdCXX/CMakeCXXCompilerId.cpp +869 -0
  26. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/3.28.2/CompilerIdCXX/CMakeCXXCompilerId.o +0 -0
  27. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/CMakeConfigureLog.yaml +388 -0
  28. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/TargetDirectories.txt +3 -0
  29. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/cmake.check_cache +1 -0
  30. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/HDiffPatch/file_for_patch.c.o +0 -0
  31. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/HDiffPatch/libHDiffPatch/HPatch/patch.c.o +0 -0
  32. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/hpatch.c.o +0 -0
  33. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/lzma/C/Lzma2Dec.c.o +0 -0
  34. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/__w/react-native-update/react-native-update/android/jni/lzma/C/LzmaDec.c.o +0 -0
  35. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rnupdate.dir/pushy.c.o +0 -0
  36. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/CMakeFiles/rules.ninja +64 -0
  37. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/additional_project_files.txt +0 -0
  38. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/build.ninja +206 -0
  39. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/build_file_index.txt +1 -0
  40. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/cmake_install.cmake +54 -0
  41. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/compile_commands.json +38 -0
  42. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/configure_fingerprint.json +1 -0
  43. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/hvigor_native_config.json +1 -0
  44. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/metadata_generation_command.txt +17 -0
  45. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/native_work_dir.txt +1 -0
  46. package/harmony/pushy/.cxx/default/default/release/arm64-v8a/output.log +14 -0
  47. package/harmony/pushy/.cxx/default/default/release/hvigor/arm64-v8a/summary.cmake +0 -0
  48. package/harmony/pushy/BuildProfile.ets +3 -5
  49. package/harmony/pushy/build-profile.json5 +8 -1
  50. package/harmony/pushy/oh-package-lock.json5 +1 -1
  51. package/harmony/pushy/src/main/cpp/CMakeLists.txt +42 -30
  52. package/harmony/pushy/src/main/ets/DownloadTask.ts +145 -106
  53. package/harmony/pushy/src/main/ets/Logger.ts +24 -7
  54. package/harmony/pushy/src/main/ets/PushyFileJSBundleProvider.ets +1 -1
  55. package/harmony/pushy/src/main/ets/PushyTurboModule.ts +9 -73
  56. package/harmony/pushy/src/main/ets/UpdateContext.ts +206 -70
  57. package/harmony/pushy.har +0 -0
  58. package/package.json +2 -1
  59. package/scripts/build-harmony-har.js +427 -0
  60. package/scripts/prepublish.ts +66 -4
  61. package/src/__tests__/core.test.ts +103 -0
  62. package/src/__tests__/setup.ts +37 -0
  63. package/src/__tests__/utils.test.ts +36 -0
  64. package/src/client.ts +14 -8
  65. package/src/core.ts +5 -5
  66. package/src/locales/en.ts +1 -0
  67. package/src/locales/zh.ts +1 -0
  68. package/src/utils.ts +13 -1
@@ -1,50 +1,135 @@
1
1
  import preferences from '@ohos.data.preferences';
2
2
  import bundleManager from '@ohos.bundle.bundleManager';
3
3
  import fileIo from '@ohos.file.fs';
4
- import { DownloadTask } from './DownloadTask';
5
4
  import common from '@ohos.app.ability.common';
5
+ import { util } from '@kit.ArkTS';
6
+ import { DownloadTask } from './DownloadTask';
6
7
  import { DownloadTaskParams } from './DownloadTaskParams';
7
8
 
9
+ type LaunchMarks = {
10
+ isFirstTime: boolean;
11
+ rolledBackVersion: string;
12
+ };
13
+
8
14
  export class UpdateContext {
15
+ private static instances: Map<string, UpdateContext> = new Map();
16
+ private static isUsingBundleUrl: boolean = false;
17
+ private static ignoreRollbackInCurrentProcess: boolean = false;
18
+
19
+ static getInstance(context: common.UIAbilityContext): UpdateContext {
20
+ const key = context.filesDir;
21
+ const cached = UpdateContext.instances.get(key);
22
+ if (cached) {
23
+ return cached;
24
+ }
25
+
26
+ const instance = new UpdateContext(context);
27
+ UpdateContext.instances.set(key, instance);
28
+ return instance;
29
+ }
30
+
9
31
  private context: common.UIAbilityContext;
10
32
  private rootDir: string;
11
33
  private preferences: preferences.Preferences;
12
- private static DEBUG: boolean = false;
13
- private static isUsingBundleUrl: boolean = false;
14
34
 
15
- constructor(context: common.UIAbilityContext) {
35
+ private constructor(context: common.UIAbilityContext) {
16
36
  this.context = context;
17
- this.rootDir = context.filesDir + '/_update';
37
+ this.rootDir = `${context.filesDir}/_update`;
38
+ this.ensureRootDir();
39
+ this.initPreferences();
40
+ }
18
41
 
42
+ private ensureRootDir(): void {
19
43
  try {
20
44
  if (!fileIo.accessSync(this.rootDir)) {
21
45
  fileIo.mkdirSync(this.rootDir);
22
46
  }
23
- } catch (e) {
24
- console.error('Failed to create root directory:', e);
47
+ } catch (error) {
48
+ console.error('Failed to create root directory:', error);
25
49
  }
26
- this.initPreferences();
27
50
  }
28
51
 
29
- private initPreferences() {
52
+ private initPreferences(): void {
30
53
  try {
31
54
  this.preferences = preferences.getPreferencesSync(this.context, {
32
55
  name: 'update',
33
56
  });
57
+
34
58
  const packageVersion = this.getPackageVersion();
35
- const storedVersion = this.preferences.getSync('packageVersion', '');
36
- if (!storedVersion) {
37
- this.preferences.putSync('packageVersion', packageVersion);
38
- this.preferences.flush();
39
- } else if (storedVersion && packageVersion !== storedVersion) {
40
- this.cleanUp();
59
+ const buildTime = this.getBuildTime();
60
+ const storedPackageVersion = this.getStringPreference('packageVersion');
61
+ const storedBuildTime = this.getStringPreference('buildTime');
62
+ const packageVersionChanged =
63
+ !!storedPackageVersion && packageVersion !== storedPackageVersion;
64
+ const buildTimeChanged =
65
+ !!storedBuildTime && buildTime !== storedBuildTime;
66
+
67
+ if (packageVersionChanged || buildTimeChanged) {
68
+ this.scheduleCleanUp();
41
69
  this.preferences.clear();
70
+ UpdateContext.ignoreRollbackInCurrentProcess = false;
71
+ }
72
+
73
+ let shouldFlush = packageVersionChanged || buildTimeChanged;
74
+ if (this.getStringPreference('packageVersion') !== packageVersion) {
42
75
  this.preferences.putSync('packageVersion', packageVersion);
76
+ shouldFlush = true;
77
+ }
78
+ if (this.getStringPreference('buildTime') !== buildTime) {
79
+ this.preferences.putSync('buildTime', buildTime);
80
+ shouldFlush = true;
81
+ }
82
+
83
+ if (shouldFlush) {
43
84
  this.preferences.flush();
44
85
  }
45
- } catch (e) {
46
- console.error('Failed to init preferences:', e);
86
+ } catch (error) {
87
+ console.error('Failed to init preferences:', error);
88
+ }
89
+ }
90
+
91
+ private getStringPreference(key: string, fallback: string = ''): string {
92
+ const value = this.preferences.getSync(key, fallback);
93
+ if (typeof value === 'string') {
94
+ return value;
95
+ }
96
+ if (value === null || value === undefined) {
97
+ return fallback;
98
+ }
99
+ return String(value);
100
+ }
101
+
102
+ private getBooleanPreference(
103
+ key: string,
104
+ fallback: boolean = false,
105
+ ): boolean {
106
+ const value = this.preferences.getSync(key, fallback);
107
+ if (typeof value === 'boolean') {
108
+ return value;
109
+ }
110
+ if (typeof value === 'string') {
111
+ const normalized = value.trim().toLowerCase();
112
+ if (normalized === 'true') {
113
+ return true;
114
+ }
115
+ if (normalized === 'false' || normalized === '') {
116
+ return false;
117
+ }
47
118
  }
119
+ if (typeof value === 'number') {
120
+ return value !== 0;
121
+ }
122
+ return fallback;
123
+ }
124
+
125
+ private scheduleCleanUp(): void {
126
+ void this.cleanUp().catch(error => {
127
+ console.error('Failed to clean up updates:', error);
128
+ });
129
+ }
130
+
131
+ public getRootDir(): string {
132
+ return this.rootDir;
48
133
  }
49
134
 
50
135
  public setKv(key: string, value: string): void {
@@ -53,40 +138,62 @@ export class UpdateContext {
53
138
  }
54
139
 
55
140
  public getKv(key: string): string {
56
- return this.preferences.getSync(key, '') as string;
141
+ return this.getStringPreference(key);
57
142
  }
58
143
 
59
144
  public isFirstTime(): boolean {
60
- return this.preferences.getSync('firstTime', false) as boolean;
145
+ return this.getBooleanPreference('firstTime', false);
61
146
  }
62
147
 
63
148
  public rolledBackVersion(): string {
64
- return this.preferences.getSync('rolledBackVersion', '') as string;
149
+ return this.getStringPreference('rolledBackVersion');
150
+ }
151
+
152
+ public consumeLaunchMarks(): LaunchMarks {
153
+ const marks = {
154
+ isFirstTime: this.getBooleanPreference('firstTimeMarked', false),
155
+ rolledBackVersion: this.rolledBackVersion(),
156
+ };
157
+
158
+ if (marks.isFirstTime) {
159
+ this.preferences.deleteSync('firstTimeMarked');
160
+ }
161
+ if (marks.rolledBackVersion) {
162
+ this.preferences.deleteSync('rolledBackVersion');
163
+ }
164
+ if (marks.isFirstTime || marks.rolledBackVersion) {
165
+ this.preferences.flush();
166
+ this.scheduleCleanUp();
167
+ }
168
+
169
+ return marks;
65
170
  }
66
171
 
67
172
  public markSuccess(): void {
68
173
  this.preferences.putSync('firstTimeOk', true);
69
- const lastVersion = this.preferences.getSync('lastVersion', '') as string;
70
- const curVersion = this.preferences.getSync('currentVersion', '') as string;
174
+ const lastVersion = this.getStringPreference('lastVersion');
175
+ const currentVersion = this.getStringPreference('currentVersion');
71
176
 
72
- if (lastVersion && lastVersion !== curVersion) {
177
+ if (lastVersion && lastVersion !== currentVersion) {
73
178
  this.preferences.deleteSync('lastVersion');
74
179
  this.preferences.deleteSync(`hash_${lastVersion}`);
75
180
  }
181
+
76
182
  this.preferences.flush();
77
- this.cleanUp();
183
+ this.scheduleCleanUp();
78
184
  }
79
185
 
80
186
  public clearFirstTime(): void {
81
187
  this.preferences.putSync('firstTime', false);
188
+ this.preferences.deleteSync('firstTimeMarked');
82
189
  this.preferences.flush();
83
- this.cleanUp();
190
+ this.scheduleCleanUp();
84
191
  }
85
192
 
86
193
  public clearRollbackMark(): void {
87
- this.preferences.putSync('rolledBackVersion', null);
194
+ this.preferences.deleteSync('rolledBackVersion');
88
195
  this.preferences.flush();
89
- this.cleanUp();
196
+ this.scheduleCleanUp();
90
197
  }
91
198
 
92
199
  public async downloadFullUpdate(url: string, hash: string): Promise<void> {
@@ -99,9 +206,9 @@ export class UpdateContext {
99
206
  params.unzipDirectory = `${this.rootDir}/${hash}`;
100
207
  const downloadTask = new DownloadTask(this.context);
101
208
  await downloadTask.execute(params);
102
- } catch (e) {
103
- console.error('Failed to download full update:', e);
104
- throw e;
209
+ } catch (error) {
210
+ console.error('Failed to download full update:', error);
211
+ throw error;
105
212
  }
106
213
  }
107
214
 
@@ -114,7 +221,7 @@ export class UpdateContext {
114
221
  params.type = DownloadTaskParams.TASK_TYPE_PLAIN_DOWNLOAD;
115
222
  params.url = url;
116
223
  params.hash = hash;
117
- params.targetFile = this.rootDir + '/' + fileName;
224
+ params.targetFile = `${this.rootDir}/${fileName}`;
118
225
 
119
226
  const downloadTask = new DownloadTask(this.context);
120
227
  await downloadTask.execute(params);
@@ -151,10 +258,10 @@ export class UpdateContext {
151
258
  params.unzipDirectory = `${this.rootDir}/${hash}`;
152
259
 
153
260
  const downloadTask = new DownloadTask(this.context);
154
- return await downloadTask.execute(params);
155
- } catch (e) {
156
- console.error('Failed to download package patch:', e);
157
- throw e;
261
+ await downloadTask.execute(params);
262
+ } catch (error) {
263
+ console.error('Failed to download package patch:', error);
264
+ throw error;
158
265
  }
159
266
  }
160
267
 
@@ -165,33 +272,47 @@ export class UpdateContext {
165
272
  throw Error(`Bundle version ${hash} not found.`);
166
273
  }
167
274
 
168
- const lastVersion = this.getKv('currentVersion');
169
- this.setKv('currentVersion', hash);
275
+ const lastVersion = this.getCurrentVersion();
276
+ this.preferences.putSync('currentVersion', hash);
170
277
  if (lastVersion && lastVersion !== hash) {
171
- this.setKv('lastVersion', lastVersion);
278
+ this.preferences.putSync('lastVersion', lastVersion);
279
+ } else {
280
+ this.preferences.deleteSync('lastVersion');
172
281
  }
173
-
174
- this.setKv('firstTime', 'true');
175
- this.setKv('firstTimeOk', 'false');
176
- this.setKv('rolledBackVersion', '');
177
- } catch (e) {
178
- console.error('Failed to switch version:', e);
179
- throw e;
282
+ this.preferences.putSync('firstTime', true);
283
+ this.preferences.putSync('firstTimeOk', false);
284
+ this.preferences.deleteSync('firstTimeMarked');
285
+ this.preferences.deleteSync('rolledBackVersion');
286
+ this.preferences.flush();
287
+ UpdateContext.ignoreRollbackInCurrentProcess = false;
288
+ } catch (error) {
289
+ console.error('Failed to switch version:', error);
290
+ throw error;
180
291
  }
181
292
  }
182
293
 
183
- public getBundleUrl() {
294
+ public getBundleUrl(): string {
184
295
  UpdateContext.isUsingBundleUrl = true;
185
- const currentVersion = this.getCurrentVersion();
186
- if (!currentVersion) {
296
+ let version = this.getCurrentVersion();
297
+ if (!version) {
187
298
  return '';
188
299
  }
189
- if (!this.isFirstTime()) {
190
- if (!this.preferences.getSync('firstTimeOk', true)) {
191
- return this.rollBack();
192
- }
300
+
301
+ const isFirstTime = this.isFirstTime();
302
+ const isFirstTimeOk = this.getBooleanPreference('firstTimeOk', true);
303
+ if (
304
+ !UpdateContext.ignoreRollbackInCurrentProcess &&
305
+ !isFirstTime &&
306
+ !isFirstTimeOk
307
+ ) {
308
+ version = this.rollBack();
309
+ } else if (isFirstTime && !UpdateContext.ignoreRollbackInCurrentProcess) {
310
+ UpdateContext.ignoreRollbackInCurrentProcess = true;
311
+ this.preferences.putSync('firstTime', false);
312
+ this.preferences.putSync('firstTimeMarked', true);
313
+ this.preferences.flush();
193
314
  }
194
- let version = currentVersion;
315
+
195
316
  while (version) {
196
317
  const bundleFile = `${this.rootDir}/${version}/bundle.harmony.js`;
197
318
  try {
@@ -201,38 +322,52 @@ export class UpdateContext {
201
322
  continue;
202
323
  }
203
324
  return bundleFile;
204
- } catch (e) {
205
- console.error('Failed to access bundle file:', e);
325
+ } catch (error) {
326
+ console.error('Failed to access bundle file:', error);
206
327
  version = this.rollBack();
207
328
  }
208
329
  }
330
+
209
331
  return '';
210
332
  }
211
333
 
212
- getPackageVersion(): string {
213
- let bundleFlags =
214
- bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION;
334
+ public getPackageVersion(): string {
215
335
  let packageVersion = '';
216
336
  try {
217
- const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleFlags);
337
+ const bundleInfo = bundleManager.getBundleInfoForSelfSync(
338
+ bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION,
339
+ );
218
340
  packageVersion = bundleInfo?.versionName || 'Unknown';
219
341
  } catch (error) {
220
- console.error('获取包信息失败:', error);
342
+ console.error('Failed to get bundle info:', error);
221
343
  }
222
344
  return packageVersion;
223
345
  }
224
346
 
347
+ public getBuildTime(): string {
348
+ try {
349
+ const content =
350
+ this.context.resourceManager.getRawFileContentSync('meta.json');
351
+ const metaData = JSON.parse(
352
+ new util.TextDecoder().decodeToString(content),
353
+ ) as {
354
+ pushy_build_time?: string | number;
355
+ };
356
+ if (metaData.pushy_build_time !== undefined) {
357
+ return String(metaData.pushy_build_time);
358
+ }
359
+ } catch {}
360
+ return '';
361
+ }
362
+
225
363
  public getCurrentVersion(): string {
226
- const currentVersion = this.getKv('currentVersion');
227
- return currentVersion;
364
+ return this.getStringPreference('currentVersion');
228
365
  }
229
366
 
230
367
  private rollBack(): string {
231
- const lastVersion = this.preferences.getSync('lastVersion', '') as string;
232
- const currentVersion = this.preferences.getSync(
233
- 'currentVersion',
234
- '',
235
- ) as string;
368
+ const lastVersion = this.getStringPreference('lastVersion');
369
+ const currentVersion = this.getCurrentVersion();
370
+
236
371
  if (!lastVersion) {
237
372
  this.preferences.deleteSync('currentVersion');
238
373
  } else {
@@ -241,16 +376,17 @@ export class UpdateContext {
241
376
  }
242
377
  this.preferences.putSync('firstTimeOk', true);
243
378
  this.preferences.putSync('firstTime', false);
379
+ this.preferences.deleteSync('firstTimeMarked');
244
380
  this.preferences.putSync('rolledBackVersion', currentVersion);
245
381
  this.preferences.flush();
246
382
  return lastVersion;
247
383
  }
248
384
 
249
- public async cleanUp() {
385
+ public async cleanUp(): Promise<void> {
250
386
  const params = new DownloadTaskParams();
251
387
  params.type = DownloadTaskParams.TASK_TYPE_CLEANUP;
252
- params.hash = this.preferences.getSync('currentVersion', '') as string;
253
- params.originHash = this.preferences.getSync('lastVersion', '') as string;
388
+ params.hash = this.getCurrentVersion();
389
+ params.originHash = this.getStringPreference('lastVersion');
254
390
  params.unzipDirectory = this.rootDir;
255
391
  const downloadTask = new DownloadTask(this.context);
256
392
  await downloadTask.execute(params);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-update",
3
- "version": "10.37.15",
3
+ "version": "10.37.16",
4
4
  "description": "react-native hot update",
5
5
  "main": "src/index",
6
6
  "scripts": {
@@ -10,6 +10,7 @@
10
10
  "lint": "eslint \"src/*.@(ts|tsx|js|jsx)\" && tsc --noEmit",
11
11
  "submodule": "git submodule update --init --recursive",
12
12
  "test": "echo \"Error: no test specified\" && exit 1",
13
+ "build:harmony-har": "node scripts/build-harmony-har.js",
13
14
  "build:so": "bun submodule && $ANDROID_HOME/ndk/28.2.13676358/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib",
14
15
  "build:ios-debug": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.debug",
15
16
  "build:ios-release": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.release",