@expo-harmony/prebuild-config 55.0.0-harmony.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/README.md +68 -0
- package/build/index.js +26 -0
- package/package.json +87 -0
- package/src/api/signing.ts +4 -0
- package/src/buildDescriptor.ts +277 -0
- package/src/check.ts +390 -0
- package/src/dependencies.ts +123 -0
- package/src/errors.ts +23 -0
- package/src/generatedFiles.ts +39 -0
- package/src/index.ts +25 -0
- package/src/manifest.ts +303 -0
- package/src/mods/withAutolinkingMods.ts +92 -0
- package/src/mods/withEntryMods.ts +332 -0
- package/src/mods/withPreparationMod.ts +85 -0
- package/src/mods/withProjectMods.ts +258 -0
- package/src/mods/withSourceMods.ts +32 -0
- package/src/native.ts +10 -0
- package/src/packageMetadata.ts +8 -0
- package/src/plugin.ts +7 -0
- package/src/reconcile.ts +70 -0
- package/src/renderers.ts +90 -0
- package/src/signing.ts +251 -0
- package/src/stale.ts +103 -0
- package/src/template.ts +172 -0
- package/src/withHarmonyPrebuildConfig.ts +47 -0
- package/tsconfig.json +20 -0
package/src/template.ts
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
HarmonyPlatformDirectory,
|
|
7
|
+
HarmonyTemplateMarker,
|
|
8
|
+
} from './buildDescriptor';
|
|
9
|
+
import { HarmonyPrebuildError } from './errors';
|
|
10
|
+
|
|
11
|
+
const PACKAGE = '@expo-harmony/template';
|
|
12
|
+
const ROOT_ENV = 'EXPO_HARMONY_TEMPLATE_ROOT';
|
|
13
|
+
const TEMPLATE_SCHEMA_VERSION = 2;
|
|
14
|
+
const TEMPLATE_PLACEHOLDERS = Object.freeze({
|
|
15
|
+
abilityName: '__EXPO_HARMONY_ABILITY_NAME__',
|
|
16
|
+
appLabel: '__EXPO_HARMONY_APP_LABEL__',
|
|
17
|
+
bundlePath: '__EXPO_HARMONY_BUNDLE_PATH__',
|
|
18
|
+
});
|
|
19
|
+
const resolveModule = createRequire(__filename).resolve;
|
|
20
|
+
|
|
21
|
+
interface Template {
|
|
22
|
+
readonly marker: string;
|
|
23
|
+
readonly schemaVersion: typeof TEMPLATE_SCHEMA_VERSION;
|
|
24
|
+
readonly json: string;
|
|
25
|
+
readonly root: string;
|
|
26
|
+
readonly harmony: string;
|
|
27
|
+
readonly version: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let bundled: Template | undefined;
|
|
31
|
+
let selected: Template | undefined;
|
|
32
|
+
let selectedRoot: string | undefined;
|
|
33
|
+
|
|
34
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
35
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function readSchema(marker: string): typeof TEMPLATE_SCHEMA_VERSION {
|
|
39
|
+
let schema: unknown;
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
schema = JSON.parse(fs.readFileSync(marker, 'utf8'));
|
|
43
|
+
} catch (cause) {
|
|
44
|
+
throw new HarmonyPrebuildError(
|
|
45
|
+
'ERR_HARMONY_TEMPLATE_INVALID',
|
|
46
|
+
`Cannot read the Harmony template schema at ${marker}.`,
|
|
47
|
+
{ cause, file: marker, operation: 'resolve-template' }
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!isRecord(schema) || schema.schemaVersion !== TEMPLATE_SCHEMA_VERSION) {
|
|
52
|
+
throw new HarmonyPrebuildError(
|
|
53
|
+
'ERR_HARMONY_TEMPLATE_INVALID',
|
|
54
|
+
`Unsupported Harmony template schema: ${isRecord(schema) ? schema.schemaVersion : 'invalid'}.`,
|
|
55
|
+
{ file: marker, operation: 'resolve-template' }
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const placeholders = schema.placeholders;
|
|
60
|
+
const names = Object.keys(TEMPLATE_PLACEHOLDERS) as Array<keyof typeof TEMPLATE_PLACEHOLDERS>;
|
|
61
|
+
|
|
62
|
+
if (!isRecord(placeholders)
|
|
63
|
+
|| Object.keys(placeholders).length !== names.length
|
|
64
|
+
|| names.some(name => placeholders[name] !== TEMPLATE_PLACEHOLDERS[name])) {
|
|
65
|
+
throw new HarmonyPrebuildError(
|
|
66
|
+
'ERR_HARMONY_TEMPLATE_INVALID',
|
|
67
|
+
'Harmony template schema has an invalid placeholder contract.',
|
|
68
|
+
{ file: marker, operation: 'resolve-template' }
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return TEMPLATE_SCHEMA_VERSION;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function read(input: string): Template {
|
|
76
|
+
if (!path.isAbsolute(input)) {
|
|
77
|
+
throw new HarmonyPrebuildError(
|
|
78
|
+
'ERR_HARMONY_TEMPLATE_INVALID',
|
|
79
|
+
`${ROOT_ENV} must be an absolute path.`,
|
|
80
|
+
{ operation: 'resolve-template' }
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let root: string;
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
root = fs.realpathSync(input);
|
|
88
|
+
} catch (cause) {
|
|
89
|
+
throw new HarmonyPrebuildError(
|
|
90
|
+
'ERR_HARMONY_TEMPLATE_INVALID',
|
|
91
|
+
`Cannot access the selected Harmony template at ${input}.`,
|
|
92
|
+
{ cause, file: input, operation: 'resolve-template' }
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const json = path.join(root, 'package.json');
|
|
97
|
+
|
|
98
|
+
let pkg;
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
pkg = JSON.parse(fs.readFileSync(json, 'utf8'));
|
|
102
|
+
} catch (cause) {
|
|
103
|
+
throw new HarmonyPrebuildError(
|
|
104
|
+
'ERR_HARMONY_TEMPLATE_INVALID',
|
|
105
|
+
`Cannot read the selected Harmony template package at ${root}.`,
|
|
106
|
+
{ cause, file: json, operation: 'resolve-template' }
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (pkg.name !== PACKAGE || typeof pkg.version !== 'string' || !pkg.version) {
|
|
111
|
+
throw new HarmonyPrebuildError(
|
|
112
|
+
'ERR_HARMONY_TEMPLATE_INVALID',
|
|
113
|
+
`The selected template must be a versioned ${PACKAGE} package.`,
|
|
114
|
+
{ file: json, operation: 'resolve-template' }
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const harmony = path.join(root, HarmonyPlatformDirectory);
|
|
119
|
+
const marker = path.join(harmony, HarmonyTemplateMarker);
|
|
120
|
+
const schemaVersion = readSchema(marker);
|
|
121
|
+
|
|
122
|
+
return Object.freeze({
|
|
123
|
+
marker,
|
|
124
|
+
schemaVersion,
|
|
125
|
+
json,
|
|
126
|
+
root,
|
|
127
|
+
harmony,
|
|
128
|
+
version: pkg.version,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function resolveBundled(): Template {
|
|
133
|
+
if (bundled) return bundled;
|
|
134
|
+
|
|
135
|
+
let json: string;
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
json = resolveModule(`${PACKAGE}/package.json`);
|
|
139
|
+
} catch (cause) {
|
|
140
|
+
throw new HarmonyPrebuildError(
|
|
141
|
+
'ERR_HARMONY_TEMPLATE_INVALID',
|
|
142
|
+
`Unable to resolve the ${PACKAGE} declared by @expo-harmony/prebuild-config.`,
|
|
143
|
+
{ cause, operation: 'resolve-template' }
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
bundled = read(path.dirname(json));
|
|
148
|
+
|
|
149
|
+
return bundled;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function resolve(): Template {
|
|
153
|
+
const root = process.env[ROOT_ENV];
|
|
154
|
+
|
|
155
|
+
if (!root) return resolveBundled();
|
|
156
|
+
|
|
157
|
+
if (selected && selectedRoot === root) return selected;
|
|
158
|
+
|
|
159
|
+
selected = read(root);
|
|
160
|
+
selectedRoot = root;
|
|
161
|
+
|
|
162
|
+
return selected;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export {
|
|
166
|
+
ROOT_ENV,
|
|
167
|
+
TEMPLATE_PLACEHOLDERS,
|
|
168
|
+
TEMPLATE_SCHEMA_VERSION,
|
|
169
|
+
resolve,
|
|
170
|
+
resolveBundled,
|
|
171
|
+
};
|
|
172
|
+
export type { Template };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeHarmonyConfig,
|
|
3
|
+
withHarmonyBaseMods,
|
|
4
|
+
type NormalizedHarmonyConfig,
|
|
5
|
+
} from '@expo-harmony/config-plugins';
|
|
6
|
+
import type { ConfigPlugin } from '@expo/config-plugins';
|
|
7
|
+
|
|
8
|
+
import { HarmonyPrebuildError } from './errors';
|
|
9
|
+
import { withAutolinkingMods } from './mods/withAutolinkingMods';
|
|
10
|
+
import { withEntryMods } from './mods/withEntryMods';
|
|
11
|
+
import { withPreparationMod } from './mods/withPreparationMod';
|
|
12
|
+
import { withProjectMods } from './mods/withProjectMods';
|
|
13
|
+
import { withSourceMods } from './mods/withSourceMods';
|
|
14
|
+
|
|
15
|
+
interface HarmonyPrebuildOptions {
|
|
16
|
+
autolinking?: boolean;
|
|
17
|
+
buildType?: 'debug' | 'release';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function applyHarmonyMods(config, harmony: NormalizedHarmonyConfig, options: HarmonyPrebuildOptions) {
|
|
21
|
+
config = withPreparationMod(config, harmony);
|
|
22
|
+
config = withProjectMods(config, harmony);
|
|
23
|
+
config = withEntryMods(config, harmony);
|
|
24
|
+
config = withSourceMods(config, harmony);
|
|
25
|
+
config = withAutolinkingMods(config, harmony, options);
|
|
26
|
+
|
|
27
|
+
return config;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const withHarmonyPrebuildConfig: ConfigPlugin<HarmonyPrebuildOptions> = (config, options = {}) => {
|
|
31
|
+
if (options.autolinking === false) {
|
|
32
|
+
throw new HarmonyPrebuildError(
|
|
33
|
+
'ERR_HARMONY_CONFIG_INVALID',
|
|
34
|
+
'Harmony autolinking cannot be disabled because the generated RNOH and Expo native project requires its outputs.',
|
|
35
|
+
{ operation: 'configure-autolinking' }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const harmony = normalizeHarmonyConfig(config);
|
|
40
|
+
|
|
41
|
+
config = applyHarmonyMods(config, harmony, options);
|
|
42
|
+
|
|
43
|
+
return withHarmonyBaseMods(config);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { withHarmonyPrebuildConfig };
|
|
47
|
+
export type { HarmonyPrebuildOptions };
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"esModuleInterop": true,
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"lib": ["ES2022"],
|
|
6
|
+
"module": "Node16",
|
|
7
|
+
"moduleResolution": "Node16",
|
|
8
|
+
"outDir": "build",
|
|
9
|
+
"rootDir": "src",
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"noImplicitAny": false,
|
|
13
|
+
"strictNullChecks": false,
|
|
14
|
+
"useUnknownInCatchVariables": false,
|
|
15
|
+
"target": "ES2022",
|
|
16
|
+
"types": ["node"]
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*.ts"],
|
|
19
|
+
"exclude": ["build"]
|
|
20
|
+
}
|