Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

[configure-splash-screen] Refactor and integrate with @expo/config #2297

Merged

Conversation

bbarthec
Copy link
Contributor

@bbarthec bbarthec commented Jun 22, 2020

Why

@expo/config should autoconfigure the splash screen once expo eject is called instead of showing nasty warning.

How

This whole PR is much too big and complex to be called a nice one 😅
The amount of code that has been written is not even to be compared to the amount of functionality this PR provides (to the disadvantage of the the first).
Nevertheless I've decided to try to ship it in the shape it is.
Why? Because I've experimented with:

  • generic SplashScreenConfig type
  • platform-specific SplashScreenConfig types that are created dynamically via mapped type
  • JSON-friendly types equivalents that are to be exposed outside the package (e.g. for @expo/config) and are dynamically generated from original types via other mapped type
  • Validator object that has this nicely looking addRule method that is fully TS-supported
  • cli command separated completely from logic now (only defines CLI options and performs minimal validation and shaping raw JSON Config for further processing)
  • a bunch of tests (these might and should be cleaned in the future - I started to wonder how to write minimal set of tests to cover each code path 🤔 any idea here?)

configure-splash-screen-flow

@bbarthec bbarthec marked this pull request as ready for review June 22, 2020 20:22
@brentvatne brentvatne requested a review from satya164 July 8, 2020 20:30
packages/config/src/android/SplashScreen.ts Outdated Show resolved Hide resolved
packages/config/src/android/SplashScreen.ts Outdated Show resolved Hide resolved
packages/config/src/android/SplashScreen.ts Outdated Show resolved Hide resolved
packages/config/src/ios/SplashScreen.ts Outdated Show resolved Hide resolved
packages/config/src/ios/SplashScreen.ts Outdated Show resolved Hide resolved
packages/configure-splash-screen/src/android/Colors.xml.ts Outdated Show resolved Hide resolved
/**
* This class is responsible for validating configuration object in a form of json and produce validated object based on validating `rules` added via `addRule` method.
*/
export default class FromJsonValidator<From extends JsonShape<To>, To extends object> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this class is pretty clever. we should probably pull it out into a util. out of curiosity, did you consider any other npm packages to do a similar thing? i'm not familiar with any that both transform and validate like this does

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Congratulations on implementing an object validator! I too am curious whether you considered other NPM packages. As I mentioned on one of the calls I've had pretty good experience with zod which, I guess, does the same thing (parses an unknown object into an object of a known TS type, inferring and parsing types and optionally validates)?

While I admire the heart you've put into this and stuff you must have learned along the way I'm a little afraid maintaining this may be a burden no one will want to take a couple of months from now and this will become a zombie file here be dragons.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it was my little experiment 😉
I really like the zod idea and I'm willing to add it to our codebase somewhere. I'm not sure though if zod can provide validation & transformation at the same time, please take a look at following lines:
https://github.com/expo/expo-cli/pull/2297/files#diff-63c94c9e1d2966b124e8333ec934d795R55
https://github.com/expo/expo-cli/pull/2297/files#diff-63c94c9e1d2966b124e8333ec934d795R29
These represent the same think, but one in JSON and other in it's semantically-validated equivalent (Color is a tuple). What I'm curious about is: whether zod can convert for example string into some complex object/structure? 🤔 Nonetheless, IMO it's still worth to be added 👍

packages/configure-splash-screen/src/validators/index.ts Outdated Show resolved Hide resolved
@brentvatne
Copy link
Member

I started to wonder how to write minimal set of tests to cover each code path 🤔 any idea here?

I think the current structure of this code lends itself very well to testing. If we test the validator/transformer functions exhaustively, then we can do some e2e tests that ensure they're wired up correctly with the CLI/external api.

One thing that we might want to do is split out the FromJsonValidator and test that independently, then just assume it works as it promises though its API within this code. We can do that in a followup PR.

@bbarthec
Copy link
Contributor Author

Linking with #1494

@sjchmiela
Copy link
Contributor

Oooh… thanks for reminding to review this 😅

Copy link
Contributor

@sjchmiela sjchmiela left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very clever pull request (which means both good and bad). 😅 Had some questions, apart from them it looks very solid!

/**
* This class is responsible for validating configuration object in a form of json and produce validated object based on validating `rules` added via `addRule` method.
*/
export default class FromJsonValidator<From extends JsonShape<To>, To extends object> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Congratulations on implementing an object validator! I too am curious whether you considered other NPM packages. As I mentioned on one of the calls I've had pretty good experience with zod which, I guess, does the same thing (parses an unknown object into an object of a known TS type, inferring and parsing types and optionally validates)?

While I admire the heart you've put into this and stuff you must have learned along the way I'm a little afraid maintaining this may be a burden no one will want to take a couple of months from now and this will become a zombie file here be dragons.

packages/config/src/ios/SplashScreen.ts Outdated Show resolved Hide resolved
Comment on lines +15 to +29
const AVAILABLE_OPTIONS_NAMES = [
'imageResizeMode',
'platform',
'backgroundColor',
'imagePath',
'darkModeBackgroundColor',
'darkModeImagePath',
'statusBarHidden',
'statusBarStyle',
'darkModeStatusBarStyle',
'statusBarTranslucent',
'statusBarBackgroundColor',
'darkModeStatusBarBackgroundColor',
] as const;

type CLIOptionName = typeof AVAILABLE_OPTIONS_NAMES[number];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this sophisticated const AVAILABLE_OPTIONS_NAMES and then this typeof instead of a simple enum or a union type?


type CLIOptionName = typeof AVAILABLE_OPTIONS_NAMES[number];

type CLIOptions = Partial<Record<CLIOptionName, string>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't type of statusBarTranslucent be boolean?

Comment on lines +79 to +82
if (!backgroundColor) {
throw new Error(
`'backgroundColor': Required option is not provided. Provide a valid color string.`
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think recent releases of commander.js allow usage of requiredOption if that's something we may want to look into

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it does, but I couldn't get this option covered by tests then 😞 Commander.js simply kills the process with exit code 1 once the option is not provided. Maybe it does not need to be tested then? 🤔 Dunno 🤷

}

const resolvedStatusBarHidden =
statusBarHidden === undefined ? undefined : Boolean(statusBarHidden);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing undefined in a variable called resolved seems icky to me. Is there a specific reason for passing undefined down? Does it say "do not modify anything related to this setting"?

Actually while writing this comment I had deja vu, so if we already talked about this then sorry

@bbarthec bbarthec force-pushed the @bbarthec/configure-splash-screen-integrate-with-config branch from 41680ca to 755420d Compare September 4, 2020 16:56
@@ -0,0 +1,138 @@
import configureAndroid from '../android';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should rename all of these tests to -test after this PR is merged. #2591

@EvanBacon
Copy link
Contributor

  • Seems the XML logic isn't unified with expo/config so running expo eject/apply formats the XML files differently.
  • This doesn't work as expected when it's rerun using apply. Apply should be supported because it makes using bare far better for expo users, but also having apply support makes changes like this substantially easier to test as a whole.
@brentvatne
Copy link
Member

Seems the XML logic isn't unified with expo/config so running expo eject/apply formats the XML files differently.

@bbarthec @EvanBacon - let's chat at the next expo-cli meeting about which xml library we should be using, we currently have three (that i'm aware of? maybe more?):

  1. xmldom
  2. xml2js
  3. xml-js

we need to consolidate on one to reduce duplicate dependencies and ensure that we're not reformatting the xml files in subtle ways when different commands are executed.

@bbarthec
Copy link
Contributor Author

Do you guys have any major concerns about this PR apart from the xml library? cc @brentvatne, @EvanBacon
If no, wy not to ship it now and work on the top of it in the separate PRs?

@brentvatne brentvatne merged commit 885f280 into master Sep 18, 2020
@brentvatne brentvatne deleted the @bbarthec/configure-splash-screen-integrate-with-config branch September 18, 2020 01:58
bbarthec pushed a commit that referenced this pull request Oct 13, 2020
…ming convention (#2749)

As mentioned in issue #2591 and PR #2297, we want to update tests from `.test` to `-test`.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
5 participants