-
Notifications
You must be signed in to change notification settings - Fork 134
Demonstrate JSON Schema as source of truth for web-features data #2990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
/** | ||
* The top-level web-features data package | ||
*/ | ||
export interface WebFeaturesData { | ||
/** | ||
* Browsers and browser release data | ||
*/ | ||
browsers: Browsers; | ||
/** | ||
* Feature identifiers and data | ||
*/ | ||
features: { [key: string]: FeatureData }; | ||
/** | ||
* Group identifiers and data | ||
*/ | ||
groups: { [key: string]: GroupData }; | ||
/** | ||
* Snapshot identifiers and data | ||
*/ | ||
snapshots?: { [key: string]: SnapshotData }; | ||
} | ||
|
||
/** | ||
* Browsers and browser release data | ||
*/ | ||
export interface Browsers { | ||
chrome: BrowserData; | ||
chrome_android: BrowserData; | ||
edge: BrowserData; | ||
firefox: BrowserData; | ||
firefox_android: BrowserData; | ||
safari: BrowserData; | ||
safari_ios: BrowserData; | ||
} | ||
|
||
/** | ||
* Browser information | ||
*/ | ||
export interface BrowserData { | ||
/** | ||
* The name of the browser, as in "Edge" or "Safari on iOS" | ||
*/ | ||
name: string; | ||
releases: Release[]; | ||
} | ||
|
||
/** | ||
* Browser release information | ||
*/ | ||
export interface Release { | ||
/** | ||
* The release date, as in "2023-12-11" | ||
*/ | ||
date: string; | ||
/** | ||
* The version string, as in "10" or "17.1" | ||
*/ | ||
version: string; | ||
} | ||
|
||
/** | ||
* A feature data entry | ||
*/ | ||
export interface FeatureData { | ||
/** | ||
* caniuse.com identifier(s) | ||
*/ | ||
caniuse?: string[] | string; | ||
/** | ||
* Sources of support data for this feature | ||
*/ | ||
compat_features?: string[]; | ||
/** | ||
* Short description of the feature, as a plain text string | ||
*/ | ||
description: string; | ||
/** | ||
* Short description of the feature, as an HTML string | ||
*/ | ||
description_html: string; | ||
/** | ||
* Whether developers are formally discouraged from using this feature | ||
*/ | ||
discouraged?: Discouraged; | ||
/** | ||
* Group identifier(s) | ||
*/ | ||
group?: string[] | string; | ||
/** | ||
* Short name | ||
*/ | ||
name: string; | ||
/** | ||
* Snapshot identifier(s) | ||
*/ | ||
snapshot?: string[] | string; | ||
/** | ||
* Specification URL(s) | ||
*/ | ||
spec: string[] | string; | ||
/** | ||
* Whether a feature is considered a "Baseline" web platform feature and when it achieved | ||
* that status | ||
*/ | ||
status?: StatusHeadline; | ||
[property: string]: any; | ||
} | ||
|
||
/** | ||
* Whether developers are formally discouraged from using this feature | ||
*/ | ||
export interface Discouraged { | ||
/** | ||
* Links to a formal discouragement notice, such as specification text, intent-to-unship, | ||
* etc. | ||
*/ | ||
according_to: string[]; | ||
/** | ||
* IDs for features that substitute some or all of this feature's utility | ||
*/ | ||
alternatives?: string[]; | ||
} | ||
|
||
/** | ||
* Whether a feature is considered a "Baseline" web platform feature and when it achieved | ||
* that status | ||
*/ | ||
export interface StatusHeadline { | ||
/** | ||
* Whether the feature is Baseline (low substatus), Baseline (high substatus), or not (false) | ||
*/ | ||
baseline: boolean | BaselineEnum; | ||
/** | ||
* Date the feature achieved Baseline high status | ||
*/ | ||
baseline_high_date?: string; | ||
/** | ||
* Date the feature achieved Baseline low status | ||
*/ | ||
baseline_low_date?: string; | ||
/** | ||
* Browser versions that most-recently introduced the feature | ||
*/ | ||
support: Support; | ||
/** | ||
* Statuses for each key in the feature's compat_features list, if applicable. Not available | ||
* to the npm release of web-features. | ||
*/ | ||
by_compat_key?: { [key: string]: Status }; | ||
[property: string]: any; | ||
} | ||
|
||
export type BaselineEnum = "high" | "low"; | ||
|
||
export interface Status { | ||
/** | ||
* Whether the feature is Baseline (low substatus), Baseline (high substatus), or not (false) | ||
*/ | ||
baseline: boolean | BaselineEnum; | ||
/** | ||
* Date the feature achieved Baseline high status | ||
*/ | ||
baseline_high_date?: string; | ||
/** | ||
* Date the feature achieved Baseline low status | ||
*/ | ||
baseline_low_date?: string; | ||
/** | ||
* Browser versions that most-recently introduced the feature | ||
*/ | ||
support: Support; | ||
[property: string]: any; | ||
} | ||
|
||
/** | ||
* Browser versions that most-recently introduced the feature | ||
*/ | ||
export interface Support { | ||
chrome?: string; | ||
chrome_android?: string; | ||
edge?: string; | ||
firefox?: string; | ||
firefox_android?: string; | ||
safari?: string; | ||
safari_ios?: string; | ||
} | ||
|
||
export interface GroupData { | ||
/** | ||
* Short name | ||
*/ | ||
name: string; | ||
/** | ||
* Identifier of parent group | ||
*/ | ||
parent?: string; | ||
} | ||
|
||
export interface SnapshotData { | ||
/** | ||
* Short name | ||
*/ | ||
name?: string; | ||
/** | ||
* Specification | ||
*/ | ||
spec?: string; | ||
[property: string]: any; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Quicktype produces a definitions that are correct, but not as narrow or | ||
// well-named as hand-written type definition might produce. This module takes | ||
// the Quicktype-generated types as renames or modifies the types to be somewhat | ||
// nicer to work with in TypeScript. | ||
|
||
import type { | ||
BaselineEnum as BaselineHighLow, | ||
BrowserData, | ||
Browsers, | ||
GroupData, | ||
FeatureData as QuicktypeMonolithicFeatureData, | ||
WebFeaturesData as QuicktypeWebFeaturesData, | ||
Release, | ||
SnapshotData, | ||
Status, | ||
StatusHeadline, | ||
Support, | ||
} from "./new.quicktype"; | ||
|
||
// Passthrough types | ||
export type { | ||
BaselineHighLow, | ||
BrowserData, | ||
Browsers, | ||
GroupData, | ||
Release, | ||
SnapshotData, | ||
Status, | ||
StatusHeadline, | ||
Support, | ||
}; | ||
|
||
export interface WebFeaturesData | ||
extends Pick<QuicktypeWebFeaturesData, "browsers" | "groups" | "snapshots"> { | ||
features: { [key: string]: FeatureData }; | ||
} | ||
|
||
export type FeatureData = Required< | ||
Pick< | ||
QuicktypeMonolithicFeatureData, | ||
"description_html" | "description" | "name" | "spec" | "status" | ||
> | ||
> & | ||
Partial< | ||
Pick< | ||
QuicktypeMonolithicFeatureData, | ||
"caniuse" | "compat_features" | "discouraged" | ||
> | ||
>; | ||
Comment on lines
+33
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a preview of what's coming when we add redirects. TypeScript and JSON Schema's type systems aren't strictly equivalent, so quicktype will generate correct but overbroad types. In this module, I'll pluck out some nuances (and badly generated names) that quicktype doesn't handle very well and clean them up by extending the generated types. While it's a bit weird looking, the benefit is that we can't completely diverge from the underlying JSON Schema. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do the TypeScript error messages if you get types wrong end up looking completely bizarre with this layering? |
||
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const t1: FeatureData = { | ||
name: "Test", | ||
description: "Hi", | ||
description_html: "Hi", | ||
spec: "", | ||
status: { | ||
baseline: false, | ||
support: {}, | ||
}, | ||
}; | ||
Comment on lines
+51
to
+61
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we like, we can even "test" some properties of our types—like I do here demonstrating a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That seems like a useful smoke test. I guess that when we load the JSON and interpret it as a TypeScript type, there's no checking going on that we could rely on? That would be helpful, but I suspect it's not a thing. |
||
|
||
export type BrowserIdentifier = keyof Browsers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is generated by quicktype from the new, hand-authored JSON Schema. The generation is OK for now but if we add something like redirects as described in #91, it has a few inconveniences. We're going to insulate ourselves from quicktype with the next TS module.