Skip to content
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

Follow up to #3420 #3437

Merged
merged 10 commits into from
Jun 11, 2021
Merged

Follow up to #3420 #3437

merged 10 commits into from
Jun 11, 2021

Conversation

samtstern
Copy link
Contributor

Description

Follow up to #3420

  • Do a first modernization pass on config.ts
  • Improve the typing of as many options.config.get("...") calls in *.ts files as I easily could

Scenarios Tested

Relying on compiler and unit tests here.

Sample Commands

N/A

@google-cla google-cla bot added the cla: yes Manual indication that this has passed CLA. label Jun 1, 2021
@samtstern samtstern requested review from joehan and inlined June 1, 2021 16:48
Copy link
Member

@inlined inlined left a comment

Choose a reason for hiding this comment

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

Generally LGTM except:

  1. There's a good handful of new casts in here. Why are they needed?
  2. I'm nervous that the functions default directory needs to be checked in all places for a fallback to default. Why can't we just put the default in config?
  3. I already didn't understand the difference between options and options.config. Now we have options.config and options.config.src. Do we really need the "src" bag?

src/config.ts Outdated Show resolved Hide resolved
@@ -28,7 +29,7 @@ export const actionFunction = async (options: any) => {
debugPort = commandUtils.parseInspectionPort(options);
}

const hubClient = new EmulatorHubClient(options.project);
const hubClient = new EmulatorHubClient(options.project as string);
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need a cast here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Previously options was any so options.project was also any. Now options is Options so options.project is unknown. We have to assert the type as string. It's not type-safe, but it wasn't before either. The slight improvement here (IMO) is putting the ugly cast out in the open.

I'll change this to use an assertion instead.

src/commands/remoteconfig-get.ts Outdated Show resolved Hide resolved
@samtstern
Copy link
Contributor Author

@inlined responses to your comments:

There's a good handful of new casts in here. Why are they needed?

Now that options is not any it has a lot of unknown properties. We were always assuming their types before, now the compiler is just making us reveal our shame with casts. I changed a lot of the casts to assertions now, which I think is better?

In general this codebase has a bad pattern where things are bolted on to options over time and then modules make assumptions about what has run before them. For example options.user is only there after certain auth utilities run. options.project is only there after requireProject.

Removing that pattern is the right thing to do but also very daunting.

I'm nervous that the functions default directory needs to be checked in all places for a fallback to default. Why can't we just put the default in config?

I would love a better way for us to handle defaults. Right now the default is set with a config.set() at runtime so the compiler doesn't know about it. What do you think is the most elegant way to handle this?

I already didn't understand the difference between options and options.config. Now we have options.config and options.config.src. Do we really need the "src" bag?

Can you suggest a clean way to get rid of it?

@inlined
Copy link
Member

inlined commented Jun 2, 2021

@inlined inlining responses to inlined responses to @inlined's comments

Now that options is not any it has a lot of unknown properties. We were always assuming their types before, now the compiler is just making us reveal our shame with casts. I changed a lot of the casts to assertions now, which I think is better?

I guess I just didn't understand at first why we can't have things like an explicit project: string | undefined. I feel better about null assertions than type assertions (not great about either, but that's a separate discussion)

In general this codebase has a bad pattern where things are bolted on to options over time and then modules make assumptions about what has run before them. For example options.user is only there after certain auth utilities run. options.project is only there after requireProject.

I've contemplated these issues a few times and I agree that I don't know the right solution. In Functions' code I just comment each field as the phase in which it becomes available, but I wish there were an elegant way to upcast a PrepareOptions to a DeployOptions to a ReleaseOptions so things would go from nullable to defined.

I would love a better way for us to handle defaults. Right now the default is set with a config.set() at runtime so the compiler doesn't know about it. What do you think is the most elegant way to handle this?

Why does default initialization in the Config not work?

Can you suggest a clean way to get rid of [Options.config.src]?

Maybe I'm being dense here, but why is it hard to unnest an object? Why is src valuable today? Maybe it is better to wait until Options.config.get/set is removed entirely and then just remove the src bag everywhere?

@samtstern
Copy link
Contributor Author

I guess I just didn't understand at first why we can't have things like an explicit project: string | undefined. I feel better about null assertions than type assertions (not great about either, but that's a separate discussion)

We can do this for the options which are present on every command like project and debug. For the per-command options I think we'll need a better system than defining them all as optional on this one type. I'll add the ones I can.

Why does default initialization in the Config not work?

Does TS support a default value in an interface? I don't think so. Right now the FirebaseConfig file is meant to represent the contents of firebase.json, not the contents + implied defaults.

I guess I could make a new type with the defaults and merge them? I do think it's important to have a type which represents the JSON config exactly as provided by the developer.

Maybe I'm being dense here, but why is it hard to unnest an object? Why is src valuable today? Maybe it is better to wait until Options.config.get/set is removed entirely and then just remove the src bag everywhere?

This was my plan, yes. But I can unnest it now if you want.

@samtstern
Copy link
Contributor Author

@inlined it's actually not safe to unnest src onto config until we get rid of config.set() since that modifies data which is like a bizzaro parallel word of src ...

Copy link
Member

@inlined inlined left a comment

Choose a reason for hiding this comment

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

Sorry, I thought I had LGTM'd earlier. I don't know if I agree that we need a type that matches the JSON directly as opposed to w/ defaults, but I'm not going to make a huge deal about it. And I understand that src can't be deleted yet. It would be nice if we could eventually get there though.

@samtstern samtstern merged commit 0641bd2 into master Jun 11, 2021
inlined added a commit that referenced this pull request Jul 3, 2021
* Unbreak build (#3463)

* Unbreak build

* linter changed its mind

* firestore:delete getConfirmationMessage should include current project (#3457)

The firestore:delete command should notify the user of the current project. This should help users minimize chances of accidental deletions when switching between projects.

* Add asia-southeast1 to RTDB CLI (#3460)

* Fix init database without projectId (#3446)

* Fix init database (#3445)

* Added value check for "feature" parameter in init (#3449)

When the optional feature parameter is provided in a `firebase init
[feature]` command, this checks that its value is a valid choice before
attempting any other initialization.

* Bump trim-newlines from 3.0.0 to 3.0.1 (#3471)

Bumps [trim-newlines](https://github.com/sindresorhus/trim-newlines) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/sindresorhus/trim-newlines/releases)
- [Commits](https://github.com/sindresorhus/trim-newlines/commits)

---
updated-dependencies:
- dependency-name: trim-newlines
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump ws from 7.2.3 to 7.4.6 (#3428)

* add node16 to tests (#3462)

* Import/export download tokens (#3444)

* Fixes Storage Emulator startup errors (#3478)

* Bump normalize-url from 4.5.0 to 4.5.1 (#3476)

Bumps [normalize-url](https://github.com/sindresorhus/normalize-url) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/sindresorhus/normalize-url/releases)
- [Commits](https://github.com/sindresorhus/normalize-url/commits)

---
updated-dependencies:
- dependency-name: normalize-url
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Fixes download tokens missing when uploading files via Cloud SDK (#3479)

* Follow up to #3420 (#3437)

* Increase waitForPortClosed timeout to 60s (#3483)

* Added validation logic to allow selectResource param type in extensions.yaml (#3489)

* Fix background functions in functions:shell (#3491)

* 9.13.0

* [firebase-release] Removed change log and reset repo after 9.13.0 release

* Fix ext:update issue where local extension is incorrectly inferred as published extension (#3499)

* Add missing changelog entry for #3499 (#3500)

* Fix init hosting:github (#3503)

* 9.13.1

* [firebase-release] Removed change log and reset repo after 9.13.1 release

* Avoid emulator data loss when there an error during export (#3511)

* Ask before overwriting storage.rules (#3510)

* Update CONTRIBUTING.md (#3513)

added note to run `npm install` before `npm link` the first time

* Release Cloud Firestore Emulator v1.13.0. (#3515)

* Basic create support

This change adds support for `firebase --open-sesame golang`.

After running this command, `firebase init` will support Go 1.13
as a langauge for Cloud Functions.

Limitations:

1. .gitignore is empty
2. Customers cannot mix Node and Go code (WAI)
3. There is little validation being done of customer code
4. The actual deployed function params are hard coded; SDK incoming

* Use vendoring to fetch SDK

* Update sample code

* Simplify unarchive pipe

* TSLint

* PR feedback

* Delete Container Registry images left after Functions deployment (#3439)

* Delete Container Registry images left after Functions deployment

* Simplify caching

* Improve error handling and report next steps to users

* lint fixes

* Fix typo

* Increase max function ID length to 63 (#3521)

* Fix crash when deploying zero functions. (#3520)

Previously most code read the desired backend from
`options.config.get("functions.backend")` which was set to the
empty backend correctly. Code that depended on payload.functions.backend
crashed because payload.functions was null when the backend was
empty.

Since optins.config should be firebase.json data, this change
normalizes on payload.functions.backend and ensures that it
is never null while options.config.get('functions') is present
(i.e. when the customer has functions to deploy).

* Use proper replace and get commands

* Update changelog with my recent pushes (#3522)

* 9.14.0

* [firebase-release] Removed change log and reset repo after 9.14.0 release

* Bump glob-parent from 5.0.0 to 5.1.2 (#3472)

* Added deferred provisioning check for Storage and Authentication during extension install (#3497)

Implemented provisioning check helper which checks whether products use by the extension are fully provisioned.

* Generate JSON Schema for firebase.json (#3505)

* Fetch from newly public GH repo

* PR feedback

* Format

Co-authored-by: davidbrenner <david.a.brenner@gmail.com>
Co-authored-by: Fred Zhang <fredzqm@google.com>
Co-authored-by: Sam Stern <samstern@google.com>
Co-authored-by: Andrew Heard <andrew@wizheard.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Bryan Kendall <bkend@google.com>
Co-authored-by: Abe Haskins <abeisgreat@abeisgreat.com>
Co-authored-by: Enrico Graziani <mrenrich84@gmail.com>
Co-authored-by: Pavel Jbanov <pavelgj@gmail.com>
Co-authored-by: Google Open Source Bot <firebase-oss-bot@google.com>
Co-authored-by: huangjeff5 <64040981+huangjeff5@users.noreply.github.com>
Co-authored-by: davidbielik <davidbielik@users.noreply.github.com>
Co-authored-by: Yuchen Shi <yuchenshi@google.com>
devpeerapong pushed a commit to devpeerapong/firebase-tools that referenced this pull request Dec 14, 2021
@bkendall bkendall deleted the ss-follow-up-3420 branch March 18, 2022 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Manual indication that this has passed CLA.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants