Skip to content

Commit

Permalink
fix(eas-cli): update EAS Metadata with new props for App Store 3.6.0 (#…
Browse files Browse the repository at this point in the history
…2671)

* refactor(eas-cli): upgrade eas metadata to support app store 3.6.0 advisory props

* chore(eas-cli): bump `@expo/apple-utils` to `2.1.0`

* fix(eas-cli): update eas metadata json schema

* docs(eas-cli): add changelog entry

* fix(eas-cli): fix typo in config version

* fix(eas-cli): resolve outdated fixtures

* chore(eas-cli): resolve linting issues
  • Loading branch information
byCedric authored Nov 5, 2024
1 parent 433c47b commit 281ae7b
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 54 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ This is the log of notable changes to EAS CLI and related packages.

### 🧹 Chores

- Upgrade EAS Metadata with new properties from App Store. ([#2671](https://github.com/expo/eas-cli/pull/2671) by [@byCedric](https://github.com/byCedric))

## [13.0.0](https://github.com/expo/eas-cli/releases/tag/v13.0.0) - 2024-11-05

### 🛠 Breaking changes
Expand Down
2 changes: 1 addition & 1 deletion packages/eas-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@expo/apple-utils": "2.0.3",
"@expo/apple-utils": "2.1.0",
"@expo/code-signing-certificates": "0.0.5",
"@expo/config": "9.0.4",
"@expo/config-plugins": "8.0.10",
Expand Down
71 changes: 53 additions & 18 deletions packages/eas-cli/schema/metadata-0.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
{
"$schema": "http://json-schema.org/draft-06/schema",
"type": "object",
"properties": {
"configVersion": {
"enum": [0],
"description": "The EAS metadata store configuration version"
},
"apple": {
"$ref": "#/definitions/AppleConfig"
}
},
"additionalProperties": false,
"required": [
"configVersion",
"apple"
],
"definitions": {
"apple": {
"AppleKidsAge": {
Expand Down Expand Up @@ -323,7 +337,8 @@
"gambling",
"unrestrictedWebAccess",
"kidsAgeBand",
"seventeenPlus"
"ageRatingOverride",
"koreaAgeRatingOverride"
],
"defaultSnippets": [
{
Expand All @@ -345,7 +360,9 @@
"gambling": false,
"unrestrictedWebAccess": false,
"kidsAgeBand": null,
"seventeenPlus": false
"ageRatingOverride": "NONE",
"koreaAgeRatingOverride": "NONE",
"lootBox": false
}
},
{
Expand All @@ -367,7 +384,9 @@
"unrestrictedWebAccess": false,
"gambling": false,
"kidsAgeBand": null,
"seventeenPlus": false
"ageRatingOverride": "${13|NONE,SEVENTEEN_PLUS,UNRATED|}",
"koreaAgeRatingOverride": "${14|NONE,FIFTEEN_PLUS,NINETEEN_PLUS|}",
"lootBox": false
}
}
],
Expand Down Expand Up @@ -442,8 +461,24 @@
},
"seventeenPlus": {
"type": "boolean",
"deprecated": true,
"deprecationMessage": "This property is deprecated, use `ageRatingOverride` instead.",
"description": "If your app rates 12+ or lower, and you believe its content may not be suitable for children under 17, you can manually set the age rating to 17+.\n@see https://help.apple.com/app-store-connect/#/dev599d50efb",
"markdownDescription": "If your app rates 12+ or lower, and you believe its content may not be suitable for children under 17, you can manually set the age rating to 17+.\n\n[Learn more](https://help.apple.com/app-store-connect/#/dev599d50efb)"
},
"ageRatingOverride": {
"$ref": "#/definitions/apple/AppleAgeRatingOverride",
"description": "If your app rates 12+ or lower, and you believe its content may not be suitable for children under 17, you can manually set the age rating to 17+.\n\nIf your app will be distributed through alternative app marketplaces or websites in the European Union and you believe your app is [Unrated](https://developer.apple.com/help/app-store-connect/reference/age-ratings), set this to `UNRATED`.\n\n@see https://help.apple.com/app-store-connect/#/dev599d50efb",
"markdownDescription": "If your app rates 12+ or lower, and you believe its content may not be suitable for children under 17, you can manually set the age rating to 17+.\n\nIf your app will be distributed through alternative app marketplaces or websites in the European Union and you believe your app is [Unrated](https://developer.apple.com/help/app-store-connect/reference/age-ratings), set this to `UNRATED`.\n\n[Learn more](https://help.apple.com/app-store-connect/#/dev599d50efb)"
},
"koreaAgeRatingOverride": {
"$ref": "#/definitions/apple/AppleKoreaAgeRatingOverride",
"description": "If your app rates 12+ or lower, and you believe its content may not be suitable for children under 15 or 19, you can manually set the age rating to 15+ or 19+.\n\nIf your app will be distributed through alternative app marketplaces or websites in the European Union and you believe your app is [Unrated](https://developer.apple.com/help/app-store-connect/reference/age-ratings), set this to `UNRATED`.\n\n@see https://help.apple.com/app-store-connect/#/dev599d50efb",
"markdownDescription": "If your app rates 12+ or lower, and you believe its content may not be suitable for children under 15 or 19, you can manually set the age rating to 15+ or 19+.\n\nIf your app will be distributed through alternative app marketplaces or websites in the European Union and you believe your app is [Unrated](https://developer.apple.com/help/app-store-connect/reference/age-ratings), set this to `UNRATED`.\n\n[Learn more](https://help.apple.com/app-store-connect/#/dev599d50efb)"
},
"lootBox": {
"type": "boolean",
"description": "Does your app contain purchasable loot boxes? These virtual containers provide players with in-game items, including functional cards or cosmetic modifications, based on random chance."
}
}
},
Expand Down Expand Up @@ -565,6 +600,20 @@
"maxLength": 4000
}
}
},
"AppleAgeRatingOverride": {
"enum": [
"NONE",
"SEVENTEEN_PLUS",
"UNRATED"
]
},
"AppleKoreaAgeRatingOverride": {
"enum": [
"NONE",
"FIFTEEN_PLUS",
"NINETEEN_PLUS"
]
}
},
"AppleConfig": {
Expand Down Expand Up @@ -775,19 +824,5 @@
}
}
}
},
"properties": {
"configVersion": {
"enum": [0],
"description": "The EAS metadata store configuration version"
},
"apple": {
"$ref": "#/definitions/AppleConfig"
}
},
"additionalProperties": false,
"required": [
"configVersion",
"apple"
]
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { AgeRatingDeclaration, KidsAge, Rating } from '@expo/apple-utils';
import {
AgeRatingDeclaration,
KidsAgeBand,
KoreaRatingOverride,
Rating,
RatingOverride,
} from '@expo/apple-utils';

import { AttributesOf } from '../../../../utils/asc';

// @ts-expect-error: Deprecated property `gamblingAndContests` needs to be deleted from the types
// Note, both `seventeenPlus` and `gamlingAndContests` are deprecated
type AgeRatingDeclarationProps = Omit<
AttributesOf<AgeRatingDeclaration>,
'seventeenPlus' | 'gamblingAndContests'
>;

// These attributes is what we get from the API when no questions are answered
export const emptyAdvisory: AttributesOf<AgeRatingDeclaration> = {
export const emptyAdvisory: AgeRatingDeclarationProps = {
alcoholTobaccoOrDrugUseOrReferences: null,
contests: null,
gamblingSimulated: null,
Expand All @@ -20,11 +31,12 @@ export const emptyAdvisory: AttributesOf<AgeRatingDeclaration> = {
gambling: false,
unrestrictedWebAccess: false,
kidsAgeBand: null,
seventeenPlus: false,
ageRatingOverride: null,
koreaAgeRatingOverride: null,
lootBox: null,
};

// @ts-expect-error: Deprecated property `gamblingAndContests` needs to be deleted from the types
export const leastRestrictiveAdvisory: AttributesOf<AgeRatingDeclaration> = {
export const leastRestrictiveAdvisory: AgeRatingDeclarationProps = {
alcoholTobaccoOrDrugUseOrReferences: Rating.NONE,
contests: Rating.NONE,
gamblingSimulated: Rating.NONE,
Expand All @@ -40,11 +52,12 @@ export const leastRestrictiveAdvisory: AttributesOf<AgeRatingDeclaration> = {
gambling: false,
unrestrictedWebAccess: false,
kidsAgeBand: null,
seventeenPlus: false,
ageRatingOverride: RatingOverride.NONE,
koreaAgeRatingOverride: KoreaRatingOverride.NONE,
lootBox: false,
};

// @ts-expect-error: Deprecated property `gamblingAndContests` needs to be deleted from the types
export const mostRestrictiveAdvisory: AttributesOf<AgeRatingDeclaration> = {
export const mostRestrictiveAdvisory: AgeRatingDeclarationProps = {
alcoholTobaccoOrDrugUseOrReferences: Rating.FREQUENT_OR_INTENSE,
contests: Rating.FREQUENT_OR_INTENSE,
gamblingSimulated: Rating.FREQUENT_OR_INTENSE,
Expand All @@ -60,11 +73,12 @@ export const mostRestrictiveAdvisory: AttributesOf<AgeRatingDeclaration> = {
gambling: true,
unrestrictedWebAccess: true,
kidsAgeBand: null,
seventeenPlus: true,
ageRatingOverride: RatingOverride.SEVENTEEN_PLUS,
koreaAgeRatingOverride: KoreaRatingOverride.NINETEEN_PLUS,
lootBox: true,
};

// @ts-expect-error: Deprecated property `gamblingAndContests` needs to be deleted from the types
export const kidsSixToEightAdvisory: AttributesOf<AgeRatingDeclaration> = {
export const kidsSixToEightAdvisory: AgeRatingDeclarationProps = {
alcoholTobaccoOrDrugUseOrReferences: Rating.NONE,
contests: Rating.NONE,
gamblingSimulated: Rating.NONE,
Expand All @@ -79,6 +93,8 @@ export const kidsSixToEightAdvisory: AttributesOf<AgeRatingDeclaration> = {
violenceRealisticProlongedGraphicOrSadistic: Rating.NONE,
gambling: false,
unrestrictedWebAccess: false,
kidsAgeBand: KidsAge.SIX_TO_EIGHT,
seventeenPlus: false,
kidsAgeBand: KidsAgeBand.SIX_TO_EIGHT,
ageRatingOverride: RatingOverride.NONE,
koreaAgeRatingOverride: KoreaRatingOverride.NONE,
lootBox: false,
};
Original file line number Diff line number Diff line change
@@ -1,48 +1,55 @@
import { AppStoreState, AppStoreVersion, Platform, ReleaseType } from '@expo/apple-utils';
import {
AppStoreState,
AppStoreVersion,
AppVersionState,
Platform,
ReleaseType,
ReviewType,
} from '@expo/apple-utils';

import { AttributesOf } from '../../../../utils/asc';

export const manualRelease: AttributesOf<AppStoreVersion> = {
platform: Platform.IOS,
versionString: '1.0.0',
appStoreState: AppStoreState.WAITING_FOR_REVIEW,
appVersionState: AppVersionState.WAITING_FOR_REVIEW,
storeIcon: null,
watchStoreIcon: null,
copyright: '2022 - ACME',
releaseType: ReleaseType.MANUAL,
earliestReleaseDate: null,
usesIdfa: null,
isWatchOnly: false,
downloadable: false,
createdDate: '2022-05-23T00:00:00.000Z',
reviewType: ReviewType.APP_STORE,
};

export const automaticRelease: AttributesOf<AppStoreVersion> = {
platform: Platform.IOS,
versionString: '2.0.0',
appStoreState: AppStoreState.WAITING_FOR_REVIEW,
appVersionState: AppVersionState.WAITING_FOR_REVIEW,
storeIcon: null,
watchStoreIcon: null,
copyright: '2022 - ACME',
releaseType: ReleaseType.AFTER_APPROVAL,
earliestReleaseDate: null,
usesIdfa: null,
isWatchOnly: false,
downloadable: false,
createdDate: '2022-05-23T00:00:00.000Z',
reviewType: ReviewType.APP_STORE,
};

export const scheduledRelease: AttributesOf<AppStoreVersion> = {
platform: Platform.IOS,
versionString: '3.0.0',
appStoreState: AppStoreState.READY_FOR_SALE,
appVersionState: AppVersionState.ACCEPTED,
storeIcon: null,
watchStoreIcon: null,
copyright: '2022 - ACME',
releaseType: ReleaseType.SCHEDULED,
earliestReleaseDate: '2022-05-29T00:00:00.000Z',
usesIdfa: null,
isWatchOnly: false,
downloadable: false,
createdDate: '2022-05-23T00:00:00.000Z',
reviewType: ReviewType.APP_STORE,
};
12 changes: 8 additions & 4 deletions packages/eas-cli/src/metadata/apple/config/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import {
AppStoreVersionLocalization,
AppStoreVersionPhasedRelease,
CategoryIds,
KoreaRatingOverride,
PhasedReleaseState,
Rating,
RatingOverride,
ReleaseType,
} from '@expo/apple-utils';

Expand Down Expand Up @@ -35,24 +37,26 @@ export class AppleConfigReader {
}

return {
ageRatingOverride: attributes.ageRatingOverride ?? RatingOverride.NONE,
alcoholTobaccoOrDrugUseOrReferences:
attributes.alcoholTobaccoOrDrugUseOrReferences ?? Rating.NONE,
contests: attributes.contests ?? Rating.NONE,
gambling: attributes.gambling ?? false,
gamblingSimulated: attributes.gamblingSimulated ?? Rating.NONE,
horrorOrFearThemes: attributes.horrorOrFearThemes ?? Rating.NONE,
kidsAgeBand: attributes.kidsAgeBand ?? null,
koreaAgeRatingOverride: attributes.koreaAgeRatingOverride ?? KoreaRatingOverride.NONE,
lootBox: attributes.lootBox ?? false,
matureOrSuggestiveThemes: attributes.matureOrSuggestiveThemes ?? Rating.NONE,
medicalOrTreatmentInformation: attributes.medicalOrTreatmentInformation ?? Rating.NONE,
profanityOrCrudeHumor: attributes.profanityOrCrudeHumor ?? Rating.NONE,
sexualContentGraphicAndNudity: attributes.sexualContentGraphicAndNudity ?? Rating.NONE,
sexualContentOrNudity: attributes.sexualContentOrNudity ?? Rating.NONE,
unrestrictedWebAccess: attributes.unrestrictedWebAccess ?? false,
violenceCartoonOrFantasy: attributes.violenceCartoonOrFantasy ?? Rating.NONE,
violenceRealistic: attributes.violenceRealistic ?? Rating.NONE,
violenceRealisticProlongedGraphicOrSadistic:
attributes.violenceRealisticProlongedGraphicOrSadistic ?? Rating.NONE,
gambling: attributes.gambling ?? false,
unrestrictedWebAccess: attributes.unrestrictedWebAccess ?? false,
kidsAgeBand: attributes.kidsAgeBand ?? null,
seventeenPlus: attributes.seventeenPlus ?? false,
};
}

Expand Down
17 changes: 12 additions & 5 deletions packages/eas-cli/src/metadata/apple/config/writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
AppStoreVersion,
AppStoreVersionLocalization,
AppStoreVersionPhasedRelease,
KoreaRatingOverride,
Rating,
RatingOverride,
ReleaseType,
} from '@expo/apple-utils';

Expand All @@ -28,26 +30,31 @@ export class AppleConfigWriter {
};
}

public setAgeRating(attributes: AttributesOf<AgeRatingDeclaration>): void {
// Note, both `seventeenPlus` and `gamlingAndContests` are deprecated
public setAgeRating(
attributes: Omit<AttributesOf<AgeRatingDeclaration>, 'seventeenPlus' | 'gamblingAndContests'>
): void {
this.schema.advisory = {
ageRatingOverride: attributes.ageRatingOverride ?? RatingOverride.NONE,
alcoholTobaccoOrDrugUseOrReferences:
attributes.alcoholTobaccoOrDrugUseOrReferences ?? Rating.NONE,
contests: attributes.contests ?? Rating.NONE,
gambling: attributes.gambling ?? false,
gamblingSimulated: attributes.gamblingSimulated ?? Rating.NONE,
horrorOrFearThemes: attributes.horrorOrFearThemes ?? Rating.NONE,
kidsAgeBand: attributes.kidsAgeBand ?? null,
koreaAgeRatingOverride: attributes.koreaAgeRatingOverride ?? KoreaRatingOverride.NONE,
lootBox: attributes.lootBox ?? false,
matureOrSuggestiveThemes: attributes.matureOrSuggestiveThemes ?? Rating.NONE,
medicalOrTreatmentInformation: attributes.medicalOrTreatmentInformation ?? Rating.NONE,
profanityOrCrudeHumor: attributes.profanityOrCrudeHumor ?? Rating.NONE,
sexualContentGraphicAndNudity: attributes.sexualContentGraphicAndNudity ?? Rating.NONE,
sexualContentOrNudity: attributes.sexualContentOrNudity ?? Rating.NONE,
unrestrictedWebAccess: attributes.unrestrictedWebAccess ?? false,
violenceCartoonOrFantasy: attributes.violenceCartoonOrFantasy ?? Rating.NONE,
violenceRealistic: attributes.violenceRealistic ?? Rating.NONE,
violenceRealisticProlongedGraphicOrSadistic:
attributes.violenceRealisticProlongedGraphicOrSadistic ?? Rating.NONE,
gambling: attributes.gambling ?? false,
unrestrictedWebAccess: attributes.unrestrictedWebAccess ?? false,
kidsAgeBand: attributes.kidsAgeBand ?? null,
seventeenPlus: attributes.seventeenPlus ?? false,
};
}

Expand Down
6 changes: 5 additions & 1 deletion packages/eas-cli/src/metadata/apple/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ export interface AppleMetadata {
review?: AppleReview;
}

export type AppleAdvisory = Partial<AgeRatingDeclarationProps>;
// The omited properties are deprecated
export type AppleAdvisory = Omit<
Partial<AgeRatingDeclarationProps>,
'seventeenPlus' | 'gamblingAndContests'
>;

/** Apps can define up to two categories, or categories with up to two subcategories */
export type AppleCategory = (string | string[])[];
Expand Down
Loading

0 comments on commit 281ae7b

Please sign in to comment.