@expo-harmony/config-plugins 55.0.10-harmony.2 → 55.0.10-harmony.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +203 -11
- package/build/compiler.d.ts +7 -0
- package/build/compiler.js +12 -0
- package/build/composition.d.ts +24 -0
- package/build/composition.js +11 -0
- package/build/config.d.ts +2 -15
- package/build/customFiles.d.ts +15 -0
- package/build/customFiles.js +108 -0
- package/build/files.d.ts +1 -1
- package/build/files.js +2 -2
- package/build/generatedFiles.d.ts +15 -0
- package/build/generatedFiles.js +70 -0
- package/build/index.d.ts +20 -5
- package/build/index.js +53 -6
- package/build/internal.d.ts +3 -0
- package/build/internal.js +13 -0
- package/build/manifest.d.ts +38 -0
- package/build/manifest.js +71 -0
- package/build/mods.d.ts +37 -31
- package/build/mods.js +118 -86
- package/build/normalizeConfig.d.ts +10 -3
- package/build/normalizeConfig.js +45 -47
- package/build/ownership.d.ts +4 -3
- package/build/ownership.js +17 -0
- package/build/paths.d.ts +13 -10
- package/build/paths.js +32 -31
- package/build/permissions.d.ts +12 -0
- package/build/permissions.js +60 -0
- package/build/pluginTypes.d.ts +15 -0
- package/build/pluginTypes.js +2 -0
- package/build/resources.d.ts +13 -0
- package/build/resources.js +55 -0
- package/package.json +9 -9
- package/src/compiler.ts +21 -0
- package/src/composition.ts +45 -0
- package/src/config.ts +3 -19
- package/src/customFiles.ts +142 -0
- package/src/files.ts +3 -4
- package/src/generatedFiles.ts +85 -0
- package/src/index.ts +20 -11
- package/src/internal.ts +3 -0
- package/src/manifest.ts +151 -0
- package/src/mods.ts +180 -128
- package/src/nativeInputs.ts +0 -1
- package/src/normalizeConfig.ts +56 -59
- package/src/ownership.ts +25 -5
- package/src/paths.ts +41 -45
- package/src/permissions.ts +68 -0
- package/src/pluginTypes.ts +24 -0
- package/src/resources.ts +65 -0
package/src/mods.ts
CHANGED
|
@@ -3,11 +3,15 @@ import path from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
withBaseMod, withMod,
|
|
6
|
-
type
|
|
6
|
+
type ExportedConfig, type ModPlatform,
|
|
7
7
|
} from '@expo/config-plugins';
|
|
8
8
|
import type { ExpoConfig } from '@expo/config-types';
|
|
9
9
|
|
|
10
10
|
import { HarmonyConfigPluginError } from './errors';
|
|
11
|
+
import type { ExpoConfigWithHarmony } from './config';
|
|
12
|
+
import type { HarmonyModuleJson } from './manifest';
|
|
13
|
+
import type { HarmonyConfigPlugin, HarmonyModAction, HarmonyModConfig } from './pluginTypes';
|
|
14
|
+
import type { HarmonyResourceFile } from './resources';
|
|
11
15
|
import { atomicWrite, readJson5, readText, writeJson5 } from './files';
|
|
12
16
|
import {
|
|
13
17
|
ManagedPaths, ProjectPaths, ResourcePaths,
|
|
@@ -21,7 +25,6 @@ export type HarmonyModName
|
|
|
21
25
|
| 'projectBuildProfile'
|
|
22
26
|
| 'rootOhPackage'
|
|
23
27
|
| 'rootHvigor'
|
|
24
|
-
| 'nativeInputsStamp'
|
|
25
28
|
| 'hvigorConfig'
|
|
26
29
|
| 'entryBuildProfile'
|
|
27
30
|
| 'entryOhPackage'
|
|
@@ -31,21 +34,20 @@ export type HarmonyModName
|
|
|
31
34
|
| 'colors'
|
|
32
35
|
| 'media'
|
|
33
36
|
| 'profiles'
|
|
37
|
+
| 'abilityStage'
|
|
34
38
|
| 'entryAbility'
|
|
35
39
|
| 'indexPage'
|
|
36
40
|
| 'worker'
|
|
37
41
|
| 'arktsPackageProvider'
|
|
38
42
|
| 'cppPackageProvider'
|
|
39
43
|
| 'cmakeLists'
|
|
40
|
-
| 'autolinking'
|
|
41
|
-
| 'manifest';
|
|
44
|
+
| 'autolinking';
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
) => ExportedConfigWithProps<T> | Promise<ExportedConfigWithProps<T>>;
|
|
46
|
+
type InternalModName = 'nativeInputsStamp' | 'manifest' | 'prepare' | 'patch';
|
|
47
|
+
type AnyModName = HarmonyModName | InternalModName;
|
|
46
48
|
|
|
47
49
|
export type HarmonyJson = Record<string, unknown>;
|
|
48
|
-
export type HarmonyResourceMap = Record<string,
|
|
50
|
+
export type HarmonyResourceMap = Record<string, HarmonyResourceFile>;
|
|
49
51
|
export type HarmonyMediaDescriptor
|
|
50
52
|
= | {
|
|
51
53
|
source: string;
|
|
@@ -96,6 +98,7 @@ const TextMods = new Set<FileModName>([
|
|
|
96
98
|
'rootHvigor',
|
|
97
99
|
'nativeInputsStamp',
|
|
98
100
|
'entryHvigor',
|
|
101
|
+
'abilityStage',
|
|
99
102
|
'entryAbility',
|
|
100
103
|
'indexPage',
|
|
101
104
|
'worker',
|
|
@@ -104,11 +107,12 @@ const TextMods = new Set<FileModName>([
|
|
|
104
107
|
'cmakeLists',
|
|
105
108
|
]);
|
|
106
109
|
const ResourceMods = new Set<HarmonyModName>(['strings', 'colors', 'media']);
|
|
107
|
-
const VirtualMods = new Set<
|
|
110
|
+
const VirtualMods = new Set<AnyModName>(['dangerous', 'autolinking', 'manifest', 'prepare', 'patch']);
|
|
108
111
|
const ResourceModNames: readonly ResourceModName[] = ['strings', 'colors', 'media'];
|
|
109
112
|
|
|
110
|
-
|
|
113
|
+
const AllModNames: readonly AnyModName[] = Object.freeze([
|
|
111
114
|
'dangerous',
|
|
115
|
+
'prepare',
|
|
112
116
|
'reactNativeConfig',
|
|
113
117
|
'appJson',
|
|
114
118
|
'projectBuildProfile',
|
|
@@ -124,6 +128,7 @@ export const HarmonyModNames: readonly HarmonyModName[] = Object.freeze([
|
|
|
124
128
|
'colors',
|
|
125
129
|
'media',
|
|
126
130
|
'profiles',
|
|
131
|
+
'abilityStage',
|
|
127
132
|
'entryAbility',
|
|
128
133
|
'indexPage',
|
|
129
134
|
'worker',
|
|
@@ -131,9 +136,14 @@ export const HarmonyModNames: readonly HarmonyModName[] = Object.freeze([
|
|
|
131
136
|
'cppPackageProvider',
|
|
132
137
|
'cmakeLists',
|
|
133
138
|
'autolinking',
|
|
139
|
+
'patch',
|
|
134
140
|
'manifest',
|
|
135
141
|
]);
|
|
136
142
|
|
|
143
|
+
export const HarmonyModNames: readonly HarmonyModName[] = Object.freeze(
|
|
144
|
+
AllModNames.filter((name): name is HarmonyModName => name !== 'manifest' && name !== 'nativeInputsStamp' && name !== 'prepare' && name !== 'patch')
|
|
145
|
+
);
|
|
146
|
+
|
|
137
147
|
export function recordManagedFile(config: ManagedConfig, file: string, owner: string): void {
|
|
138
148
|
config._internal ??= {};
|
|
139
149
|
config._internal.harmonyManagedFiles ??= [];
|
|
@@ -146,7 +156,7 @@ export function recordManagedFile(config: ManagedConfig, file: string, owner: st
|
|
|
146
156
|
config._internal.harmonyManagedFiles = files;
|
|
147
157
|
}
|
|
148
158
|
|
|
149
|
-
function assertModResults(
|
|
159
|
+
function assertModResults(name: AnyModName, value: unknown, kind: 'json' | 'resource' | 'text'): void {
|
|
150
160
|
const valid = kind === 'text'
|
|
151
161
|
? typeof value === 'string'
|
|
152
162
|
: value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
@@ -154,35 +164,42 @@ function assertModResults(modName: HarmonyModName, value: unknown, kind: 'json'
|
|
|
154
164
|
if (!valid) {
|
|
155
165
|
throw new HarmonyConfigPluginError(
|
|
156
166
|
'ERR_HARMONY_MOD_RESULTS_INVALID',
|
|
157
|
-
`harmony.${
|
|
158
|
-
{ operation: `harmony.${
|
|
167
|
+
`harmony.${name} must return ${kind === 'text' ? 'a string' : 'an object'} modResults.`,
|
|
168
|
+
{ operation: `harmony.${name}.write` }
|
|
159
169
|
);
|
|
160
170
|
}
|
|
161
171
|
}
|
|
162
172
|
|
|
163
|
-
function withFileProvider(config: ExpoConfig,
|
|
173
|
+
function withFileProvider(config: ExpoConfig, name: FileModName): ExpoConfig {
|
|
164
174
|
return withBaseMod<FileResult>(config, {
|
|
165
175
|
platform: 'harmony' as ModPlatform,
|
|
166
|
-
mod:
|
|
176
|
+
mod: name,
|
|
167
177
|
isProvider: true,
|
|
168
|
-
isIntrospective: JsonMods.has(
|
|
169
|
-
saveToInternal: JsonMods.has(
|
|
178
|
+
isIntrospective: JsonMods.has(name),
|
|
179
|
+
saveToInternal: JsonMods.has(name),
|
|
170
180
|
async action(value) {
|
|
171
|
-
const { nextMod, ...
|
|
172
|
-
const
|
|
173
|
-
const root =
|
|
174
|
-
const file =
|
|
175
|
-
? await resolveProjectPath(root,
|
|
176
|
-
: await resolveHarmonyPath(root, ManagedPaths[
|
|
177
|
-
const exists = fs.existsSync(file);
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
181
|
+
const { nextMod: next, ...request } = value.modRequest;
|
|
182
|
+
const project = name in ProjectPaths;
|
|
183
|
+
const root = project ? request.projectRoot : request.platformProjectRoot;
|
|
184
|
+
const file = project
|
|
185
|
+
? await resolveProjectPath(root, name as keyof typeof ProjectPaths)
|
|
186
|
+
: await resolveHarmonyPath(root, ManagedPaths[name as keyof typeof ManagedPaths]);
|
|
187
|
+
const exists = !request.ignoreExistingNativeFiles && fs.existsSync(file);
|
|
188
|
+
const template = value._internal?.harmonyTemplateDirectory;
|
|
189
|
+
const input = !exists && !project && typeof template === 'string'
|
|
190
|
+
? await resolveHarmonyPath(template, ManagedPaths[name as keyof typeof ManagedPaths])
|
|
191
|
+
: file;
|
|
192
|
+
|
|
193
|
+
const data = request.ignoreExistingNativeFiles && input === file
|
|
194
|
+
? (JsonMods.has(name) ? {} : '')
|
|
195
|
+
: JsonMods.has(name)
|
|
196
|
+
? await readJson5<HarmonyJson>(input, {}, name)
|
|
197
|
+
: await readText(file);
|
|
198
|
+
|
|
199
|
+
const context = { ...request, modFile: file, modFileExists: exists } as typeof value.modRequest;
|
|
200
|
+
const result = await next!({ ...value, modRequest: context, modResults: data });
|
|
201
|
+
|
|
202
|
+
assertModResults(name, result.modResults, JsonMods.has(name) ? 'json' : 'text');
|
|
186
203
|
|
|
187
204
|
if (!result.modRequest.introspect) {
|
|
188
205
|
if (typeof result.modResults === 'string') {
|
|
@@ -191,7 +208,7 @@ function withFileProvider(config: ExpoConfig, modName: FileModName): ExpoConfig
|
|
|
191
208
|
await writeJson5(file, result.modResults);
|
|
192
209
|
}
|
|
193
210
|
|
|
194
|
-
recordManagedFile(result, file,
|
|
211
|
+
recordManagedFile(result, file, name);
|
|
195
212
|
}
|
|
196
213
|
|
|
197
214
|
return result;
|
|
@@ -202,13 +219,18 @@ function withFileProvider(config: ExpoConfig, modName: FileModName): ExpoConfig
|
|
|
202
219
|
async function readResourceMap(
|
|
203
220
|
root: string,
|
|
204
221
|
entries: Readonly<Record<string, string>>,
|
|
205
|
-
|
|
222
|
+
name: ResourceModName,
|
|
223
|
+
template?: string,
|
|
224
|
+
ignore = false
|
|
206
225
|
): Promise<HarmonyResourceMap> {
|
|
207
226
|
const resources: HarmonyResourceMap = {};
|
|
208
227
|
|
|
209
228
|
for (const [scope, relative] of Object.entries(entries)) {
|
|
210
229
|
const file = await resolveHarmonyPath(root, relative);
|
|
211
|
-
|
|
230
|
+
const fallback = ignore || !fs.existsSync(file);
|
|
231
|
+
const input = fallback && template ? await resolveHarmonyPath(template, relative) : file;
|
|
232
|
+
|
|
233
|
+
resources[scope] = ignore && input === file ? {} : await readJson5<HarmonyJson>(input, {}, name);
|
|
212
234
|
}
|
|
213
235
|
|
|
214
236
|
return resources;
|
|
@@ -221,6 +243,7 @@ async function readMediaMap(root: string): Promise<HarmonyMediaMap> {
|
|
|
221
243
|
const directory = await resolveHarmonyPath(root, relative);
|
|
222
244
|
|
|
223
245
|
media[scope] = {};
|
|
246
|
+
|
|
224
247
|
let names: string[] = [];
|
|
225
248
|
|
|
226
249
|
try {
|
|
@@ -274,6 +297,7 @@ async function writeMediaMap(
|
|
|
274
297
|
{ operation: 'harmony.media.write' }
|
|
275
298
|
);
|
|
276
299
|
}
|
|
300
|
+
|
|
277
301
|
if (!descriptor || typeof descriptor !== 'object' || Array.isArray(descriptor)) {
|
|
278
302
|
throw new HarmonyConfigPluginError(
|
|
279
303
|
'ERR_HARMONY_CONFIG_INVALID',
|
|
@@ -283,16 +307,14 @@ async function writeMediaMap(
|
|
|
283
307
|
}
|
|
284
308
|
|
|
285
309
|
const item = descriptor as Partial<HarmonyMediaDescriptor>;
|
|
286
|
-
|
|
287
|
-
const hasContent = Object.hasOwn(item, 'content');
|
|
288
|
-
|
|
289
|
-
if (hasSource === hasContent) {
|
|
310
|
+
if (Object.hasOwn(item, 'source') === Object.hasOwn(item, 'content')) {
|
|
290
311
|
throw new HarmonyConfigPluginError(
|
|
291
312
|
'ERR_HARMONY_CONFIG_INVALID',
|
|
292
313
|
`Harmony media ${scope}/${name} must define exactly one of source or content.`,
|
|
293
314
|
{ operation: 'harmony.media.write' }
|
|
294
315
|
);
|
|
295
316
|
}
|
|
317
|
+
|
|
296
318
|
if (item.replaceBase !== undefined && typeof item.replaceBase !== 'boolean') {
|
|
297
319
|
throw new HarmonyConfigPluginError(
|
|
298
320
|
'ERR_HARMONY_CONFIG_INVALID',
|
|
@@ -303,7 +325,7 @@ async function writeMediaMap(
|
|
|
303
325
|
|
|
304
326
|
let content: string | Uint8Array;
|
|
305
327
|
|
|
306
|
-
if (
|
|
328
|
+
if (Object.hasOwn(item, 'source')) {
|
|
307
329
|
if (typeof item.source !== 'string' || item.source.length === 0) {
|
|
308
330
|
throw new HarmonyConfigPluginError(
|
|
309
331
|
'ERR_HARMONY_CONFIG_INVALID',
|
|
@@ -334,11 +356,9 @@ async function writeMediaMap(
|
|
|
334
356
|
}
|
|
335
357
|
}
|
|
336
358
|
|
|
337
|
-
// Resolve and read every desired input before removing stale resources. A
|
|
338
|
-
// malformed descriptor or missing source therefore cannot partially mutate
|
|
339
|
-
// an otherwise valid generated project.
|
|
340
359
|
for (const [scope, names] of Object.entries(previous)) {
|
|
341
360
|
if (!(scope in ResourcePaths.media)) continue;
|
|
361
|
+
|
|
342
362
|
const directory = await resolveHarmonyPath(
|
|
343
363
|
root,
|
|
344
364
|
ResourcePaths.media[scope as keyof typeof ResourcePaths.media]
|
|
@@ -360,9 +380,9 @@ async function writeMediaMap(
|
|
|
360
380
|
if (replaceBase) {
|
|
361
381
|
const base = path.parse(name).name;
|
|
362
382
|
|
|
363
|
-
for (const
|
|
364
|
-
if (path.parse(
|
|
365
|
-
await fs.promises.rm(path.join(directory,
|
|
383
|
+
for (const entry of await fs.promises.readdir(directory)) {
|
|
384
|
+
if (path.parse(entry).name === base && entry !== name) {
|
|
385
|
+
await fs.promises.rm(path.join(directory, entry), { force: true });
|
|
366
386
|
}
|
|
367
387
|
}
|
|
368
388
|
}
|
|
@@ -374,53 +394,56 @@ async function writeMediaMap(
|
|
|
374
394
|
}
|
|
375
395
|
}
|
|
376
396
|
|
|
377
|
-
function withResourceProvider(config: ExpoConfig,
|
|
378
|
-
const
|
|
397
|
+
function withResourceProvider(config: ExpoConfig, name: ResourceModName): ExpoConfig {
|
|
398
|
+
const introspective = name !== 'media';
|
|
379
399
|
|
|
380
400
|
return withBaseMod<ResourceResult>(config, {
|
|
381
401
|
platform: 'harmony' as ModPlatform,
|
|
382
|
-
mod:
|
|
402
|
+
mod: name,
|
|
383
403
|
isProvider: true,
|
|
384
|
-
isIntrospective,
|
|
385
|
-
saveToInternal:
|
|
404
|
+
isIntrospective: introspective,
|
|
405
|
+
saveToInternal: introspective,
|
|
386
406
|
async action(value) {
|
|
387
|
-
const { nextMod, ...
|
|
388
|
-
const root =
|
|
389
|
-
const data =
|
|
390
|
-
?
|
|
391
|
-
|
|
392
|
-
|
|
407
|
+
const { nextMod: next, ...request } = value.modRequest;
|
|
408
|
+
const root = request.platformProjectRoot;
|
|
409
|
+
const data = name === 'media'
|
|
410
|
+
? (request.ignoreExistingNativeFiles
|
|
411
|
+
? Object.fromEntries(Object.keys(ResourcePaths.media).map(scope => [scope, {}]))
|
|
412
|
+
: await readMediaMap(root))
|
|
413
|
+
: await readResourceMap(
|
|
414
|
+
root, ResourcePaths[name], name,
|
|
415
|
+
value._internal?.harmonyTemplateDirectory, request.ignoreExistingNativeFiles
|
|
416
|
+
);
|
|
417
|
+
const previous = name === 'media'
|
|
393
418
|
? Object.fromEntries(
|
|
394
419
|
Object.entries(data).map(([scope, files]) => [scope, Object.keys(files)])
|
|
395
420
|
)
|
|
396
421
|
: {};
|
|
397
422
|
|
|
398
|
-
const result = await
|
|
423
|
+
const result = await next!({ ...value, modRequest: request, modResults: data });
|
|
399
424
|
|
|
400
|
-
assertModResults(
|
|
425
|
+
assertModResults(name, result.modResults, 'resource');
|
|
401
426
|
|
|
402
427
|
if (!result.modRequest.introspect) {
|
|
403
|
-
if (
|
|
428
|
+
if (name === 'media') {
|
|
404
429
|
await writeMediaMap(root, result.modResults as HarmonyMediaMap, result, previous);
|
|
405
430
|
} else {
|
|
406
|
-
const paths = ResourcePaths[
|
|
431
|
+
const paths = ResourcePaths[name];
|
|
407
432
|
|
|
408
433
|
for (const [scope, resource] of Object.entries(result.modResults)) {
|
|
409
434
|
if (!(scope in paths)) continue;
|
|
410
435
|
|
|
411
|
-
// Harmony's resource compiler requires the JSON root to contain
|
|
412
|
-
// exactly one resource-kind member. An empty scope serialized as
|
|
413
|
-
// `{}` is invalid, so omit it until a plugin contributes content.
|
|
414
436
|
if (!resource || typeof resource !== 'object' || Array.isArray(resource)) {
|
|
415
437
|
throw new HarmonyConfigPluginError(
|
|
416
438
|
'ERR_HARMONY_CONFIG_INVALID',
|
|
417
|
-
`Harmony ${
|
|
418
|
-
{ operation: `harmony.${
|
|
439
|
+
`Harmony ${name} scope ${scope} must be an object.`,
|
|
440
|
+
{ operation: `harmony.${name}.write` }
|
|
419
441
|
);
|
|
420
442
|
}
|
|
421
443
|
|
|
422
444
|
const file = await resolveHarmonyPath(root, paths[scope as keyof typeof paths]);
|
|
423
445
|
|
|
446
|
+
// Harmony's resource compiler rejects an empty JSON root.
|
|
424
447
|
if (Object.keys(resource).length === 0) {
|
|
425
448
|
await fs.promises.rm(file, { force: true });
|
|
426
449
|
|
|
@@ -428,7 +451,7 @@ function withResourceProvider(config: ExpoConfig, modName: ResourceModName): Exp
|
|
|
428
451
|
}
|
|
429
452
|
|
|
430
453
|
await writeJson5(file, resource);
|
|
431
|
-
recordManagedFile(result, file,
|
|
454
|
+
recordManagedFile(result, file, name);
|
|
432
455
|
}
|
|
433
456
|
}
|
|
434
457
|
}
|
|
@@ -438,158 +461,187 @@ function withResourceProvider(config: ExpoConfig, modName: ResourceModName): Exp
|
|
|
438
461
|
});
|
|
439
462
|
}
|
|
440
463
|
|
|
441
|
-
function withVirtualProvider(config: ExpoConfig,
|
|
464
|
+
function withVirtualProvider(config: ExpoConfig, name: AnyModName): ExpoConfig {
|
|
442
465
|
return withBaseMod<null>(config, {
|
|
443
466
|
platform: 'harmony' as ModPlatform,
|
|
444
|
-
mod:
|
|
467
|
+
mod: name,
|
|
445
468
|
isProvider: true,
|
|
469
|
+
isIntrospective: name === 'prepare',
|
|
446
470
|
async action(value) {
|
|
447
|
-
const { nextMod, ...
|
|
448
|
-
|
|
449
|
-
return nextMod!({ ...value, modRequest, modResults: null });
|
|
471
|
+
const { nextMod: next, ...request } = value.modRequest;
|
|
472
|
+
return next!({ ...value, modRequest: request, modResults: null });
|
|
450
473
|
},
|
|
451
474
|
});
|
|
452
475
|
}
|
|
453
476
|
|
|
454
|
-
function withProvider(config: ExpoConfig,
|
|
477
|
+
function withProvider(config: ExpoConfig, name: AnyModName): ExpoConfig {
|
|
455
478
|
const actions: HarmonyModAction[] = [];
|
|
456
479
|
|
|
457
480
|
config = withMod(config, {
|
|
458
481
|
platform: 'harmony' as ModPlatform,
|
|
459
|
-
mod:
|
|
482
|
+
mod: name,
|
|
460
483
|
async action(value) {
|
|
461
484
|
let result = value;
|
|
462
485
|
|
|
463
|
-
//
|
|
464
|
-
// that ordering for Harmony plugins registered after the provider.
|
|
486
|
+
// Late mods must follow Expo's last-registered-first order.
|
|
465
487
|
for (let index = actions.length - 1; index >= 0; index -= 1) {
|
|
466
|
-
result = await actions[index](result);
|
|
488
|
+
result = await actions[index](result as unknown as HarmonyModConfig<unknown>) as unknown as typeof result;
|
|
467
489
|
}
|
|
468
490
|
|
|
469
491
|
return result;
|
|
470
492
|
},
|
|
471
493
|
});
|
|
472
494
|
|
|
473
|
-
if (JsonMods.has(
|
|
474
|
-
config = withFileProvider(config,
|
|
475
|
-
} else if (ResourceMods.has(
|
|
476
|
-
config = withResourceProvider(config,
|
|
477
|
-
} else if (VirtualMods.has(
|
|
478
|
-
config = withVirtualProvider(config,
|
|
495
|
+
if (JsonMods.has(name as FileModName) || TextMods.has(name as FileModName)) {
|
|
496
|
+
config = withFileProvider(config, name as FileModName);
|
|
497
|
+
} else if (ResourceMods.has(name as HarmonyModName)) {
|
|
498
|
+
config = withResourceProvider(config, name as ResourceModName);
|
|
499
|
+
} else if (VirtualMods.has(name)) {
|
|
500
|
+
config = withVirtualProvider(config, name);
|
|
479
501
|
} else {
|
|
480
502
|
throw new HarmonyConfigPluginError(
|
|
481
503
|
'ERR_HARMONY_MOD_NOT_REGISTERED',
|
|
482
|
-
`Unknown Harmony mod: ${
|
|
504
|
+
`Unknown Harmony mod: ${name}`,
|
|
483
505
|
{ operation: 'register-base-mods' }
|
|
484
506
|
);
|
|
485
507
|
}
|
|
486
508
|
|
|
487
509
|
const mods = (config as ExportedConfig).mods as unknown as ModTable | undefined;
|
|
488
|
-
const provider = mods?.harmony?.[
|
|
510
|
+
const provider = mods?.harmony?.[name];
|
|
489
511
|
|
|
490
512
|
if (provider?.isProvider) provider.expoHarmonyLateActions = actions;
|
|
491
513
|
|
|
492
514
|
return config;
|
|
493
515
|
}
|
|
494
516
|
|
|
495
|
-
export function withHarmonyBaseMods(config:
|
|
496
|
-
for (const
|
|
517
|
+
export function withHarmonyBaseMods<Config extends ExpoConfigWithHarmony>(config: Config): Config {
|
|
518
|
+
for (const name of AllModNames) {
|
|
497
519
|
const mods = (config as ExportedConfig).mods as unknown as ModTable;
|
|
498
520
|
|
|
499
|
-
if (!mods?.harmony?.[
|
|
521
|
+
if (!mods?.harmony?.[name]?.isProvider) config = withProvider(config as ExpoConfig, name) as Config;
|
|
500
522
|
}
|
|
501
523
|
|
|
502
524
|
const mods = (config as ExportedConfig).mods as unknown as ModTable;
|
|
503
525
|
const table = mods.harmony!;
|
|
504
526
|
|
|
505
527
|
mods.harmony = Object.fromEntries([
|
|
506
|
-
...
|
|
507
|
-
...Object.entries(table).filter(([name]) => !
|
|
528
|
+
...AllModNames.filter(name => table[name] && name !== 'manifest' && name !== 'patch').map(name => [name, table[name]]),
|
|
529
|
+
...Object.entries(table).filter(([name]) => !AllModNames.includes(name as AnyModName)),
|
|
530
|
+
['patch', table.patch],
|
|
531
|
+
['manifest', table.manifest],
|
|
508
532
|
]);
|
|
509
533
|
|
|
510
534
|
return config;
|
|
511
535
|
}
|
|
512
536
|
|
|
513
|
-
export function withHarmonyMod<T = unknown>(
|
|
514
|
-
config:
|
|
537
|
+
export function withHarmonyMod<T = unknown, Config extends ExpoConfigWithHarmony = ExpoConfigWithHarmony>(
|
|
538
|
+
config: Config,
|
|
515
539
|
tuple: [HarmonyModName, HarmonyModAction<T>]
|
|
516
|
-
):
|
|
540
|
+
): Config {
|
|
517
541
|
if (!Array.isArray(tuple) || tuple.length !== 2) {
|
|
518
542
|
throw new TypeError('withHarmonyMod expects [modName, action].');
|
|
519
543
|
}
|
|
520
544
|
|
|
521
|
-
const [
|
|
522
|
-
if (!HarmonyModNames.includes(
|
|
545
|
+
const [name, action] = tuple;
|
|
546
|
+
if (!HarmonyModNames.includes(name) || typeof action !== 'function') {
|
|
523
547
|
throw new HarmonyConfigPluginError(
|
|
524
548
|
'ERR_HARMONY_MOD_NOT_REGISTERED',
|
|
525
|
-
`Cannot register Harmony mod: ${
|
|
549
|
+
`Cannot register Harmony mod: ${name}`,
|
|
526
550
|
{ operation: 'register-mod' }
|
|
527
551
|
);
|
|
528
552
|
}
|
|
529
553
|
|
|
554
|
+
return registerMod(config, name, action);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export function registerMod<T, Config extends ExpoConfigWithHarmony>(
|
|
558
|
+
config: Config,
|
|
559
|
+
name: string,
|
|
560
|
+
action: HarmonyModAction<T>
|
|
561
|
+
): Config {
|
|
530
562
|
const mods = (config as ExportedConfig).mods as unknown as ModTable | undefined;
|
|
531
|
-
const provider = mods?.harmony?.[
|
|
563
|
+
const provider = mods?.harmony?.[name];
|
|
532
564
|
|
|
533
565
|
if (provider?.isProvider && provider.expoHarmonyLateActions) {
|
|
534
|
-
|
|
566
|
+
// Build an ordinary Expo interceptor on an isolated mod table, preserving
|
|
567
|
+
// its registration stack, error behavior and execution trace for late mods.
|
|
568
|
+
const carrier = withMod<T>({ ...config, mods: {} } as ExpoConfig, {
|
|
569
|
+
platform: 'harmony' as ModPlatform,
|
|
570
|
+
mod: name,
|
|
571
|
+
action: action as unknown as Parameters<typeof withMod<T>>[1]['action'],
|
|
572
|
+
});
|
|
573
|
+
const interceptor = (carrier.mods as unknown as Record<string, Record<string, HarmonyModAction>>).harmony[name];
|
|
574
|
+
|
|
575
|
+
provider.expoHarmonyLateActions.push(interceptor);
|
|
576
|
+
|
|
535
577
|
return config;
|
|
536
578
|
}
|
|
537
579
|
|
|
538
|
-
return withMod<T>(config
|
|
580
|
+
return withMod<T>(config as ExpoConfig, {
|
|
581
|
+
platform: 'harmony' as ModPlatform,
|
|
582
|
+
mod: name,
|
|
583
|
+
action: action as unknown as Parameters<typeof withMod<T>>[1]['action'],
|
|
584
|
+
}) as Config;
|
|
539
585
|
}
|
|
540
586
|
|
|
541
|
-
export const withReactNativeConfig:
|
|
587
|
+
export const withReactNativeConfig: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
542
588
|
= (config, action) => withHarmonyMod(config, ['reactNativeConfig', action]);
|
|
543
|
-
export const withAppJson:
|
|
589
|
+
export const withAppJson: HarmonyConfigPlugin<HarmonyModAction<HarmonyJson>>
|
|
544
590
|
= (config, action) => withHarmonyMod(config, ['appJson', action]);
|
|
545
|
-
export const withProjectBuildProfile:
|
|
591
|
+
export const withProjectBuildProfile: HarmonyConfigPlugin<HarmonyModAction<HarmonyJson>>
|
|
546
592
|
= (config, action) => withHarmonyMod(config, ['projectBuildProfile', action]);
|
|
547
|
-
export const withRootOhPackage:
|
|
593
|
+
export const withRootOhPackage: HarmonyConfigPlugin<HarmonyModAction<HarmonyJson>>
|
|
548
594
|
= (config, action) => withHarmonyMod(config, ['rootOhPackage', action]);
|
|
549
|
-
export const withRootHvigor:
|
|
595
|
+
export const withRootHvigor: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
550
596
|
= (config, action) => withHarmonyMod(config, ['rootHvigor', action]);
|
|
551
|
-
export const withNativeInputsStamp:
|
|
552
|
-
= (config, action) =>
|
|
553
|
-
export const withHvigorConfig:
|
|
597
|
+
export const withNativeInputsStamp: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
598
|
+
= (config, action) => registerMod(config, 'nativeInputsStamp', action);
|
|
599
|
+
export const withHvigorConfig: HarmonyConfigPlugin<HarmonyModAction<HarmonyJson>>
|
|
554
600
|
= (config, action) => withHarmonyMod(config, ['hvigorConfig', action]);
|
|
555
|
-
export const withEntryBuildProfile:
|
|
601
|
+
export const withEntryBuildProfile: HarmonyConfigPlugin<HarmonyModAction<HarmonyJson>>
|
|
556
602
|
= (config, action) => withHarmonyMod(config, ['entryBuildProfile', action]);
|
|
557
|
-
export const withEntryOhPackage:
|
|
603
|
+
export const withEntryOhPackage: HarmonyConfigPlugin<HarmonyModAction<HarmonyJson>>
|
|
558
604
|
= (config, action) => withHarmonyMod(config, ['entryOhPackage', action]);
|
|
559
|
-
export const withEntryHvigor:
|
|
605
|
+
export const withEntryHvigor: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
560
606
|
= (config, action) => withHarmonyMod(config, ['entryHvigor', action]);
|
|
561
|
-
export const withModuleJson:
|
|
607
|
+
export const withModuleJson: HarmonyConfigPlugin<HarmonyModAction<HarmonyModuleJson>>
|
|
562
608
|
= (config, action) => withHarmonyMod(config, ['moduleJson', action]);
|
|
563
|
-
export const withStrings:
|
|
609
|
+
export const withStrings: HarmonyConfigPlugin<HarmonyModAction<HarmonyResourceMap>>
|
|
564
610
|
= (config, action) => withHarmonyMod(config, ['strings', action]);
|
|
565
|
-
export const withColors:
|
|
611
|
+
export const withColors: HarmonyConfigPlugin<HarmonyModAction<HarmonyResourceMap>>
|
|
566
612
|
= (config, action) => withHarmonyMod(config, ['colors', action]);
|
|
567
|
-
export const withMedia:
|
|
613
|
+
export const withMedia: HarmonyConfigPlugin<HarmonyModAction<HarmonyMediaMap>>
|
|
568
614
|
= (config, action) => withHarmonyMod(config, ['media', action]);
|
|
569
|
-
export const withProfiles:
|
|
615
|
+
export const withProfiles: HarmonyConfigPlugin<HarmonyModAction<HarmonyJson>>
|
|
570
616
|
= (config, action) => withHarmonyMod(config, ['profiles', action]);
|
|
571
|
-
export const
|
|
617
|
+
export const withAbilityStage: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
618
|
+
= (config, action) => withHarmonyMod(config, ['abilityStage', action]);
|
|
619
|
+
export const withEntryAbility: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
572
620
|
= (config, action) => withHarmonyMod(config, ['entryAbility', action]);
|
|
573
|
-
export const withIndexPage:
|
|
621
|
+
export const withIndexPage: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
574
622
|
= (config, action) => withHarmonyMod(config, ['indexPage', action]);
|
|
575
|
-
export const withWorker:
|
|
623
|
+
export const withWorker: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
576
624
|
= (config, action) => withHarmonyMod(config, ['worker', action]);
|
|
577
|
-
export const withArkTSPackageProvider:
|
|
625
|
+
export const withArkTSPackageProvider: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
578
626
|
= (config, action) => withHarmonyMod(config, ['arktsPackageProvider', action]);
|
|
579
|
-
export const withCppPackageProvider:
|
|
627
|
+
export const withCppPackageProvider: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
580
628
|
= (config, action) => withHarmonyMod(config, ['cppPackageProvider', action]);
|
|
581
|
-
export const withCMakeLists:
|
|
629
|
+
export const withCMakeLists: HarmonyConfigPlugin<HarmonyModAction<string>>
|
|
582
630
|
= (config, action) => withHarmonyMod(config, ['cmakeLists', action]);
|
|
583
|
-
export const withHarmonyAutolinking:
|
|
631
|
+
export const withHarmonyAutolinking: HarmonyConfigPlugin<HarmonyModAction<null>>
|
|
584
632
|
= (config, action) => withHarmonyMod(config, ['autolinking', action]);
|
|
585
|
-
export const withCngManifest:
|
|
586
|
-
= (config, action) =>
|
|
587
|
-
export const
|
|
633
|
+
export const withCngManifest: HarmonyConfigPlugin<HarmonyModAction<null>>
|
|
634
|
+
= (config, action) => registerMod(config, 'manifest', action);
|
|
635
|
+
export const withPreparation: HarmonyConfigPlugin<HarmonyModAction<null>>
|
|
636
|
+
= (config, action) => registerMod(config, 'prepare', action);
|
|
637
|
+
export const withProjectPatch: HarmonyConfigPlugin<HarmonyModAction<null>>
|
|
638
|
+
= (config, action) => registerMod(config, 'patch', action);
|
|
639
|
+
export const withHarmonyDangerousMod: HarmonyConfigPlugin<HarmonyModAction<null>>
|
|
588
640
|
= (config, action) => withHarmonyMod(config, ['dangerous', action]);
|
|
589
641
|
|
|
590
|
-
export const withHarmonyResources:
|
|
591
|
-
for (const
|
|
592
|
-
withHarmonyMod(config, [
|
|
642
|
+
export const withHarmonyResources: HarmonyConfigPlugin<HarmonyModAction<unknown>> = (config, action) => {
|
|
643
|
+
for (const name of ResourceModNames) {
|
|
644
|
+
withHarmonyMod(config, [name, action]);
|
|
593
645
|
}
|
|
594
646
|
|
|
595
647
|
return config;
|
package/src/nativeInputs.ts
CHANGED
|
@@ -78,7 +78,6 @@ function fingerprintHarmonyNativeInputsSync(
|
|
|
78
78
|
const files = findLocalHars(root, manifest);
|
|
79
79
|
|
|
80
80
|
const hash = crypto.createHash('sha256');
|
|
81
|
-
|
|
82
81
|
hash.update(`expo-harmony-native-dependencies-v${HarmonyNativeInputsFingerprintVersion}\0`);
|
|
83
82
|
hash.update(Uint8Array.from(data));
|
|
84
83
|
if (lock) hash.update(lock);
|