-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Use NPM SimpleSchema rather than Meteor #3331
Conversation
8078627
to
51c4b7d
Compare
@aldeed Hey Eric, I think I speak for everyone when I say we are super-excited to get this work done and to have you doing it. Just starting to review this code now and my first question is that I am unclear on why some of these changes need to be made to support node-simple-schema. I wonder if you could put in some review comments about why some of these changes were made it would make it easier for me to understand what's going on. (this is one area where GH code review is really lacking) I wonder if maybe we could schedule a time to talk to me and/or the team about this and help us understand how node-simple-schema differs from meteor-simple-schema. It's a pretty core part of our project and everyone on the team needs to have a really good understanding of how it works. |
@zenweasel There might be some changes still in here from my trying to debug issues, which I will remove before finalizing. Still need to skim through it all a final time myself. I also fixed some over-reactive autoruns while trying to figure out a bug caused by the updates, but I'll move those changes into a separate PR since they're technically unrelated. I'll add some details about what things were updated as I do another read-through of the diff. Possibly tomorrow or this weekend. |
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.
Scanned through the changes. Will review in more detail, but for now, when I went to test immediately had error in lib/api/catalog.js
getVariants()
Error: You may not pass an array of schemas to the SimpleSchema constructor or to extend()
at SimpleSchema.extend (/Users/aaronjudd/Projects/reaction/node_modules/simpl-schema/dist/SimpleSchema.js:503:40)
at new SimpleSchema (/Users/aaronjudd/Projects/reaction/node_modules/simpl-schema/dist/SimpleSchema.js:127:10)
at ns.Collection.c2AttachSchema [as attachSchema] (packages/aldeed:collection2-core/collection2.js:35:10)
at collections.js (lib/collections/collections.js:85:8)
at fileEvaluate (packages/modules-runtime.js:333:9)
at require (packages/modules-runtime.js:228:16)
at index.js (lib/collections/index.js:1:14)
at fileEvaluate (packages/modules-runtime.js:333:9)
at require (packages/modules-runtime.js:228:16)
at catalog.js (lib/api/catalog.js:1:163)
@aaronjudd Sorry I had more changes I hadn't pushed. I pushed them now, and should include fixing the error you saw. There are still other more hidden issues I'm investigating, but I think it's getting close. |
0c2a772
to
bb622a6
Compare
bb622a6
to
982f9c1
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.
General changes:
- Passing arrays to SimpleSchema is no longer supported, so instead I use
clone().extend({})
check
andTracker
need to be passed as options to everySimpleSchema
constructortype: [Type]
isn't supported for arrays, so instead it'stype: Array
plus a specific separate key for the array items- autoValues work differently now, only setting the value if the parent object exists. Many places in Reaction were relying on the old behavior of an object being auto-created, so I've retained that behavior where necessary by adding
defaultValue: {}
on the object key's schema. - Changed Number to SimpleSchema.Integer and Number+decimal to just Number
- New SS doesn't work with
check
package, so these usages in methods have been changed toschema.validate()
, which does the same thing. It still satisfies audit-argument-checks due to passingcheck
into the SS options. - invalidKeys renamed to validationErrors
- Use bypassCollection2 option on migration operations. This is best practice to avoid schema errors since the schema changes over time
// If it's not an array, the filter should match exactly | ||
return item[property] === itemFilter[property]; | ||
return Array.isArray(itemVal) ? itemVal.includes(filterVal) : itemVal === filterVal; |
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 was checking the schema to see if it should be an array, but it actually makes more sense to just check if the value is an array.
client/modules/core/main.js
Outdated
|
||
return defaultValue || undefined; | ||
const prefs = userPrefs.get(); | ||
return prefs && prefs[packageName] && prefs[packageName][preference] || defaultValue || 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.
Not sure why, but I had problems with this while trying to fix SS issues. Before it would react every time anything about the user record changed whereas now reactivity is limited to the prefs changing.
client/modules/core/main.js
Outdated
}); | ||
} | ||
return false; | ||
const userId = Meteor.userId(); |
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.
Just a small change here to remove an unnecessary Meteor.user()
call. This matters more on the server than on the client (Meteor.user() would hit the database every time whereas userId would not), but it's still a good habit for client code, too.
client/modules/core/startup.js
Outdated
if (!userId) return; | ||
const user = Meteor.users.findOne(userId, { fields: { profile: 1 } }); | ||
userPrefs.set(user && user.profile && user.profile.preferences || 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.
This is used by the rewritten getUserPreferences
function.
client/modules/i18n/main.js
Outdated
@@ -42,23 +43,21 @@ export function getBrowserLanguage() { | |||
export function getLabelsFor(schema, name) { | |||
const labels = {}; | |||
// loop through all the rendered form fields and generate i18n keys | |||
for (const fieldName of schema._schemaKeys) { | |||
Object.keys(schema.mergedSchema()).forEach((fieldName) => { |
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.
Gotta do this differently since subschemas aren't automatically merged in the new SS
server/imports/fixtures/orders.js
Outdated
@@ -130,17 +130,20 @@ export default function () { | |||
requiresShipping: true, | |||
shipping: [{ | |||
shopId: getShopId(), | |||
address: getAddress({ isShippingDefault: true }), |
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.
These missing props were causing test failures. I'm pretty sure they were always improperly missing, but for some reason the old SS package didn't catch the errors I guess.
_id: { | ||
$nin: [productId] | ||
} | ||
}).count(); |
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 fixed an infinite loop I was seeing, though I don't recall how to reproduce it. It should be obvious reading the code that the $nin should have been there.
}); | ||
return done(); |
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.
done
was called too early with these on the outside
result = Meteor.call(`${processor}/payment/capture`, paymentMethod); | ||
} catch (e) { | ||
error = e; | ||
} |
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.
The only change here is that the Meteor.call of ${processor}/payment/capture
is now synchronous (has no callback). Before this change, I had tests failing because that call would still be executing after the test had already finished and removed the sandbox data. Doing it synchronous seems like it would be better in real world, too, but on the off chance that this was intentionally async, there might be a different solution by rewriting how the tests work.
server/startup/init.js
Outdated
ddpError.error = "validation-error"; | ||
ddpError.details = error.details; | ||
return ddpError; | ||
}); |
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.
Not sure if this is the proper file to put this in. Let me know if you want it moved.
@zenweasel @aaronjudd I think this is pretty close. Finally figured out all the pesky bugs and got tests passing (on my machine at least). This was much more difficult than I thought, mainly because all of your crazy schemas illuminated several edge case bugs in SimpleSchema. But the good news is that I feel quite confident in npm SimpleSchema now. I ran through some screens, but I'm not an expert on the app workflows, so it would be helpful to have some manual testing through common flows and with common plugins. |
Seeing this error on startup:
|
See this error when I add a product and set the price:
|
@@ -11,7 +11,7 @@ Meteor.methods({ | |||
// Under consideration for deprecation and migrating other payment Packages | |||
// to payments-stripe style methods | |||
"cart/submitPayment": function (paymentMethod) { | |||
check(paymentMethod, Reaction.Schemas.PaymentMethod); |
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 think this is actually a pretty important check here that shouldn't just be switched to Object
. If the paymentMethod
doesn't have specific values it's going to fail hard upstream and we should catch it here.
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.
@zenweasel It might be possible to use the schema, but the problem I was having with using the schema in some places like this is that the payment method being passed is somewhat different from what ultimately goes into the DB, either because of default values or for some other reasons. This object is validated against the schema already as part of the update call on line 59, so it seemed like checking it here is a bit superfluous anyway.
@@ -42,7 +41,6 @@ describe("discount rate methods", function () { | |||
expect(discountInsertSpy).to.have.been.called; | |||
|
|||
const discountCount = Discounts.find(discountId).count(); | |||
Meteor._sleepForMs(500); |
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'm getting test failures re-introduced by removing these sleeps.
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.
Is it okay if I try to fix the code instead? Needing to sleep for tests is a tenuous fix and just ignores the fact that failures due to timing usually mean poorly written code.
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 sure. I would love to get these really fixed. Just pointing out that the tests are failing intermittently now.
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.
Just a few style notes
@@ -2,7 +2,7 @@ | |||
import Shippo from "shippo"; | |||
import { Meteor } from "meteor/meteor"; | |||
import { ValidatedMethod } from "meteor/mdg:validated-method"; | |||
import { SimpleSchema } from "meteor/aldeed:simple-schema"; | |||
import SimpleSchema from "simpl-schema"; |
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.
import order
lib/collections/schemas/products.js
Outdated
import { Meteor } from "meteor/meteor"; | ||
import { Random } from "meteor/random"; | ||
import { SimpleSchema } from "meteor/aldeed:simple-schema"; | ||
import { Tracker } from "meteor/tracker"; | ||
import SimpleSchema from "simpl-schema"; |
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.
import order
server/api/core/core.js
Outdated
* that have been attached to the collection or false if | ||
* the collection or schema could not be found | ||
*/ | ||
collectionSchema(collection, selector) { |
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 provide any sort of deprecation path there rather than just removing this in case application developers are using it?
@@ -104,6 +104,7 @@ describe("Account Meteor method ", function () { | |||
const newAddress = account.profile.addressBook[ | |||
account.profile.addressBook.length - 1]; | |||
delete newAddress._id; | |||
delete newAddress.failedValidation; |
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.
Why are we deleting this here?
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.
Because it is added to the doc automatically due to a defaultValue. I'm not sure why it wasn't an issue prior to my changes, but I'm pretty sure the defaultValue was always there. If you don't want to delete it, then it could be added to the original address being inserted.
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.
No, I was just trying to understand why we were deleting it
import { check, Match } from "meteor/check"; | ||
import { SimpleSchema } from "meteor/aldeed:simple-schema"; | ||
import SimpleSchema from "simpl-schema"; |
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.
import order
server/startup/init.js
Outdated
@@ -1,6 +1,18 @@ | |||
import { Meteor } from "meteor/meteor"; | |||
import SimpleSchema from "simpl-schema"; |
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.
import order
I don't seem to be getting any validation error when saving invalid settings in any of the settings panels (as an example, remove "Company Code" from the Avalara tax method and it should throw an error but does not). |
This is looking really close, fantastic. I see id/react/validation issues in Taxes, Accounts, Login Services but verified that these console errors all exist in master as well, so not apparently introduced here. The lack of validation, as reported by Brent I am able to replicate as well in the Avalara panel, and is not reproducible in master. Most other forms do seem to have validation though. I noticed the sort order of the packages (as seen in the icon-side-bar) are different in master versus this branch. Fatal error in checkout address validation, reproducible by adding address in checkout...
I'll keep poking, but that one at least is a blocker. |
@aldeed Don't forget to enter yourself for the Hack-a-bug-a-thon We are giving away a $1000 gift card and other prizes |
@zenweasel @aaronjudd So far I have fixed the following:
Still need to fix:
|
Tested and this last issue seems to be fixed. |
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.
All issues resolved. 👍
When this will be merged to master? |
Merge in 1.8.0 and fixed conflicts |
Oh my god, this was already working in release branch why you didn't merge it? |
@DenisBogatirov there's still breaking tests and some conflicts that needed cleaning up. Originally we weren't going to release this until the 2.0 release (big changes), but as it's looking pretty close, I've tagged this for 1.9 release (next week), so hopefully it'll be merged pretty quickly. @aldeed is actually on vacation though, so waiting on him to return, before we do a final review and merge. |
the merge conflicts 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.
Conflicts resolved, tests passed. Merging.
@aldeed new issue found (after merge into 1.9) -> can create a new issue but thought it'd be useful here: Seen clicking on "Tax" in sidebar, or opening any of the tax settings:
|
BREAKING CHANGES
This PR updates the
aldeed:simple-schema
Meteor package dependency to instead depend on thesimpl-schema
NPM package, which is the newest release of the same library. As part of this change, there are several breaking changes and other gotchas to be aware of..meteor/versions
file. Make sure thataldeed:simple-schema
is not listed. If it is there, that is because you depend on another Meteor package that depends onaldeed:simple-schema
. You will have to update or remove any such packages (withmeteor remove
/meteor add
) untilaldeed:simple-schema
disappears from your.meteor/versions
file.import { SimpleSchema } from "meteor/aldeed:simple-schema"
lines that you have added in your custom code, and replace them withimport SimpleSchema from "simpl-schema"
simple-schema
with the "e", and that is NOT the one you want.)attachSchema
in your code, be aware that passing an array toattachSchema
will no longer work. You should first merge all the schemas and then pass the combined schema toattachSchema