-
Notifications
You must be signed in to change notification settings - Fork 56
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
Improvement for DataSnapshot paths (#10, #26) #32
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.
I still need to take a more detailed look, but my high level feedback is that path supplied to makeDataSnapshot
should populate context.params
, not the other way around. Snapshots represent a particular database write that happened, so wildcards should not be supported in their construction.
That seems reasonable. Let me know what you think once you take a good look and we'll make it work one way or the other! |
Alright, dropped out snapshot path population from params, so now params is populated from snapshot path and not the other way around. Also added some better logging for when a dev accidentally passes URL with wildcards. |
…into ah-datasnapshot-params
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.
You haven't fully removed the functionality for populating the snapshot's path from params. See inline comments.
As well, I would like to avoid casting the data as any
, since bugs are harder to catch and the code is harder to maintain down the road. Your code currently also does not handle the case when the function is onWrite
, therefore data is actually a Change object as opposed to a snapshot. It also doesn't seem to handle Firestore, which faces the same usability challenge.
Some suggestions:
- Modify database.makeSnapshot and firestore.makeDocumentSnapshot to throw if there's a wildcard in the path provided
- Within
wrap
, check__trigger.eventTrigger.eventType
to see if the function being wrapped is RTDB or Firestore, and whether it's onWrite or onCreate/onDelete - Depending on the check above, check
data
to ensure it is an instance ofDataSnapshot
,DocumentSnapshot
,Change<DataSnapshot>
, orChange<DocumentSnapshot>
, throw error otherwise. - Once you are assured the data is the right type, you can cast it as such. Proceed to get its path, and construct the params from it.
'hello world', | ||
'/ref/{wildcard}/nested/{anotherWildcard}', | ||
); | ||
const params = { |
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 you make makeDataSnapshot throw, instead of only catching it later when wrapped is called.
spec/main.spec.ts
Outdated
expect(result.context.resource.name).to.equal('ref/cat/nested/that'); | ||
}); | ||
|
||
it('should error when DataSnapshot wildcard path does not match resource path', () => { |
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 test is no longer relevant
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 test checks the snapshot's provided path against the route in the function definition, I think that's still relevant because a dev could still path a snapshot which has a completely wrong path for a trigger, right?
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.
Ah, I see now, it is a poorly written test, but the intent is still useful, I think. I've changed it to..
it('should error when DataSnapshot path does not match trigger template', () => {
const fft = new FirebaseFunctionsTest();
fft.init();
const snap = makeDataSnapshot(
'hello world',
'/different/at/nested/bat',
);
const wrapped = wrap(constructCF('google.firebase.database.ref.write'));
expect(() => wrapped(snap, { params })).to.throw();
});
});
Does that seem more right?
it('should not match a path which has different chunks', () => { | ||
const params = _extractParamsFromPath( | ||
'locations/{company}/users/{user}', | ||
'companies/firebase/users/{user}'); |
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.
companies/firebase/users/user
(second parameter to _extractParamsFromPath should not have wildcard, under the normal use of this function)
it('should not match a path which has different chunks', () => { | ||
const differentChunk = _isValidWildcardMatch( | ||
'locations/{company}/users/{user}', | ||
'companies/firebase/users/{user}'); |
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.
companies/firebase/users/user
for same reason as above
const formattedSnapshotPath = _compiledWildcardPath( | ||
unsafeData._path, | ||
eventContextOptions ? eventContextOptions.params : null); | ||
data = makeDataSnapshot(unsafeData._data, formattedSnapshotPath, unsafeData.app) as any; |
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.
Remaking the data snapshot isn't necessary if you are not populating the snapshot's path from params.
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.
That's what I thought, It is necessary for standardizing the path to remove extra /
, however I'll move this logic to makeSnapshot
as you're right that it's a better place for it.
|
||
// Ensure that the same param wasn't specified by the path and the options.params bundle | ||
const pathParams = _extractParamsFromPath(cloudFunction.__trigger.eventTrigger.resource, unsafeData._path); | ||
const overlappingWildcards = differenceWith( |
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 is also not necessary if you do a check within makeSnapshot to ensure the snapshot path doesn't have wildcards.
@abeisgoat Do you have bandwidth to pick this up again? The test is broken and there's been some merge conflicts, but I think we're close! |
I think this has been superseded by #114 |
I agree with this. Marking this as closed, but happy to reevaluate too. |
Description
Fixes common UX issue where context.params are not populated from wildcards in path. (See #10 and #26)
Code sample
New Behavior
New Behavior
I've also added some better logic for ensuring a DataSnapshot's path fits the trigger it is passed to.
Previous / Current Behavior (DataSnapshot Path Checking)
Tests
Added various tests for new functionality which changes DataSnapshot
path
,_isValidWildcardMatch
, and_extractParamsFromPath
.All test pass, canonical uppercase sample tests also pass without change.