@expo/eas-json 0.37.0 → 0.39.0

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 (42) hide show
  1. package/build/build/resolver.d.ts +8 -0
  2. package/build/build/resolver.js +67 -0
  3. package/build/build/schema.d.ts +2 -0
  4. package/build/{EasJsonSchema.js → build/schema.js} +16 -55
  5. package/build/{EasBuild.types.d.ts → build/types.d.ts} +6 -1
  6. package/build/{EasJson.types.js → build/types.js} +0 -0
  7. package/build/errors.d.ts +4 -0
  8. package/build/errors.js +7 -1
  9. package/build/index.d.ts +5 -4
  10. package/build/index.js +10 -8
  11. package/build/reader.d.ts +15 -0
  12. package/build/reader.js +75 -0
  13. package/build/schema.d.ts +2 -0
  14. package/build/schema.js +15 -0
  15. package/build/submit/resolver.d.ts +9 -0
  16. package/build/submit/resolver.js +72 -0
  17. package/build/submit/schema.d.ts +4 -0
  18. package/build/submit/schema.js +35 -0
  19. package/build/{EasSubmit.types.d.ts → submit/types.d.ts} +6 -1
  20. package/build/{EasSubmit.types.js → submit/types.js} +1 -0
  21. package/build/types.d.ts +20 -0
  22. package/build/{EasBuild.types.js → types.js} +0 -0
  23. package/package.json +5 -4
  24. package/src/__tests__/{EasJsonReader-build-test.ts → reader-build-test.ts} +49 -51
  25. package/src/__tests__/{EasJsonReader-submit-test.ts → reader-submit-test.ts} +49 -7
  26. package/src/build/resolver.ts +97 -0
  27. package/src/{EasJsonSchema.ts → build/schema.ts} +14 -60
  28. package/src/{EasBuild.types.ts → build/types.ts} +7 -5
  29. package/src/errors.ts +4 -0
  30. package/src/index.ts +6 -13
  31. package/src/reader.ts +87 -0
  32. package/src/schema.ts +13 -0
  33. package/src/submit/resolver.ts +114 -0
  34. package/src/submit/schema.ts +35 -0
  35. package/src/{EasSubmit.types.ts → submit/types.ts} +7 -7
  36. package/src/types.ts +21 -0
  37. package/build/EasJson.types.d.ts +0 -29
  38. package/build/EasJsonReader.d.ts +0 -39
  39. package/build/EasJsonReader.js +0 -208
  40. package/build/EasJsonSchema.d.ts +0 -6
  41. package/src/EasJson.types.ts +0 -31
  42. package/src/EasJsonReader.ts +0 -265
@@ -1,265 +0,0 @@
1
- import { Platform } from '@expo/eas-build-job';
2
- import JsonFile from '@expo/json-file';
3
- import envString from 'env-string';
4
- import fs from 'fs-extra';
5
- import path from 'path';
6
-
7
- import { BuildProfile } from './EasBuild.types';
8
- import { CliConfig, CredentialsSource, EasJson, RawBuildProfile } from './EasJson.types';
9
- import {
10
- AndroidSubmitProfileSchema,
11
- CliConfigSchema,
12
- EasJsonSchema,
13
- IosSubmitProfileSchema,
14
- MinimalEasJsonSchema,
15
- } from './EasJsonSchema';
16
- import {
17
- AndroidSubmitProfileFieldsToEvaluate,
18
- IosSubmitProfileFieldsToEvaluate,
19
- SubmitProfile,
20
- } from './EasSubmit.types';
21
- import { InvalidEasJsonError, MissingEasJsonError } from './errors';
22
-
23
- interface EasJsonPreValidation {
24
- cli?: object;
25
- build: { [profile: string]: object };
26
- submit?: { [profile: string]: object };
27
- }
28
-
29
- const defaults = {
30
- distribution: 'store',
31
- credentialsSource: CredentialsSource.REMOTE,
32
- } as const;
33
-
34
- type LoggerFn = (...args: any[]) => void;
35
-
36
- interface Logger {
37
- log: LoggerFn;
38
- warn: LoggerFn;
39
- }
40
-
41
- export class EasJsonReader {
42
- private static log?: Logger;
43
-
44
- public static formatEasJsonPath(projectDir: string): string {
45
- return path.join(projectDir, 'eas.json');
46
- }
47
-
48
- public static setLog(log: Logger): void {
49
- this.log = log;
50
- }
51
-
52
- constructor(private projectDir: string) {}
53
-
54
- public async getBuildProfileNamesAsync(): Promise<string[]> {
55
- const easJson = await this.readRawAsync();
56
- return Object.keys(easJson?.build ?? {});
57
- }
58
-
59
- public async getCliConfigAsync(): Promise<CliConfig | null> {
60
- try {
61
- const easJson = await this.readRawAsync();
62
- if (!easJson.cli) {
63
- return null;
64
- }
65
- const { value, error } = CliConfigSchema.validate(easJson.cli, {
66
- allowUnknown: false,
67
- convert: true,
68
- abortEarly: false,
69
- });
70
- if (error) {
71
- throw new Error(`"cli" field in eas.json is not valid [${error.toString()}]`);
72
- }
73
- return value as CliConfig;
74
- } catch (err: any) {
75
- if (err instanceof MissingEasJsonError) {
76
- return null;
77
- }
78
- throw err;
79
- }
80
- }
81
-
82
- public async getSubmitProfileNamesAsync({ throwIfEasJsonDoesNotExist = true } = {}): Promise<
83
- string[]
84
- > {
85
- try {
86
- const easJson = await this.readRawAsync();
87
- return Object.keys(easJson?.submit ?? {});
88
- } catch (err: any) {
89
- if (!throwIfEasJsonDoesNotExist && err.code === 'ENOENT') {
90
- return [];
91
- } else {
92
- throw err;
93
- }
94
- }
95
- }
96
-
97
- public async readBuildProfileAsync<T extends Platform>(
98
- platform: T,
99
- profileName: string
100
- ): Promise<BuildProfile<T>> {
101
- const easJson = await this.readAndValidateAsync();
102
- this.ensureBuildProfileExists(easJson, profileName);
103
- const {
104
- android: resolvedAndroidSpecificValues,
105
- ios: resolvedIosSpecificValues,
106
- ...resolvedProfile
107
- } = this.resolveBuildProfile(easJson, profileName);
108
- if (platform === Platform.ANDROID) {
109
- const profileWithoutDefaults = profileMerge(
110
- resolvedProfile,
111
- resolvedAndroidSpecificValues ?? {}
112
- );
113
- return profileMerge(defaults, profileWithoutDefaults) as BuildProfile<T>;
114
- } else if (platform === Platform.IOS) {
115
- const profileWithoutDefaults = profileMerge(resolvedProfile, resolvedIosSpecificValues ?? {});
116
- return profileMerge(defaults, profileWithoutDefaults) as BuildProfile<T>;
117
- } else {
118
- throw new Error(`Unknown platform ${platform}`);
119
- }
120
- }
121
-
122
- public async readSubmitProfileAsync<T extends Platform>(
123
- platform: T,
124
- profileNameArg?: string
125
- ): Promise<SubmitProfile<T>> {
126
- let profileName = profileNameArg;
127
-
128
- if (!profileName) {
129
- const profileNames = await this.getSubmitProfileNamesAsync({
130
- throwIfEasJsonDoesNotExist: false,
131
- });
132
-
133
- if (profileNames.includes('production')) {
134
- profileName = 'production';
135
- } else if (profileNames.includes('release')) {
136
- profileName = 'release';
137
- } else {
138
- return getDefaultSubmitProfile(platform);
139
- }
140
- }
141
-
142
- const easJson = await this.readAndValidateAsync();
143
- const profile = easJson?.submit?.[profileName];
144
- if (!profile) {
145
- throw new Error(`There is no submit profile named ${profileName} in eas.json`);
146
- }
147
- const platformProfile = profile[platform];
148
- if (platformProfile) {
149
- return this.evaluateFields(platform, platformProfile as SubmitProfile<T>);
150
- } else {
151
- return getDefaultSubmitProfile(platform);
152
- }
153
- }
154
-
155
- public async readAndValidateAsync(): Promise<EasJson> {
156
- const easJson = await this.readRawAsync();
157
- const { value, error } = EasJsonSchema.validate(easJson, {
158
- allowUnknown: false,
159
- convert: true,
160
- abortEarly: false,
161
- });
162
-
163
- if (error) {
164
- throw new InvalidEasJsonError(`eas.json is not valid [${error.toString()}]`);
165
- }
166
- return value as EasJson;
167
- }
168
-
169
- public async readRawAsync(): Promise<EasJsonPreValidation> {
170
- try {
171
- const easJsonPath = EasJsonReader.formatEasJsonPath(this.projectDir);
172
- if (!(await fs.pathExists(easJsonPath))) {
173
- throw new MissingEasJsonError(
174
- `An eas.json file could not be found at ${easJsonPath}. You must make one in order to proceed. Learn more at https://expo.fyi/eas-json`
175
- );
176
- }
177
- const rawEasJson = JsonFile.read(easJsonPath);
178
- const { value, error } = MinimalEasJsonSchema.validate(rawEasJson, { abortEarly: false });
179
- if (error) {
180
- throw new InvalidEasJsonError(`eas.json is not valid [${error.toString()}]`);
181
- }
182
- return value;
183
- } catch (err: any) {
184
- if (err.code === 'EJSONPARSE') {
185
- err.message = `Found invalid JSON in eas.json. ${err.message}`;
186
- }
187
- throw err;
188
- }
189
- }
190
-
191
- private resolveBuildProfile(
192
- easJson: EasJson,
193
- profileName: string,
194
- depth: number = 0
195
- ): RawBuildProfile {
196
- if (depth >= 2) {
197
- throw new Error(
198
- 'Too long chain of build profile extensions, make sure "extends" keys do not make a cycle'
199
- );
200
- }
201
- const buildProfile = easJson.build[profileName];
202
- if (!buildProfile) {
203
- throw new Error(`There is no build profile named ${profileName} in eas.json`);
204
- }
205
- const { extends: baseProfileName, ...buildProfileRest } = buildProfile;
206
- if (baseProfileName) {
207
- return profileMerge(
208
- this.resolveBuildProfile(easJson, baseProfileName, depth + 1),
209
- buildProfileRest
210
- );
211
- } else {
212
- return buildProfileRest;
213
- }
214
- }
215
-
216
- private ensureBuildProfileExists(easJson: EasJson, profileName: string): void {
217
- if (!easJson.build || !easJson.build[profileName]) {
218
- throw new Error(`There is no build profile named ${profileName} in eas.json`);
219
- }
220
- }
221
-
222
- private evaluateFields<T extends Platform>(
223
- platform: T,
224
- profile: SubmitProfile<T>
225
- ): SubmitProfile<T> {
226
- const fields =
227
- platform === Platform.ANDROID
228
- ? AndroidSubmitProfileFieldsToEvaluate
229
- : IosSubmitProfileFieldsToEvaluate;
230
- const evaluatedProfile = { ...profile };
231
- for (const field of fields) {
232
- if (field in evaluatedProfile) {
233
- // @ts-ignore
234
- evaluatedProfile[field] = envString(evaluatedProfile[field], process.env);
235
- }
236
- }
237
- return evaluatedProfile;
238
- }
239
- }
240
-
241
- export function profileMerge(base: RawBuildProfile, update: RawBuildProfile): RawBuildProfile {
242
- const result = {
243
- ...base,
244
- ...update,
245
- };
246
- if (base.env && update.env) {
247
- result.env = {
248
- ...base.env,
249
- ...update.env,
250
- };
251
- }
252
- if (base.android && update.android) {
253
- result.android = profileMerge(base.android, update.android);
254
- }
255
- if (base.ios && update.ios) {
256
- result.ios = profileMerge(base.ios, update.ios);
257
- }
258
- return result;
259
- }
260
-
261
- function getDefaultSubmitProfile<T extends Platform>(platform: T): SubmitProfile<T> {
262
- const Schema =
263
- platform === Platform.ANDROID ? AndroidSubmitProfileSchema : IosSubmitProfileSchema;
264
- return Schema.validate({}, { convert: true }).value;
265
- }