-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
feat(example-validation-app): add validation example #4895
Conversation
6def69d
to
a107e7a
Compare
adeb0f4
to
6d5f4d8
Compare
The coverage decrease reported by coverall are in |
|
||
The application will start on port 3000. Open http://localhost:3000/explorer in | ||
your browser. You can try to test the validation for the `/coffee-shops` | ||
endpoints. |
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.
Please point to the document you will be completing in this PR : #4874 . This way, the user won't be frustrated. We shouldn't expect them to dig into the acceptance and unit tests to figure out what steps they should take to test the validation
in the API Explorer.
Great example, by the way :)
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.
👏 Good to have the json spec + interceptor's validation example, mostly LGTM. A few suggestions and minor comments.
*/ | ||
@bind({tags: {key: ValidatePhoneNumInterceptor.BINDING_KEY}}) | ||
export class ValidatePhoneNumInterceptor implements Provider<Interceptor> { | ||
static readonly BINDING_KEY = `interceptors.${ValidatePhoneNumInterceptor.name}`; |
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.
nitpick: I think usually we create a keys.ts
file to expose the bingding keys. It's easy for organizing, especially when turn it into a component.
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.
it's generated by lb4 interceptor
.
examples/validation-app/src/interceptors/validate-phone-num.interceptor.ts
Show resolved
Hide resolved
) { | ||
// Add pre-invocation logic here | ||
const coffeeShop: CoffeeShop = new CoffeeShop(); | ||
if (invocationCtx.methodName === 'create') |
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.
hmm, how about using method level interceptor to generate the instance?
I think the situation is similar to what I did in the access control example's method level voter: before executing the validation/authorization logic, we need do some pre-work based on method.
And I am a bit confused why have to create a new model instance first? Wouldn't the data from request already a model instance?
(Considering this example aims to demo validation. The interceptor details doesn't can be improved in a 2nd round :p)
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.
@emonddr had the same question about instantiating the CoffeeShop instance, but I couldn't find a good alternatives. See discussion: https://github.com/strongloop/loopback-next/pull/4874/files#r392316159. Please let me know if you have a better solution! Thanks.
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.
For method level interceptor, I'm thinking the interceptor should be applied to multiple methods in the CoffeeShopController (create, update, updateById, patch), so that's why i'm using class level interceptor.
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 can still apply the decorator at relevant methods. That might be more explicit.
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.
@dhmlau The method level interceptor can be separated from the global one, e.g. create
method has an endpoint level interceptor which adds the coffeeshop instance to the invocationContext, and the controller level interceptor does the validation.
I am good with the current implementation to land this PR, we can always discuss and improve after it.
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.
Talked to @jannyHou. She was thinking to have the class level interceptor to validate the instance and retrieve the instance based on the method name in the method level interceptor. But it's good with my current implementation.
examples/validation-app/src/interceptors/validate-phone-num.interceptor.ts
Show resolved
Hide resolved
@@ -28,7 +28,7 @@ import {ValidatePhoneNumInterceptor} from '../interceptors'; | |||
import {CoffeeShop} from '../models'; | |||
import {CoffeeShopRepository} from '../repositories'; | |||
|
|||
// Add this line to apply interceptor to this class | |||
// Add this line to apply interceptor to this method |
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 apply the decorator at class level and use if
logic in the implementation to skip other methods.
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 meant to say the comment should be // Add this line to apply interceptor to this class
examples/validation-app/src/interceptors/validate-phone-num.interceptor.ts
Outdated
Show resolved
Hide resolved
@jannyHou @raymondfeng, I've got the "undefined" code working in the interceptor. Please review my latest commit on the changes: 1cecd21. @emonddr, I've modified the README to contain more info on how to trigger the validation error. |
bb0fc66
to
38ed026
Compare
When I used this code I got the error ,, Server is running at http://[::1]:3000 |
38ed026
to
9776f90
Compare
// Add pre-invocation logic here | ||
let coffeeShop: CoffeeShop | undefined; | ||
if (invocationCtx.methodName === 'create') | ||
Object.assign(coffeeShop, invocationCtx.args[0]); |
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.
Does this work? coffeeShop
is undefined at this point. Won't the Object.assign fail if LHS is 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.
you're right. it failed when i'm running the actual app. I've reverted it back to the original:
const coffeeShop: CoffeeShop = new CoffeeShop();
If you have a better solution, please let me know!
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.
ok. Just had webex with Dom, and we have a solution. Updated the PR. Thanks!
20a5881
to
a356baf
Compare
examples/validation-app/README.md
Outdated
npm start | ||
``` | ||
|
||
The application will start on port 3000. Open http://localhost:3000/explorer in |
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.
start on -> listen on?
d4c2a06
to
bf023e8
Compare
@Arathy-sivan, thanks for bringing it up. I've fixed it in the latest commit. Please check again. Thanks. |
@@ -0,0 +1,57 @@ | |||
// Copyright IBM Corp. 2020. All Rights Reserved. |
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 know this is generated automatically, but if it's not needed for the example, can it be removed?
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.
do you mean to remove copyrights for all files in this example?
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.
Oh no sorry, I meant the ping controller.
examples/validation-app/src/__tests__/acceptance/validate.acceptance.ts
Outdated
Show resolved
Hide resolved
Thanks, it's working. |
Hi, Unhandled error in POST /phonemds: 500 TypeError: Cannot read property 'slice' of undefined |
@Ararathy-sivan Ensure that your interceptor is coded to handle this case. |
210849e
to
e8c8fd7
Compare
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.
Nice job 👍
examples/validation-app/src/index.ts
Outdated
|
||
const url = app.restServer.url; | ||
console.log(`Server is running at ${url}`); | ||
console.log(`Try ${url}/ping`); |
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.
Remove this line too
3b91e25
to
3c87a5e
Compare
FYI - The decrease in coverage complained by coverall are from other examples which I didn't change. |
Related to: #4874
Add a validation example.
Next step:
Files changed apart from the generated files:
Checklist
👉 Read and sign the CLA (Contributor License Agreement) 👈
npm test
passes on your machinepackages/cli
were updatedexamples/*
were updated👉 Check out how to submit a PR 👈