Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions packages/eas-cli/schema/metadata-0.json
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,118 @@
"vi": { "$ref": "#/definitions/apple/AppleAppClipLocalizedInfo", "description": "Vietnamese" }
}
},
"ApplePrivacy": {
"type": "object",
"additionalProperties": false,
"description": "Privacy metadata. Currently only contains App Privacy Nutrition Labels (data usage).",
"properties": {
"dataUsage": {
"$ref": "#/definitions/apple/AppleDataUsage",
"description": "App Privacy Nutrition Labels. Declares what data the app collects, how it is used, and how it is linked to the user. Required for new app submissions since 2021."
}
}
},
"AppleDataUsage": {
"type": "object",
"additionalProperties": false,
"description": "Privacy Nutrition Labels — declarative declaration of data the app collects. When `dataNotCollected` is true, no data is collected and `categories` must be empty.",
"properties": {
"dataNotCollected": {
"type": "boolean",
"description": "Whether the app collects no data at all. Mirrors Apple's \"Data Not Collected\" toggle. When true, `categories` must be empty."
},
"categories": {
"type": "array",
"description": "Per-category data usage declarations.",
"items": {
"$ref": "#/definitions/apple/AppleDataUsageCategoryEntry"
}
}
}
},
"AppleDataUsageCategoryEntry": {
"type": "object",
"additionalProperties": false,
"required": ["category"],
"description": "A single Privacy Nutrition Labels declaration: pairs a data category with the purposes it is used for and the data protection / linkage classification.",
"properties": {
"category": {
"$ref": "#/definitions/apple/AppleDataUsageCategoryId",
"description": "Apple data category."
},
"purposes": {
"type": "array",
"description": "Purposes the category is used for. At least one entry is required when the category is collected.",
"items": {
"$ref": "#/definitions/apple/AppleDataUsagePurposeId"
}
},
"protections": {
"type": "array",
"description": "Data protection / linkage classification(s). A single category can be both linked to the user and used for tracking.",
"items": {
"$ref": "#/definitions/apple/AppleDataUsageDataProtectionId"
}
}
}
},
"AppleDataUsageCategoryId": {
"enum": [
"ADVERTISING_DATA",
"AUDIO",
"BROWSING_HISTORY",
"COARSE_LOCATION",
"CONTACTS",
"CRASH_DATA",
"CREDIT_AND_FRAUD",
"CUSTOMER_SUPPORT",
"DEVICE_ID",
"EMAIL_ADDRESS",
"EMAILS_OR_TEXT_MESSAGES",
"ENVIRONMENTAL_SCANNING",
"FITNESS",
"GAMEPLAY_CONTENT",
"HANDS",
"HEAD_MOVEMENT",
"HEALTH",
"NAME",
"OTHER_CONTACT_INFO",
"OTHER_DATA",
"OTHER_DIAGNOSTIC_DATA",
"OTHER_FINANCIAL_INFO",
"OTHER_USAGE_DATA",
"OTHER_USER_CONTENT",
"PAYMENT_INFORMATION",
"PERFORMANCE_DATA",
"PHONE_NUMBER",
"PHOTOS_OR_VIDEOS",
"PHYSICAL_ADDRESS",
"PRECISE_LOCATION",
"PRODUCT_INTERACTION",
"PURCHASE_HISTORY",
"SEARCH_HISTORY",
"SENSITIVE_INFO",
"USER_ID"
]
},
"AppleDataUsagePurposeId": {
"enum": [
"THIRD_PARTY_ADVERTISING",
"DEVELOPERS_ADVERTISING",
"ANALYTICS",
"PRODUCT_PERSONALIZATION",
"APP_FUNCTIONALITY",
"OTHER_PURPOSES"
]
},
"AppleDataUsageDataProtectionId": {
"enum": [
"DATA_USED_TO_TRACK_YOU",
"DATA_LINKED_TO_YOU",
"DATA_NOT_LINKED_TO_YOU",
"DATA_NOT_COLLECTED"
]
},
"AppleAgeRatingOverride": {
"enum": [
"NONE",
Expand Down Expand Up @@ -1034,6 +1146,10 @@
"appClip": {
"$ref": "#/definitions/apple/AppleAppClip",
"description": "App Clip metadata. Only applies to apps that ship an App Clip target."
},
"privacy": {
"$ref": "#/definitions/apple/ApplePrivacy",
"description": "Privacy metadata, including App Privacy Nutrition Labels (data usage). Required for new app submissions since 2021."
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions packages/eas-cli/src/metadata/apple/config/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
AppleAppClip,
AppleAppClipDefaultExperience,
AppleAppClipLocalizedInfo,
AppleDataUsage,
AppleMetadata,
ApplePreviews,
AppleScreenshots,
Expand Down Expand Up @@ -257,4 +258,12 @@ export class AppleConfigReader {
public getAppClipLocalizedInfo(locale: string): AppleAppClipLocalizedInfo | null {
return this.schema.appClip?.defaultExperience?.info?.[locale] ?? null;
}

/**
* Get the privacy data usage block (Privacy Nutrition Labels), or `null` if
* not configured. When `null`, the data usage task is a no-op.
*/
public getDataUsage(): AppleDataUsage | null {
return this.schema.privacy?.dataUsage ?? null;
}
}
19 changes: 19 additions & 0 deletions packages/eas-cli/src/metadata/apple/config/writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
AppleAppClipDefaultExperience,
AppleAppClipLocalizedInfo,
AppleAppClipReviewDetail,
AppleDataUsage,
AppleMetadata,
ApplePreviews,
AppleScreenshots,
Expand Down Expand Up @@ -218,6 +219,24 @@ export class AppleConfigWriter {
this.schema.info[locale].previews = Object.keys(previews).length > 0 ? previews : undefined;
}

/**
* Set the privacy data usage block. Pass `null` to clear it (e.g. when the
* remote app has no data usage entries declared yet).
*/
public setDataUsage(dataUsage: AppleDataUsage | null): void {
if (!dataUsage) {
if (this.schema.privacy) {
delete this.schema.privacy.dataUsage;
if (Object.keys(this.schema.privacy).length === 0) {
delete this.schema.privacy;
}
}
return;
}
this.schema.privacy = this.schema.privacy ?? {};
this.schema.privacy.dataUsage = dataUsage;
}

/** Set the App Clip default experience attributes (action, releaseWithAppStoreVersion). */
public setAppClipDefaultExperience(
attributes: Pick<AppleAppClipDefaultExperience, 'action' | 'releaseWithAppStoreVersion'>
Expand Down
4 changes: 3 additions & 1 deletion packages/eas-cli/src/metadata/apple/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { AppClipData } from './tasks/app-clip';
import type { AppInfoData } from './tasks/app-info';
import type { AppReviewData } from './tasks/app-review-detail';
import type { AppVersionData } from './tasks/app-version';
import type { DataUsageData } from './tasks/data-usage';
import type { PreviewsData } from './tasks/previews';
import type { ScreenshotsData } from './tasks/screenshots';

Expand All @@ -18,7 +19,8 @@ export type AppleData = { app: App; projectDir: string } & AppInfoData &
AppReviewData &
ScreenshotsData &
PreviewsData &
AppClipData;
AppClipData &
DataUsageData;

/**
* The unprepared partial apple data, used within the `prepareAsync` tasks.
Expand Down
Loading
Loading