Skip to content

Commit

Permalink
Make app metadata more generic to prepare for app details endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
baltpeter committed Jun 13, 2024
1 parent ceeab99 commit 8a4290b
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 73 deletions.
109 changes: 97 additions & 12 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ parse-play - v2.2.0
### Type Aliases

- [AppMetadata](README.md#appmetadata)
- [AppMetadataFull](README.md#appmetadatafull)
- [AppMetadataProperty](README.md#appmetadataproperty)
- [AppMetadataPropertySearch](README.md#appmetadatapropertysearch)
- [AppMetadataPropertyTopCharts](README.md#appmetadatapropertytopcharts)
- [CategoryId](README.md#categoryid)
- [CountryCode](README.md#countrycode)
- [DataSafetyLabel](README.md#datasafetylabel)
Expand All @@ -37,6 +41,8 @@ parse-play - v2.2.0
- [dataSafetyLabelDataCategories](README.md#datasafetylabeldatacategories)
- [dataSafetyLabelDataTypes](README.md#datasafetylabeldatatypes)
- [dataSafetyLabelPurposes](README.md#datasafetylabelpurposes)
- [searchAppMetadataProperties](README.md#searchappmetadataproperties)
- [topChartsAppMetadataProperties](README.md#topchartsappmetadataproperties)

### Functions

Expand All @@ -48,9 +54,28 @@ parse-play - v2.2.0

### AppMetadata

Ƭ **AppMetadata**: `Object`
Ƭ **AppMetadata**<`P`\>: `Pick`<[`AppMetadataFull`](README.md#appmetadatafull), `P`\>

A single app and its associated metadata.
The metadata for a single app. The available properties depend on which endpoint this was fetched from.

#### Type parameters

| Name | Type |
| :------ | :------ |
| `P` | extends [`AppMetadataProperty`](README.md#appmetadataproperty) |

#### Defined in

[common/data-format.ts:42](https://github.com/baltpeter/parse-play/blob/main/src/common/data-format.ts#L42)

___

### AppMetadataFull

Ƭ **AppMetadataFull**: `Object`

The full metadata that can theoretically be fetched for an app. The individual endpoints will only return a subset of
this, see [AppMetadata](README.md#appmetadata).

#### Type declaration

Expand All @@ -74,7 +99,43 @@ A single app and its associated metadata.

#### Defined in

[common/data-format.ts:6](https://github.com/baltpeter/parse-play/blob/main/src/common/data-format.ts#L6)
[common/data-format.ts:7](https://github.com/baltpeter/parse-play/blob/main/src/common/data-format.ts#L7)

___

### AppMetadataProperty

Ƭ **AppMetadataProperty**: keyof [`AppMetadataFull`](README.md#appmetadatafull)

A property that can be present in the metadata of an app.

#### Defined in

[common/data-format.ts:40](https://github.com/baltpeter/parse-play/blob/main/src/common/data-format.ts#L40)

___

### AppMetadataPropertySearch

Ƭ **AppMetadataPropertySearch**: typeof [`searchAppMetadataProperties`](README.md#searchappmetadataproperties)[`number`]

A property present in the metadata of each app in the search results.

#### Defined in

[endpoints/search.ts:42](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/search.ts#L42)

___

### AppMetadataPropertyTopCharts

Ƭ **AppMetadataPropertyTopCharts**: typeof [`topChartsAppMetadataProperties`](README.md#topchartsappmetadataproperties)[`number`]

A property present in the metadata of each app in the top chart.

#### Defined in

[endpoints/top-charts.ts:49](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L49)

___

Expand Down Expand Up @@ -297,25 +358,25 @@ ___

### SearchAppsResults

Ƭ **SearchAppsResults**: [`AppMetadata`](README.md#appmetadata)[]
Ƭ **SearchAppsResults**: [`AppMetadata`](README.md#appmetadata)<[`AppMetadataPropertySearch`](README.md#appmetadatapropertysearch)\>[]

A list of the search results.

#### Defined in

[endpoints/search.ts:26](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/search.ts#L26)
[endpoints/search.ts:46](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/search.ts#L46)

___

### TopChartsEntry

Ƭ **TopChartsEntry**: [`AppMetadata`](README.md#appmetadata)
Ƭ **TopChartsEntry**: [`AppMetadata`](README.md#appmetadata)<[`AppMetadataPropertyTopCharts`](README.md#appmetadatapropertytopcharts)\>

A single app and its associated metadata on a top chart.

#### Defined in

[endpoints/top-charts.ts:33](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L33)
[endpoints/top-charts.ts:54](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L54)

___

Expand Down Expand Up @@ -366,7 +427,7 @@ A list of the entries on the respective top chart.

#### Defined in

[endpoints/top-charts.ts:37](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L37)
[endpoints/top-charts.ts:58](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L58)

## Variables

Expand Down Expand Up @@ -410,6 +471,30 @@ Taken from the official documentation: <https://web.archive.org/web/202207011224

[common/consts.ts:325](https://github.com/baltpeter/parse-play/blob/main/src/common/consts.ts#L325)

___

### searchAppMetadataProperties

`Const` **searchAppMetadataProperties**: readonly [``"position"``, ``"app_id"``, ``"icon_url"``, ``"screenshot_urls"``, ``"name"``, ``"rating"``, ``"category"``, ``"price"``, ``"buy_url"``, ``"store_path"``, ``"trailer_url"``, ``"description"``, ``"developer"``, ``"downloads"``, ``"cover_image_url"``]

The properties present in the metadata of each app in the search results.

#### Defined in

[endpoints/search.ts:24](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/search.ts#L24)

___

### topChartsAppMetadataProperties

`Const` **topChartsAppMetadataProperties**: readonly [``"position"``, ``"app_id"``, ``"icon_url"``, ``"screenshot_urls"``, ``"name"``, ``"rating"``, ``"category"``, ``"price"``, ``"buy_url"``, ``"store_path"``, ``"trailer_url"``, ``"description"``, ``"developer"``, ``"downloads"``, ``"cover_image_url"``]

The properties present in the metadata of each app in the top chart.

#### Defined in

[endpoints/top-charts.ts:31](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L31)

## Functions

### fetchDataSafetyLabels
Expand Down Expand Up @@ -486,7 +571,7 @@ The top chart.

#### Defined in

[endpoints/top-charts.ts:96](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L96)
[endpoints/top-charts.ts:117](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L117)

**fetchTopCharts**(`requests`, `options`): `Promise`<([`TopChartsResult`](README.md#topchartsresult) \| `undefined`)[]\>

Expand All @@ -510,7 +595,7 @@ An array of the top charts, in the same order as the requests.

#### Defined in

[endpoints/top-charts.ts:110](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L110)
[endpoints/top-charts.ts:131](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/top-charts.ts#L131)

___

Expand All @@ -537,7 +622,7 @@ The search results.

#### Defined in

[endpoints/search.ts:131](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/search.ts#L131)
[endpoints/search.ts:151](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/search.ts#L151)

**searchApps**(`requests`, `options`): `Promise`<([`SearchAppsResults`](README.md#searchappsresults) \| `undefined`)[]\>

Expand All @@ -561,4 +646,4 @@ An array of the search results, in the same order as the requests.

#### Defined in

[endpoints/search.ts:145](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/search.ts#L145)
[endpoints/search.ts:165](https://github.com/baltpeter/parse-play/blob/main/src/endpoints/search.ts#L165)
65 changes: 43 additions & 22 deletions src/common/data-format.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { LanguageCode, CountryCode } from './consts';

/**
* A single app and its associated metadata.
* The full metadata that can theoretically be fetched for an app. The individual endpoints will only return a subset of
* this, see {@link AppMetadata}.
*/
export type AppMetadata = {
export type AppMetadataFull = {
/** The app's position in a list (top chart, search results). */
position: number;
/** The app's bundle ID. */
Expand Down Expand Up @@ -35,30 +36,50 @@ export type AppMetadata = {
/** A URL to the app's cover image. */
cover_image_url: string | undefined;
};
/** A property that can be present in the metadata of an app. */
export type AppMetadataProperty = keyof AppMetadataFull;
/** The metadata for a single app. The available properties depend on which endpoint this was fetched from. */
export type AppMetadata<P extends AppMetadataProperty> = Pick<AppMetadataFull, P>;

export const formatCurrency = (
value: number,
currency: string,
options: { language: LanguageCode; country: CountryCode }
) => new Intl.NumberFormat(`${options.language}-${options.country}`, { style: 'currency', currency }).format(value);
export const parseAppEntry = (

const appMetadataProperties: Record<
Exclude<AppMetadataProperty, 'position'>,
(d: any, options: { language: LanguageCode; country: CountryCode }) => any
> = {
app_id: (d) => d[0][0],
icon_url: (d) => d[1][3][2],
screenshot_urls: (d) => d[2].map((s: any) => s[3][2]),
name: (d) => d[3],
rating: (d) => d[4][1],
category: (d) => d[5],
price: (d, o) => (d[8] ? formatCurrency(d[8]?.[1][0][0] / 1e6, d[8]?.[1][0][1], o) : undefined),
buy_url: (d) => d[8]?.[6][5][2],
store_path: (d) => d[10][4][2],
trailer_url: (d) => d[12]?.[0][0][3][2],
description: (d) => d[13][1],
developer: (d) => d[14],
downloads: (d) => d[15],
cover_image_url: (d) => d[22][3]?.[2],
};
export const parseAppEntry = <P extends AppMetadataProperty>(
entry: any,
idx: number,
options: { language: LanguageCode; country: CountryCode }
): AppMetadata => ({
position: idx + 1,
app_id: entry[0][0],
icon_url: entry[1][3][2],
screenshot_urls: entry[2].map((s: any) => s[3][2]),
name: entry[3],
rating: entry[4][1],
category: entry[5],
price: entry[8] ? formatCurrency(entry[8]?.[1][0][0] / 1e6, entry[8]?.[1][0][1], options) : undefined,
buy_url: entry[8]?.[6][5][2],
store_path: entry[10][4][2],
trailer_url: entry[12]?.[0][0][3][2],
description: entry[13][1],
developer: entry[14],
downloads: entry[15],
cover_image_url: entry[22][3]?.[2],
});
properties: P[] | readonly P[],
options: { language: LanguageCode; country: CountryCode; idx?: number }
): AppMetadata<P> => {
const res: Record<string, any> = {};

if (options.idx) res.position = options.idx + 1;

for (const [property, getter] of Object.entries(appMetadataProperties).filter(([p]) =>
properties.includes(p as P)
)) {
res[property] = getter(entry, options);
}

return res as AppMetadata<P>;
};
26 changes: 23 additions & 3 deletions src/endpoints/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,30 @@ export type SearchAppsOptions = {
language: LanguageCode;
};

/** The properties present in the metadata of each app in the search results. */
export const searchAppMetadataProperties = [
'position',
'app_id',
'icon_url',
'screenshot_urls',
'name',
'rating',
'category',
'price',
'buy_url',
'store_path',
'trailer_url',
'description',
'developer',
'downloads',
'cover_image_url',
] as const;
/** A property present in the metadata of each app in the search results. */
export type AppMetadataPropertySearch = typeof searchAppMetadataProperties[number];
/**
* A list of the search results.
*/
export type SearchAppsResults = AppMetadata[];
export type SearchAppsResults = AppMetadata<AppMetadataPropertySearch>[];

export const searchAppsRequestPayload = (request: SearchAppsRequest): RequestPayload => [
'lGYRle',
Expand Down Expand Up @@ -77,7 +97,7 @@ export const parseSearchAppsPayload = (data: any, options: SearchAppsOptions): S

assert(() => meta.length === 102 || meta.length === 101, 'Meta length.');

return parseAppEntry(meta, hasFeaturedApp ? idx + 1 : idx, options);
return parseAppEntry(meta, searchAppMetadataProperties, { ...options, idx: hasFeaturedApp ? idx + 1 : idx });
});

if (hasFeaturedApp) {
Expand All @@ -89,7 +109,7 @@ export const parseSearchAppsPayload = (data: any, options: SearchAppsOptions): S
'Featured entry inner meta length.'
);

const featuredEntryParsed: AppMetadata = {
const featuredEntryParsed = {
position: 1,
app_id: featuredEntry[16][11][0][0],
icon_url: featuredEntry[16][2][95][0][3][2],
Expand Down
25 changes: 23 additions & 2 deletions src/endpoints/top-charts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,31 @@ export type TopChartsOptions = {
language: LanguageCode;
};

/** The properties present in the metadata of each app in the top chart. */
export const topChartsAppMetadataProperties = [
'position',
'app_id',
'icon_url',
'screenshot_urls',
'name',
'rating',
'category',
'price',
'buy_url',
'store_path',
'trailer_url',
'description',
'developer',
'downloads',
'cover_image_url',
] as const;
/** A property present in the metadata of each app in the top chart. */
export type AppMetadataPropertyTopCharts = typeof topChartsAppMetadataProperties[number];

/**
* A single app and its associated metadata on a top chart.
*/
export type TopChartsEntry = AppMetadata;
export type TopChartsEntry = AppMetadata<AppMetadataPropertyTopCharts>;
/**
* A list of the entries on the respective top chart.
*/
Expand Down Expand Up @@ -78,7 +99,7 @@ export const parseTopChartPayload = (data: any, options: TopChartsOptions): TopC
'Weird second meta object only has category.'
);

return parseAppEntry(meta, idx, options);
return parseAppEntry(meta, topChartsAppMetadataProperties, { ...options, idx });
});

return parsed;
Expand Down
Loading

0 comments on commit 8a4290b

Please sign in to comment.