{"_id":"projection-utils","_rev":"7-a012b8f2c9edc300875cc988fafded73","name":"projection-utils","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"projection-utils","version":"1.0.0","description":"Utilities to work with projections (e.g. mongo)","main":"index.js","directories":{"test":"test"},"scripts":{"test":"jest"},"repository":{"type":"git","url":"git+ssh://git@github.com/mixmaxhq/projection-utils.git"},"keywords":["deep","intersect","intersection","mongo","mongodb","projection","query","set","union"],"author":{"name":"Eli Skeggs","email":"eli@mixmax.com","url":"https://mixmax.com"},"license":"MIT","bugs":{"url":"https://github.com/mixmaxhq/projection-utils/issues"},"homepage":"https://github.com/mixmaxhq/projection-utils#readme","devDependencies":{"jest":"^23.3.0"},"gitHead":"3353a4d283714f5cc35d20f11ad7d1b8e206a08b","_id":"projection-utils@1.0.0","_npmVersion":"6.0.0","_nodeVersion":"8.9.3","_npmUser":{"name":"skeggse","email":"skeggse@gmail.com"},"dist":{"integrity":"sha512-8eWY9w4/UUsgsOhe3L0KGTj7cHf3mY3jnoEc9v5gsbAzBy9IkY07XZ9b51WmieJSQs3ZJnS9NAQZu1m+JdAdSQ==","shasum":"37ac9aa6c941041843e2afcae9a01085a3949042","tarball":"https://registry.npmjs.org/projection-utils/-/projection-utils-1.0.0.tgz","fileCount":6,"unpackedSize":20113,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbQ66OCRA9TVsSAnZWagAAprwP/05j4mUNNShtSFzPh69n\nX/NDVxsrD47oFTT6mNDzR13MUFDTPenZXcQqAkJWOTn+2D81tQMaUB8YQlfy\n8WzLQnA8KIr9xLn48a3WG/IPaCuodNUsaCpaeudHjvJIBm8OBzptRDM1PgYa\nJfWHh28Za03icclaFQOLay2jrdxx7PW+jIS1dt+ZHQLYjYjNgEpH+rbEaGrK\nPAdlDy1kDusZXECezxFq+6ErbyfzaC3ylI7+gH/24Dc7AYfFIhtNGGeTHmUk\nwXgZZGVk6uLGcLJtIXmjZhemdp17BH/2/aeodS0ujc+dqmxTsshJb6Iek8Sn\nOaPf3VQaf6tA+ZW4wYERrFwAtW9HUZEYnaj7E3seG0sLcL/azGb2eIIYRd3r\n6d3L4crJRp4u64pjepNPDxvvD5oyij0qGohDkBy98qEMnPgE0AT7Wet4rERQ\noFyTfuc4/htISkDahbRjAnDWknuAP6gmRZu8TfhIF5g/or/BxFjjsIbxCp0V\nMwcrpFxvAsJ+llOuTYDFI6Ued5Z24Za1afFq2XT4zOMCEou/ANGD8fw/FHaL\nzgrTEpM+DiFa+KeBj3ZBtB4N7JK82MRwcexhYdzeM+bc5YNhZT2/On1ozJpu\nm0ytCmazhOt4i/z0M56YqFtEQMuxZkPNHYSSDUebvRRwvXFNmAj4n/wIAppJ\n9+1w\r\n=wi0H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD9OOOl8b+mu9wbNWE7idaW+4ZbhiAtSRSSib+YExMg8AIhAPZzkcVhaSNBqsxXtGVKVnFNkinP2drC+UMh8c2fL5z6"}]},"maintainers":[{"name":"skeggse","email":"skeggse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/projection-utils_1.0.0_1531162254478_0.005974113128196512"},"_hasShrinkwrap":false},"1.1.0":{"name":"projection-utils","version":"1.1.0","description":"Utilities to work with projections (e.g. mongo)","main":"index.js","directories":{"test":"test"},"scripts":{"test":"jest"},"repository":{"type":"git","url":"git+ssh://git@github.com/mixmaxhq/projection-utils.git"},"keywords":["deep","intersect","intersection","mongo","mongodb","projection","query","set","union"],"author":{"name":"Eli Skeggs","email":"eli@mixmax.com","url":"https://mixmax.com"},"license":"MIT","bugs":{"url":"https://github.com/mixmaxhq/projection-utils/issues"},"homepage":"https://github.com/mixmaxhq/projection-utils#readme","devDependencies":{"jest":"^23.3.0"},"gitHead":"7e3d3dd12219c155e80aeea5ae4a698ff9f84044","_id":"projection-utils@1.1.0","_npmVersion":"6.0.0","_nodeVersion":"8.9.3","_npmUser":{"name":"skeggse","email":"skeggse@gmail.com"},"dist":{"integrity":"sha512-SyAjKYd83c9rcBfb4Xpawq0dnPbgOzva2vEaKvdd5rC+6a1MzLyNieqRfT0pas7FBJRyI4JLeuCENpz/Va8mMw==","shasum":"6438b4b6fcdbcd809fa2a79b096efc41a06b02ed","tarball":"https://registry.npmjs.org/projection-utils/-/projection-utils-1.1.0.tgz","fileCount":6,"unpackedSize":26277,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbQ8UzCRA9TVsSAnZWagAAhlEP/R+Ntm0QjiAVpQgO45Vu\nRBKi7mjQHUj/bK2SgDJUxemmzdhnY82HEz0pIBz5uBb5NTXuQW6stDOkEpYP\nY+jTA/ItjudNAnlPEBe7/NPXJkyTFdt/UuxU+YaQJhmwQ/uyXeFCM298zo/E\nGSI3//1CE7s4WVW6DeRTzBsFk0NRoGGSbXTCz0B2+LMWsIcENB3bk4E/Ru9a\njAasSCMfSh3bSiBWaH6gn1veKevdnsYct7NM99R9oCyzeDncuzDnOSbaKyFX\nZljylhnjEyj2iS+PgUmrUk2hjOSsmmN0YIdc1ociT7jbH0ARBENUG8rQegXr\ni0v4DYNuI22Glbuvg/3s2eXxMN0qXHiJPrtX239ZHOXJ9a5c7nd1bVwZsmvS\nlHKbOkRWfoukqKSrcz2wV77lhgA/xw5Due+xp1ULDlifot+Npr6h3r1ZkJ+m\noY9NZKetyuE7dR7CJXVlX68SaAoNtMmjweLWdKrh5GhSVjn+8U8CtKdYwVEO\nInmAZFA5DZYx1G4AIXhLi5Gh1Uey0V/ohoiao1LfFF/3NcJEY39zez0afy+y\n1W4TJpXoAh4B6ijlrKvDjaudK7OctO+123ACfN1QIWSO6Mdq5V88kWQpDp+z\nYhz9cHrvYmBj0v9Gjy3uImAdgLsE+6i2Oo9q/qT3dRIDv1Vw2isqeIXOFmdp\nKOM5\r\n=McCT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCa5y7Zow3YtMW8anX3sYun3dURKaKOhIwnKIvivKaJ2wIgAejdRykCAor57rW954s2HEELwggiq2prN/JDFgkXWaQ="}]},"maintainers":[{"email":"hello@andytran.me","name":"andytran"},{"email":"bradavogel@gmail.com","name":"bradvogel"},{"email":"junk@rith.com","name":"chanpory"},{"email":"chuy@mixmax.com","name":"chuy-mixmax"},{"email":"gaastonsr@gmail.com","name":"gaastonsr"},{"email":"meier.garret@gmail.com","name":"ghmeier"},{"email":"janice@mixmax.com","name":"janicelihuang"},{"email":"jen+npm@mixmax.com","name":"jenskene"},{"email":"liisa@mixmax.com","name":"liisa"},{"email":"logankeahidavis@gmail.com","name":"logandavis"},{"email":"megan@mixmax.com","name":"megantinleywilson"},{"email":"mericsson@gmail.com","name":"mericsson"},{"email":"admin+mixmax-codeship-npm@mixmax.com","name":"mixmax-codeship"},{"email":"olofmathe@hotmail.com","name":"olofster"},{"email":"pricj004@gmail.com","name":"pricj004"},{"email":"srinand@mixmax.com","name":"sbalaji1996"},{"email":"shil.sinha@gmail.com","name":"shils"},{"email":"skeggse@gmail.com","name":"skeggse"},{"email":"ttacon@gmail.com","name":"ttacon"},{"email":"jeffreywear@gmail.com","name":"wearhere"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/projection-utils_1.1.0_1531168051607_0.6580756586634544"},"_hasShrinkwrap":false}},"time":{"created":"2018-07-09T18:50:54.478Z","1.0.0":"2018-07-09T18:50:54.532Z","modified":"2022-05-13T12:04:19.015Z","1.1.0":"2018-07-09T20:27:31.685Z"},"maintainers":[{"email":"skeggse@gmail.com","name":"skeggse"}],"description":"Utilities to work with projections (e.g. mongo)","homepage":"https://github.com/mixmaxhq/projection-utils#readme","keywords":["deep","intersect","intersection","mongo","mongodb","projection","query","set","union"],"repository":{"type":"git","url":"git+ssh://git@github.com/mixmaxhq/projection-utils.git"},"author":{"name":"Eli Skeggs","email":"eli@mixmax.com","url":"https://mixmax.com"},"bugs":{"url":"https://github.com/mixmaxhq/projection-utils/issues"},"license":"MIT","readme":"projection-utils\n================\n\nA set of utilities for working with MongoDB-style projections.\n\nNotably, this project exposes a `ProjectionFieldSet` class that tracks, merges,\nand intersects multi-level projections.\n\nWe do not support symmetric or asymmetric diffing of field sets, as the\nsemantics are not well-defined on mongo projections. A field set that contains\n`users` minus a field set that contains `users.accessToken` would need new\nsyntax to represent the fields under `users` that aren't `accessToken`, or would\nneed knowledge of all existant fields under the `users` subdocument. It's better\nto handle this yourself, using `intersect`, and a whitelist of permitted fields.\n\n### `ProjectionFieldSet`\n\nBasic usage:\n\n```js\nconst permittedFields = ProjectionFieldSet.fromDotted(\n  ['users.id', 'users.email', 'share', 'content']);\n\nconst desiredFields = ProjectionFieldSet.fromDotted(\n  ['users', 'users.accessToken', 'share', 'invalid']);\n\n// The fields we want, where they're permitted.\nconst selectedFields = permittedFields.intersect(desiredFields);\n\n// Add fields that we need for server-side business logic.\nconst mandatoryFields = ProjectionFieldSet.fromDotted(\n  ['internalVersion']);\n\nconst queryFields = selectedFields.union(mandatoryFields);\nconst projection = queryFields.toMongo();\n// => {'users.id': 1, 'users.email': 1, share: 1, internalVersion: 1}\n```\n\nConstructor usage:\n\n```js\n// Equivalent to the first fromDotted invocation in the previous example.\nconst permittedFields = new ProjectionFieldSet([\n  ['users', 'id'],\n  ['users', 'email'],\n  ['share'],\n  ['content'],\n]);\n```\n\nIterate over paths:\n\n```js\nfor (const path of permittedFields) {\n  // path is the array containing the parts of the path, e.g.:\n  // ['users', 'email']\n}\n\n// Or just convert to an Array:\nconst fields = Array.from(permittedFields);\n```\n\nEnumerate dot-joined paths:\n\n```js\nconst dotJoined = Array.from(queryFields.toDotted());\n// => ['users.id', 'users.email', 'share', 'internalVersion']\n```\n\nCheck for field containment, and partial field containment:\n\n```js\nqueryFields.contains(['users']);\n// => false, because only some of the fields in users are included\n\n// equivalent to the above\nqueryFields.containsDotted('users');\n\n// produces the set of fields that are included under the users field\nArray.from(queryFields.get(['users']));\n// => [['users', 'id'], ['users', 'email']]\n\nArray.from(queryFields.getDotted('users'));\n// => ['users.id', 'users.email']\n\n// both produce no items\nArray.from(queryFields.get(['invalid']));\nArray.from(queryFields.getDotted('invalid'));\n// => []\n\n// exclude the users prefix\nArray.from(queryFields.get('users', false));\n// => [['id'], ['email']]\n\nArray.from(queryFields.getDotted('users', false));\n// => ['id', 'email']\n```\n\nExplicitly expand the set of fields:\n\n```js\n// Add users.name to queryFields. Unlike intersect and union, this mutates the\n// ProjectionFieldSet instead of making a new instance.\nqueryFields.widen(['users', 'name']);\nqueryFields.toMongo();\n// => {'users.id': 1, 'users.email': 1, 'users.name': 1, share: 1, internalVersion: 1}\n\n// Expand queryFields to include all fields of users (even accessToken - take\n// care when ordering operations on ProjectionFieldSets, as an intersect won't\n// forbid a set of fields being added to the produced ProjectionFieldSet.\nqueryFields.widen(['users']);\nqueryFields.toMongo();\n// => {users: 1, share: 1, internalVersion: 1}\n```\n\nNote that field sets can be singular. Unioning with a singular value yields a\nsingular value, and intersecting with a singular value yields the non-singular\nvalue. For example:\n\n```js\n// This is distinct from new ProjectionFieldSet([]) (and\n// new ProjectionFieldSet()), which yield an empty fieldset, rather than a\n// singular fieldset.\nconst singular = new ProjectionFieldSet([[]]);\n\nsingular.union(singular);\n// => copy of singular\n\nsingular.intersect(singular);\n// => copy of singular\n\nsingular.union(mandatoryFields);\n// => copy of singular\n\nsingular.intersect(mandatoryFields);\n// => copy of mandatoryFields\n\nconst empty = new ProjectionFieldSet([]);\n\nempty.union(empty);\n// => copy of empty\n\nempty.intersect(empty);\n// => copy of empty\n\nempty.union(mandatoryFields);\n// => copy of mandatoryFields\n\nempty.intersect(mandatoryFields);\n// => copy of empty\n\n\nsingular.union(empty);\n// => copy of singular\n\nsingular.intersect(empty);\n// => copy of empty\n```\n","readmeFilename":"README.md"}