-
Notifications
You must be signed in to change notification settings - Fork 400
feat: initializeApp idempotency #2947
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: master
Are you sure you want to change the base?
Conversation
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.
Overall LGTM! Added a few comments. Thank you!
* or `options.credential` are defined. This is due to the function's inability to | ||
* determine if the existing {@link App}'s `options` compare to the `options` parameter | ||
* of this function. It's recommended to use {@link getApp} or {@link getApps} if your | ||
* implementation uses either of these two fields in {@link AppOptions}. |
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.
Should we extend the JSDoc with an example?
/**...
* For example, to safely initialize an app that may already exist:
*
* ```javascript
* let app;
* try {
* app = getApp("myApp");
* } catch (error) {
* app = initializeApp({ credential: myCredential }, "myApp");
* }
* ```
*/
src/app/lifecycle.ts
Outdated
} else if (autoInit) { | ||
// Auto-initialization is triggered when no options were passed to | ||
// initializeApp. With no options to compare, simply return the App. | ||
return currentApp; | ||
} else { |
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.
Can we simplify this by using early exits/guard clauses (and removing the nested if else statements)?
If it doesn't work in this case feel free to ignore. For example:
if (this.appStore.has(appName)) {
const currentApp = this.appStore.get(appName)!;
if (currentApp.autoInit() !== autoInit) {
throw new FirebaseAppError(
AppErrorCodes.INVALID_APP_OPTIONS,
`Firebase app named "${appName}" attempted mismatch between custom AppOptions` +
' and an App created via Auto Init.'
)
}
if (autoInit) {
return currentApp;
}
if (typeof options.httpAgent !== 'undefined') {
.....
src/app/lifecycle.ts
Outdated
|
||
// `httpAgent` objects cannot be compared with deepEquals impls. | ||
// Idempotency cannot be supported if one exists. | ||
if (typeof options.httpAgent !== 'undefined') { |
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.
nit: Would it make sense to move this (and below) validation to a separate function (out of initializeApp
) to clean it up a bit?
src/app/lifecycle.ts
Outdated
* @internal | ||
*/ | ||
function validateAppNameFormat(appName: string): void { | ||
if (typeof appName !== 'string' || appName === '') { |
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.
Can we use validator.isNonEmptyString()
here?
firebase-admin-node/src/utils/validator.ts
Line 104 in 26b884f
export function isNonEmptyString(value: any): value is string { |
src/app/lifecycle.ts
Outdated
export function initializeApp(options?: AppOptions, appName: string = DEFAULT_APP_NAME): App { | ||
return defaultAppStore.initializeApp(options, appName); | ||
} | ||
|
||
/** | ||
* Returns an existing App instance for the provided name. If no name is provided | ||
* the the default app name is queried. |
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.
queried
or used
?
* A (read-only) array of all initialized apps. | ||
* | ||
* @returns An array containing all initialized apps. | ||
*/ |
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.
Let's get @egilmorez's review on the new doc changes, please. Thanks!
src/app/lifecycle.ts
Outdated
'name.', | ||
); | ||
AppErrorCodes.INVALID_APP_OPTIONS, | ||
`Firebase app named "${appName}" attempted mismatch between custom AppOptions` + |
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.
Can we simplify this error message? I am not sure Auto Init
is a well known term in the Admin SDK world
Discussion
Update
initializeApp
to return an existing app if one exists with the same name and the sameAppOptions
. However, due to their inabilty to be compared,initializeApp
will throw if an existing app has a configuredCredential
orhttpAgent
.Additionally adds reference docs to
getApp
andgetApps
.Testing
Updated unit tests.
API Changes
Internal: go/fb-admin-init-idempotency
Fixes: #2111