{"_id":"@90soft/parse-server-kit","_rev":"19-317e873f522bf52c225bab06ccc84b09","name":"@90soft/parse-server-kit","dist-tags":{"latest":"2.10.1"},"versions":{"1.0.0":{"name":"@90soft/parse-server-kit","version":"1.0.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@1.0.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"0383dd0f4ba6966477f7bc55dc00897f14610dc4","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-1.0.0.tgz","fileCount":17,"integrity":"sha512-+b1ewXDp/r86jkIRDSCfIqlFDaYjR90qFrkjlgmOveD2IwS4MXu+v6E9R1s2SbcYOy/sP6t0YvTzER2ctzK+BQ==","signatures":[{"sig":"MEUCIGizNvKpRWm9aR1PaNAvvqnHD54/9voee2srSqsiCQDdAiEA8IvUFR3itFwfQa3tmk9ExUjH7D+y9ChwntsxQulq7AI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37021},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"9b632f0c9773d7845e625a480b0ef22e111fffb3","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Decorator-driven development kit for Parse Server — @ParseClass, @ParseField, BaseModel, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","typescript":"^5.5.0","@types/node":"^20.0.0","reflect-metadata":"^0.2.2"},"peerDependencies":{"parse":">=5.0.0","reflect-metadata":">=0.1.13"},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_1.0.0_1775741166736_0.6250049657725876","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@90soft/parse-server-kit","version":"2.0.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.0.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"fc7e3d5487adb5eed50447cf385d39e85f51e55a","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.0.0.tgz","fileCount":97,"integrity":"sha512-T7xx3Wb4sxcva/mMmwU4fmw5ncrjga+xdSwv62JgGE32ucQuWFV0WUfjOW1A8YWpagV3d9Fu8w0cInT93b63sg==","signatures":[{"sig":"MEYCIQDjaeljmibBy8stt6yhKrge3X8KXopXN58WL3qkPsriEQIhAJILAEpVXDMoKavS3j8qmRgO8P1cyHMTq5qgeGomnx/Y","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":174329},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"19e5bd3bcf168d620dba4323761e968ae4f4c05c","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.0.0_1775742083673_0.3757847604192128","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@90soft/parse-server-kit","version":"2.0.1","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.0.1","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"0ccf3f933f8f69ce44b5dd2e6c56543a23fd2caf","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.0.1.tgz","fileCount":98,"integrity":"sha512-uAWy+iL1pSsvcODyFck+8NSCLqQvjC8CoXGId4tWyUdqVF9now5h+I/9iwopRDb0fTMoeAGbTXjvRCO2ib6rCg==","signatures":[{"sig":"MEUCIQDKZQ5v3xGvK5MUxWxUJH7WAhx4uyBu+dxbIlZPBONYxgIgAoaaVuF6SosYcaFm+Eg1ZboaZjA0bgjbbQ/hawnrJuo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":188760},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"8c1f3e858aecb83cd6df31c152f1ac4594c39426","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.0.1_1775987747129_0.7443564262875124","host":"s3://npm-registry-packages-npm-production"}},"2.0.2":{"name":"@90soft/parse-server-kit","version":"2.0.2","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.0.2","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"1c9afe4f67dc78001b603b0cdc50e72cc064e980","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.0.2.tgz","fileCount":98,"integrity":"sha512-anLBYce/staZvfknadBAyydlbINDIb5qEulSN/avbQjxjFNws/y2KDeRn44dhpNaUncNir67csmnPxn1rSkb8Q==","signatures":[{"sig":"MEYCIQD4XWZ0sqfyo0U9Ol27VeYer7D2nWMkFlc1i8LGShlrIgIhAMvWhGfnANqrBh7j173rNBnSlhZwUh1fU5p19iAs90UK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":191579},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"2e12a97734aefdf8dbbfc6d1524bccedc5f6c432","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.0.2_1775988416562_0.8779903527460309","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@90soft/parse-server-kit","version":"2.1.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.1.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"e476f0f9dacaf938336f7979e974e19df7d75ea9","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.1.0.tgz","fileCount":102,"integrity":"sha512-J8/zdaRhKbKOtOZpMYaeugY4hBy9Al5dIEsiPu9nPDEQMkqYduN3/lkXnDPXD1plwQL506bTQCrer7G5DUDD9g==","signatures":[{"sig":"MEQCIELOHhZWRCR3Pe6MjF6yuc2uYu8HLgiiZ9TX4SW+efFvAiAown2Ij3sbZS4WlU+n22wdN+or3V5IDxz7l+hANL8vjg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":197023},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"6fc2dc247d660134df334e5b5bbd7292dd8bd419","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.1.0_1775989950727_0.14634134249503616","host":"s3://npm-registry-packages-npm-production"}},"2.2.0":{"name":"@90soft/parse-server-kit","version":"2.2.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.2.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"d9b59739f22b329aecbae700839d021731443abc","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.2.0.tgz","fileCount":102,"integrity":"sha512-XCN0gHVWxisoZvqTFzvaS8+QK/fqUD5gDSBzYo44oqbSCTfqTbWGtCBoIwyg75eRYr1pnlf9eSgiMgy0cPL+BQ==","signatures":[{"sig":"MEQCIHca5dNYbCfvCQqqmtrhvxUoaPC+kgLObtGtBC8g0yXVAiAGpv7NwsT4Mmfw/ZJBXJ19T4NWOOf8XNgMzH3PovpJEA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":197708},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"1d4279e23eb685daaf6e4afbc65b1ec4e6dc9db0","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.2.0_1775992133390_0.7577597291958398","host":"s3://npm-registry-packages-npm-production"}},"2.3.0":{"name":"@90soft/parse-server-kit","version":"2.3.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.3.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"370dc8dbb728410491c67842a61944a75828d552","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.3.0.tgz","fileCount":102,"integrity":"sha512-6v5zkQ3FYSi1XGoEDzGnS8wdfE3lbC4jCRCrFMipPs+Sog9sjOQ8/4SXfrbu0LuTAFvoIDnEzSYCLv+MQKvrKw==","signatures":[{"sig":"MEYCIQDQMGFco8hOtWpoVvXX1OCvA0l0CcyeKYgncP/1Oa++WAIhAL/Q5ydOWyzMU2K5iFpk8AlgrM6aSRT53x78lLBV7mBx","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":194063},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"0e3cd6542fb9fe883d809236656f01f679b27a99","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.3.0_1775992442397_0.796108460983606","host":"s3://npm-registry-packages-npm-production"}},"2.3.1":{"name":"@90soft/parse-server-kit","version":"2.3.1","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.3.1","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"0cdb0b6261ddd0ab72f24ed375bebb3ca74c5883","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.3.1.tgz","fileCount":102,"integrity":"sha512-F2PnjlYho6oQjC4jqssEon1/YE2j8MUwKOUmRlNXb0lXrU+DD4cdHDpgzGTv4g+wDgmT3hsDXPrWYzkrwhU92A==","signatures":[{"sig":"MEQCIH3WiAfKmuE1HDn327LIz1NG1QabgV78ZHqD7XboztYPAiBorlzMwwQ86r14q7NelubyBT5kERtKkSCZvRwTtgqquA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":194434},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"dddc8ee292ee041496ba2698c0b0a275136acf35","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.3.1_1775993178099_0.8430897600532434","host":"s3://npm-registry-packages-npm-production"}},"2.4.0":{"name":"@90soft/parse-server-kit","version":"2.4.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.4.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"78dcfae8bd275ff14c98249859f8c6436d218cc5","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.4.0.tgz","fileCount":110,"integrity":"sha512-eutC4LwgKXN4CSs8ujGozKPnGd7NMDN41T9YbQCiR+SPyPUYhK/7xR5KjUoPFzGz7EUzF5TPT+MsmH1AShwdyw==","signatures":[{"sig":"MEUCIGF9fPw3nDhBeNiu18n79C32fTZhyP6ls80GbqAhfG9kAiEAtw0qAlWOtqzEoUQPGWrpljum6L77ETPXPCQ31ZlSrlw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":214756},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"ec14d7f85f40c068f40fa19c48e42dd3e025054c","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.4.0_1775994303402_0.3055734476997507","host":"s3://npm-registry-packages-npm-production"}},"2.5.0":{"name":"@90soft/parse-server-kit","version":"2.5.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.5.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"e98ec65dc371b684fcd1d7deb2b34554a02519af","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.5.0.tgz","fileCount":110,"integrity":"sha512-2b5EYZcvMrqN18u8sgJvDSqVtGCjlwSr7BmNibusrtyPj6YRIUzcbI8XzBS5jQ8/LbhpYwPBNqgg+5e2jQBdRg==","signatures":[{"sig":"MEUCIQC625AWxds9n8WRSSDbB1TKauZ3+5j4ddc3/Q6TSTlPqAIgPIVrSIUhxUikzRQmhopS0/sUbiFGFBmjk7mbFqqvXlE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":228929},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"ec14d7f85f40c068f40fa19c48e42dd3e025054c","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.5.0_1777977722584_0.7432428280696426","host":"s3://npm-registry-packages-npm-production"}},"2.5.1":{"name":"@90soft/parse-server-kit","version":"2.5.1","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.5.1","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"b17d53c7b2168fa178f52900e9a650daebca41df","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.5.1.tgz","fileCount":110,"integrity":"sha512-QT5j68+fpojO0zFD0T9EPVJPhUx6CnafoLQtJSfpMvdvyDGooKMKLUn2nx8htHsKxZENcKxHHHjidzi129KFBQ==","signatures":[{"sig":"MEUCIQC0tihhQn+A0RfuDKUc/Ux32DyjEWBEW/G51jl10MzzrgIgKGSw1GaqV0j667lV0j9bM8869f+LnrHqaDiQKtRHIVM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":233413},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"ec14d7f85f40c068f40fa19c48e42dd3e025054c","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.5.1_1780832266163_0.6912640719451884","host":"s3://npm-registry-packages-npm-production"}},"2.5.2":{"name":"@90soft/parse-server-kit","version":"2.5.2","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.5.2","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"9d7e730ecd71e01a6b833bf0c1755546df3b2f52","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.5.2.tgz","fileCount":110,"integrity":"sha512-dMgrAHM6KO17BMOhx3tLIVVGUVpO+3CEEEzZ3SXcNZ6RBPtReV+mfuCVYCXlF9xvKK3OU4EjpK7+mB/ShYL02g==","signatures":[{"sig":"MEUCIHeNjDhFDlTyuV7oFuT4DhUhnHSLmTSE+vPbhm3xySvvAiEAhSmdHJlMbGa5mV4NXIS6Hxx7wZPQy9pysDu7qbqVKIs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":235056},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"ec14d7f85f40c068f40fa19c48e42dd3e025054c","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.5.2_1780833567010_0.08307604340041697","host":"s3://npm-registry-packages-npm-production"}},"2.5.3":{"name":"@90soft/parse-server-kit","version":"2.5.3","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.5.3","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"f0b4993109667e790fb4121ebb8388de7ba745a2","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.5.3.tgz","fileCount":110,"integrity":"sha512-7wYz7b2xrg+Ut0q58gVqdWT6vpVIja1Ed13WvEdiTjer7olXCMAd4HlOwTiRUeWt2XH9d2KWzelYZUZhd5OBrw==","signatures":[{"sig":"MEUCIAGN+m8ErrUHBO9Z5MXdmT7ZrZcgIgz/6Cmafn9PRfjOAiEAiTll9NHyBH7L2kc2kKlw8kPEC6cbhluYq8VWi3qQywc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":236690},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"cdbdc5e0572a3c65feb8ca8cb0fb8dbfb246c892","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.5.3_1782123754135_0.7754192498282535","host":"s3://npm-registry-packages-npm-production"}},"2.6.0":{"name":"@90soft/parse-server-kit","version":"2.6.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.6.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"201b0c7e8382eb10b455f756fe717fba92f6c3c3","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.6.0.tgz","fileCount":114,"integrity":"sha512-ugYlhxcNmbceK8LXwQodrNdR8ZI6tcfNPWE2ylrUW9o3Qg7UZy2T34QyCcGYJyUghEOgua4ktLf16Ttmkqe98A==","signatures":[{"sig":"MEQCIG6QV0E4tOoad+6sLt8rpS4ULADSiPE4b3ofLXPq/17gAiAUpyniYJzvF91Ax8RVrQyOnhNIWo4FzMlsFBOQM1ET5A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":243696},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"cdbdc5e0572a3c65feb8ca8cb0fb8dbfb246c892","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"parse":"^5.3.0","express":"^5.0.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/node":"^20.0.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"node-cron":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.6.0_1782382997662_0.8115961199712907","host":"s3://npm-registry-packages-npm-production"}},"2.8.0":{"name":"@90soft/parse-server-kit","version":"2.8.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.8.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"d3d3d7b709cf133a3a1c4d214c4d5e2117fca029","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.8.0.tgz","fileCount":130,"integrity":"sha512-GrBOZDYqwI9jOKry1DNuODzpnCJ8sGEznxU5qL2RR2u+geTqmnMvb85l2+CXDGCDtHOubGZIVHrRsDw2i43WXw==","signatures":[{"sig":"MEUCIG70qPOQmnpWIm9EkJb0lV5W003EzRdGshbPVbg5nCHVAiEAlztBGXjZGtzRm+Ltv2fnN1pC3IM6k5Hdp5nrRQ2uHG0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":317404},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"c9cde5ace8934b992bd050daa842f8a4a3068083","scripts":{"test":"jest","build":"tsc","test:all":"npm test && npm run test:integration","prepublishOnly":"npm run build","test:integration":"NODE_OPTIONS=--experimental-vm-modules jest --config jest.integration.config.js"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","parse":"^5.3.0","express":"^5.0.0","ts-jest":"^29.2.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","parse-server":"^9.10.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1","mongodb-memory-server":"^11.2.0"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","node-cron":">=3.0.0","@types/parse":">=3.0.0","parse-server":">=8.3.0","reflect-metadata":">=0.1.13","swagger-ui-express":">=4.0.0"},"peerDependenciesMeta":{"node-cron":{"optional":true},"@types/parse":{"optional":true},"parse-server":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.8.0_1786877879550_0.2837648273076163","host":"s3://npm-registry-packages-npm-production"}},"2.8.1":{"name":"@90soft/parse-server-kit","version":"2.8.1","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.8.1","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"ad42469d0c2c42241baabb7b8d9d13d1f48488f5","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.8.1.tgz","fileCount":131,"integrity":"sha512-BHH4ui4T8WvHFZbrBljzD71xcZh61RZpxB9DrWq37/ZJHSiS4965gtkSxTHjCEHCjuu1w5agONAw82ftrDDCnA==","signatures":[{"sig":"MEUCIQDrr+uwYCRMSk2W6alR60Hl7Ctjhxjw479ilIM1slG2vgIgbKv7pH81T1jG68+HPKnbRrK7kzOBjlogywykJv6/pRQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":342062},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"c23d40f947facbfe15d939be170722186fc53eaf","scripts":{"test":"jest","build":"tsc","test:all":"npm test && npm run test:integration","prepublishOnly":"npm run build","test:integration":"NODE_OPTIONS=--experimental-vm-modules jest --config jest.integration.config.js"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","parse":"^5.3.0","express":"^5.0.0","ts-jest":"^29.2.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","parse-server":"^9.10.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1","mongodb-memory-server":"^11.2.0"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","node-cron":">=3.0.0","@types/parse":">=3.0.0","parse-server":">=8.3.0","reflect-metadata":">=0.1.13","swagger-ui-express":">=4.0.0"},"peerDependenciesMeta":{"node-cron":{"optional":true},"@types/parse":{"optional":true},"parse-server":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.8.1_1786878484006_0.38178332880700294","host":"s3://npm-registry-packages-npm-production"}},"2.8.2":{"name":"@90soft/parse-server-kit","version":"2.8.2","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.8.2","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"efab6232b4618c9cc95d43fa1a74b20395f56825","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.8.2.tgz","fileCount":131,"integrity":"sha512-6Dm+E215VZ/rqQTAj7/eKJwgZAR1vQK4sEXGOM6y+5mVsQZDo8BcBvotnLdB9TM3PbRnhe5uibVYGrRNHa6r9g==","signatures":[{"sig":"MEUCIF/ICEv4KybVmWkZ81DSqmo/SiGza6YxpL9FxiGDyFOkAiEAgpAa7/GUn8TBkfj0Fs1xZ0SnM3KDVqdtJOKWEhJuuis=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":344628},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"9cac35f6068a13feb0d6b697a1ac04ae157a4875","scripts":{"test":"jest","build":"tsc","test:all":"npm test && npm run test:integration","prepublishOnly":"npm run build","test:integration":"NODE_OPTIONS=--experimental-vm-modules jest --config jest.integration.config.js"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","parse":"^5.3.0","express":"^5.0.0","ts-jest":"^29.2.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","parse-server":"^9.10.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1","mongodb-memory-server":"^11.2.0"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","node-cron":">=3.0.0","@types/parse":">=3.0.0","parse-server":">=8.3.0","reflect-metadata":">=0.1.13","swagger-ui-express":">=4.0.0"},"peerDependenciesMeta":{"node-cron":{"optional":true},"@types/parse":{"optional":true},"parse-server":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.8.2_1786879768806_0.6501733884875223","host":"s3://npm-registry-packages-npm-production"}},"2.9.0":{"name":"@90soft/parse-server-kit","version":"2.9.0","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","_id":"@90soft/parse-server-kit@2.9.0","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"dist":{"shasum":"1d76a8289ce45d1b422f51d280be8e64cfd0dba7","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.9.0.tgz","fileCount":135,"integrity":"sha512-Ng/Ft9gKfpHBb2pf7yNdhwZ2n9LoMeOvTngh/N6qBQVB5QPqAZMTV+92Cm10b9BVuQ0IfgE4E72uw1wknW4hoA==","signatures":[{"sig":"MEUCIQCgCU83JLt9+BJ24ZX1xvEzhJYSnvZjnFgI96im6kax9wIgA37hAlm1TqM2V5PyepkrLYzu1/sRdK1Eteqzs+P8BUk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":363984},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"047f0eb879a33fdf09d0d2f8bd4322c6367730f1","scripts":{"test":"jest","build":"tsc","test:all":"npm test && npm run test:integration","prepublishOnly":"npm run build","test:integration":"NODE_OPTIONS=--experimental-vm-modules jest --config jest.integration.config.js"},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"repository":{"url":"https://git.90-soft.com/90_soft/parse-server-kit.git","type":"git"},"_npmVersion":"10.8.2","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","directories":{},"_nodeVersion":"20.19.3","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","parse":"^5.3.0","express":"^5.0.0","ts-jest":"^29.2.0","node-cron":"^4.0.0","typescript":"^5.5.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","parse-server":"^9.10.0","@types/express":"^5.0.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1","mongodb-memory-server":"^11.2.0"},"peerDependencies":{"parse":">=5.0.0","express":">=4.0.0","node-cron":">=3.0.0","@types/parse":">=3.0.0","parse-server":">=8.3.0","reflect-metadata":">=0.1.13","swagger-ui-express":">=4.0.0"},"peerDependenciesMeta":{"node-cron":{"optional":true},"@types/parse":{"optional":true},"parse-server":{"optional":true},"swagger-ui-express":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/parse-server-kit_2.9.0_1786880190600_0.830580087160619","host":"s3://npm-registry-packages-npm-production"}},"2.10.1":{"name":"@90soft/parse-server-kit","version":"2.10.1","description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","test":"jest","test:integration":"NODE_OPTIONS=--experimental-vm-modules jest --config jest.integration.config.js","test:all":"npm test && npm run test:integration","prepublishOnly":"npm run build"},"keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"author":{"name":"90Soft"},"license":"MIT","repository":{"type":"git","url":"https://git.90-soft.com/90_soft/parse-server-kit.git"},"engines":{"node":">=18.0.0"},"peerDependencies":{"@types/parse":">=3.0.0","express":">=4.0.0","node-cron":">=3.0.0","parse":">=5.0.0","parse-server":">=8.3.0","reflect-metadata":">=0.1.13","swagger-ui-express":">=4.0.0"},"peerDependenciesMeta":{"@types/parse":{"optional":true},"node-cron":{"optional":true},"swagger-ui-express":{"optional":true},"parse-server":{"optional":true}},"devDependencies":{"@types/express":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","express":"^5.0.0","jest":"^29.7.0","mongodb-memory-server":"^11.2.0","node-cron":"^4.0.0","parse":"^5.3.0","parse-server":"^9.10.0","reflect-metadata":"^0.2.2","swagger-ui-express":"^5.0.1","ts-jest":"^29.2.0","typescript":"^5.5.0"},"_id":"@90soft/parse-server-kit@2.10.1","gitHead":"8f6998f42eb6878345d7f8e236a5ddb614c76e87","_nodeVersion":"20.19.3","_npmVersion":"10.8.2","dist":{"integrity":"sha512-thnk9DtLSOJmq3X9ccsg0aoblntfm5USzKwZrFvCbuh2LXcnQRIhltGUmAEOHxiyunu443+g/KmmWIWA/EGcNQ==","shasum":"d6e626d7a011aa0145051869731eaf90960234b3","tarball":"https://registry.npmjs.org/@90soft/parse-server-kit/-/parse-server-kit-2.10.1.tgz","fileCount":140,"unpackedSize":399903,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC1ogXuEGN7q6kMyRl+t4ix20ZF3qGxlZcKsm0B1eSP5QIhAI3GS6YpBHjrbkUjOA7Bewo1VtlIztRLnxefRp7s3mvy"}]},"_npmUser":{"name":"90soft","email":"w.alhalabi@90-soft.com"},"directories":{},"maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/parse-server-kit_2.10.1_1787667925805_0.39774970420940625"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-09T13:26:06.597Z","modified":"2026-08-25T14:25:26.123Z","1.0.0":"2026-04-09T13:26:06.880Z","2.0.0":"2026-04-09T13:41:23.875Z","2.0.1":"2026-04-12T09:55:47.344Z","2.0.2":"2026-04-12T10:06:56.703Z","2.1.0":"2026-04-12T10:32:30.916Z","2.2.0":"2026-04-12T11:08:53.564Z","2.3.0":"2026-04-12T11:14:02.568Z","2.3.1":"2026-04-12T11:26:18.271Z","2.4.0":"2026-04-12T11:45:03.565Z","2.5.0":"2026-05-05T10:42:02.725Z","2.5.1":"2026-06-07T11:37:46.310Z","2.5.2":"2026-06-07T11:59:27.154Z","2.5.3":"2026-06-22T10:22:34.257Z","2.6.0":"2026-06-25T10:23:17.788Z","2.8.0":"2026-08-16T10:57:59.823Z","2.8.1":"2026-08-16T11:08:04.166Z","2.8.2":"2026-08-16T11:29:28.964Z","2.9.0":"2026-08-16T11:36:30.752Z","2.10.1":"2026-08-25T14:25:25.976Z"},"author":{"name":"90Soft"},"license":"MIT","keywords":["parse-server","decorators","typescript","backend","cloud-functions","mongodb","acl","swagger","cron"],"repository":{"type":"git","url":"https://git.90-soft.com/90_soft/parse-server-kit.git"},"description":"Complete decorator-driven development kit for Parse Server — models, cloud functions, triggers, cron, routing, ACL, Swagger, and more.","maintainers":[{"name":"90soft","email":"w.alhalabi@90-soft.com"}],"readme":"# @90soft/parse-server-kit\r\n\r\nDecorator-driven development kit for Parse Server. Write models and cloud functions with TypeScript decorators — no boilerplate.\r\n\r\n## Install\r\n\r\n```bash\r\nnpm install @90soft/parse-server-kit\r\n```\r\n\r\n**Required peers:** `parse`, `reflect-metadata`, `express`\r\n\r\n**Optional peers** — install only what you use. Each degrades with a warning rather than failing:\r\n\r\n| Package | Needed for | Without it |\r\n|---|---|---|\r\n| `node-cron` | `@Cron` | Cron jobs are skipped |\r\n| `swagger-ui-express` | `setupSwagger` browser UI | The spec is still served at `/api-docs/json` |\r\n| `parse-server` | `createVersionedMongoAdapter`, `createSchemaConfig` | Transactions and `@ParseVersionField` are unavailable. **8.3+ required** — `createSchemaConfig` emits `keepUnknownIndexes`, and parse-server refuses to start on an option it does not recognise |\r\n| `@types/parse` | TypeScript builds | See below |\r\n\r\n### TypeScript setup\r\n\r\nTwo things are **required** in your `tsconfig.json`, and neither fails loudly if\r\nyou miss it:\r\n\r\n```jsonc\r\n{\r\n  \"compilerOptions\": {\r\n    \"experimentalDecorators\": true,  // REQUIRED\r\n    \"emitDecoratorMetadata\": true    // optional — see below\r\n  }\r\n}\r\n```\r\n\r\n- **`experimentalDecorators: true` is mandatory.** This package uses *legacy*\r\n  decorators. TypeScript 5.0+ defaults to the standard (TC39) decorators, which\r\n  are a different feature with different semantics — without this flag every\r\n  `@ParseClass` / `@ParseField` in your project silently misbehaves.\r\n- **`emitDecoratorMetadata` is not required.** The package reads no `design:type`\r\n  metadata; it stores its own keys. Turn it on only if something else in your\r\n  project needs it.\r\n\r\nThis package's published type declarations refer to a **global** `Parse`\r\nnamespace, the way cloud code sees it. Install `@types/parse` to provide it:\r\n\r\n```bash\r\nnpm install --save-dev @types/parse\r\n```\r\n\r\nWithout it you will see `Cannot find namespace 'Parse'` when compiling against\r\nthe kit. If you already have `@types/parse`, nothing changes — do not also\r\ndeclare your own global `Parse` namespace, or the two will collide.\r\n\r\n### Runtime requirements\r\n\r\n| | |\r\n|---|---|\r\n| Node | ≥ 18 for this package; **≥ 20.19** if you are on parse-server 9 |\r\n| MongoDB | ≥ 7.0.16 for parse-server 9; **replica set** required for transactions |\r\n| Database | Transactions and `@ParseVersionField` are **MongoDB-only** — they have no effect on Postgres |\r\n\r\n---\r\n\r\n## Quick Start\r\n\r\n### 1. Define a Model\r\n\r\n```ts\r\nimport { ParseClass, ParseField, BaseModel } from '@90soft/parse-server-kit';\r\nimport { UserRoles, roleKey } from '@90soft/parse-server-kit';\r\n\r\n@ParseClass('Product', {\r\n  clp: {\r\n    find:   { [roleKey(UserRoles.ADMIN)]: true, [roleKey(UserRoles.EMPLOYEE)]: true },\r\n    get:    { [roleKey(UserRoles.ADMIN)]: true, [roleKey(UserRoles.EMPLOYEE)]: true },\r\n    create: { [roleKey(UserRoles.ADMIN)]: true, [roleKey(UserRoles.EMPLOYEE)]: true },\r\n    update: { [roleKey(UserRoles.ADMIN)]: true, [roleKey(UserRoles.EMPLOYEE)]: true },\r\n    delete: { [roleKey(UserRoles.ADMIN)]: true },\r\n    count:  { [roleKey(UserRoles.ADMIN)]: true, [roleKey(UserRoles.EMPLOYEE)]: true },\r\n  },\r\n})\r\nexport default class Product extends BaseModel {\r\n  @ParseField({ type: 'String', required: true })\r\n  name!: string;\r\n\r\n  @ParseField({ type: 'Number', required: true, min: 0 })\r\n  price!: number;\r\n\r\n  @ParseField({ type: 'String', enum: ['active', 'draft', 'archived'] })\r\n  status!: string;\r\n\r\n  @ParseField({ type: 'Pointer', targetClass: 'Category', required: true })\r\n  category!: any;\r\n\r\n  @ParseField({ type: 'Boolean' })\r\n  available!: boolean;\r\n\r\n  @ParseField({ type: 'Date' })\r\n  createdDate!: Date;\r\n}\r\n```\r\n\r\n### 2. Write Cloud Functions\r\n\r\n```ts\r\nimport { CloudFunction, Route, catchError, UserRoles } from '@90soft/parse-server-kit';\r\nimport Product from '../../models/Product';\r\nimport User from '../../models/User';\r\n\r\n@Route(Product) // → /api/products/createProduct, /api/products/listProducts, …\r\nclass ProductFunctions {\r\n\r\n  @CloudFunction({\r\n    methods: ['POST'],\r\n    validation: { requireUser: true, fields: { name: { required: true } } },\r\n  })\r\n  static async createProduct(req: Parse.Cloud.FunctionRequest) {\r\n    const user = req.user! as User;\r\n    const product = Product.fromParams(req.params);\r\n    const [err, saved] = await catchError(\r\n      product.save(null, { sessionToken: user.getSessionToken() })\r\n    );\r\n    if (err) throw err;\r\n    return saved;\r\n  }\r\n\r\n  @CloudFunction({\r\n    methods: ['GET'],\r\n    validation: { requireUser: true, fields: { skip: { type: String }, limit: { type: String } } },\r\n  })\r\n  static async listProducts(req: Parse.Cloud.FunctionRequest) {\r\n    const query = new Parse.Query(Product);\r\n    query.include('category');\r\n    const skip = Number(req.params.skip) || 0;\r\n    const limit = Number(req.params.limit) || 10;\r\n    query.skip(skip).limit(limit);\r\n\r\n    if (req.params.search) {\r\n      const search = req.params.search;\r\n      query.matches('name', new RegExp(search, 'i'));\r\n    }\r\n\r\n    const [err, results] = await catchError(query.find({ sessionToken: req.user!.getSessionToken() }));\r\n    if (err) throw err;\r\n\r\n    const [countErr, count] = await catchError(query.count({ sessionToken: req.user!.getSessionToken() }));\r\n    return { results, count: countErr ? 0 : count };\r\n  }\r\n\r\n  @CloudFunction({\r\n    methods: ['POST'],\r\n    validation: { requireUser: true, fields: { id: { required: true } } },\r\n  })\r\n  static async getProduct(req: Parse.Cloud.FunctionRequest) {\r\n    const query = new Parse.Query(Product);\r\n    query.include('category');\r\n    const [err, product] = await catchError(query.get(req.params.id, { sessionToken: req.user!.getSessionToken() }));\r\n    if (err) throw err;\r\n    return product;\r\n  }\r\n\r\n  @CloudFunction({\r\n    methods: ['POST'],\r\n    validation: { requireUser: true, fields: { id: { required: true } } },\r\n  })\r\n  static async updateProduct(req: Parse.Cloud.FunctionRequest) {\r\n    const user = req.user! as User;\r\n    const product = Product.fromParams(req.params);\r\n    const [err, saved] = await catchError(\r\n      product.save(null, { sessionToken: user.getSessionToken() })\r\n    );\r\n    if (err) throw err;\r\n    return saved;\r\n  }\r\n\r\n  @CloudFunction({\r\n    methods: ['POST'],\r\n    validation: { requireUser: true, fields: { id: { required: true } } },\r\n  })\r\n  static async deleteProduct(req: Parse.Cloud.FunctionRequest) {\r\n    const query = new Parse.Query(Product);\r\n    const [err, product] = await catchError(query.get(req.params.id, { useMasterKey: true }));\r\n    if (err) throw err;\r\n    const [delErr] = await catchError(product!.destroy({ useMasterKey: true }));\r\n    if (delErr) throw delErr;\r\n    return { success: true };\r\n  }\r\n}\r\n```\r\n\r\n> **Note on the search above.** `query.matches()` compiles to a Mongo `$regex`.\r\n> parse-server 9.8+ can disable that operator entirely via\r\n> `requestComplexity.allowRegex: false` — a worthwhile hardening option, since an\r\n> unanchored user-supplied regex is both a scan and a ReDoS surface. If you turn\r\n> it on, replace this with a text index (`@ParseClass({compoundIndexes: [{fields:\r\n> ['name'], fieldTypes: {name: 'text'}}]})`) and `query.fullText('name', search)`.\r\n\r\n### 3. Add Triggers\r\n\r\n```ts\r\nimport { ParseClass, ParseField, BaseModel, BeforeSave, AfterDelete } from '@90soft/parse-server-kit';\r\n\r\n@ParseClass('Product', { /* clp... */ })\r\nexport default class Product extends BaseModel {\r\n  @ParseField({ type: 'String', required: true })\r\n  name!: string;\r\n\r\n  @BeforeSave()\r\n  static async onBeforeSave(req: Parse.Cloud.BeforeSaveRequest<Product>) {\r\n    // Validate or modify before saving\r\n    if (!req.object.get('name')) {\r\n      throw new Parse.Error(142, 'Name is required');\r\n    }\r\n  }\r\n\r\n  @AfterDelete()\r\n  static async onAfterDelete(req: Parse.Cloud.AfterDeleteRequest<Product>) {\r\n    // Cleanup after deletion\r\n    console.log(`Product ${req.object.id} deleted`);\r\n  }\r\n}\r\n```\r\n\r\n### 4. Add Cron Jobs\r\n\r\n```ts\r\nimport { Cron, CronSchedule } from '@90soft/parse-server-kit';\r\n\r\nclass MyCronJobs {\r\n  @Cron({ schedule: CronSchedule.DAILY_MIDNIGHT, description: 'Cleanup expired sessions' })\r\n  static async cleanupSessions() {\r\n    // job logic\r\n  }\r\n\r\n  @Cron({ schedule: '*/30 * * * *', description: 'Sync data every 30 minutes' })\r\n  static async syncData() {\r\n    // job logic\r\n  }\r\n}\r\n```\r\n\r\n### 5. Server Setup (app.ts)\r\n\r\n```ts\r\nimport express from 'express';\r\nimport {\r\n  CloudFunctionRegistry, TriggerRegistry, CronRegistry,\r\n  importFiles, catchError, applyMongoValidators,\r\n  validateEntityRoutes, restrictRoutes, removeResultMiddleware,\r\n  conditionalJsonMiddleware, setupSwagger,\r\n} from '@90soft/parse-server-kit';\r\n\r\nconst app = express();\r\n\r\n// 1. Load models (must be before Parse Server init)\r\nimportFiles(join(__dirname, 'cloudCode/models'));\r\n\r\n// 2. Init Parse Server\r\nconst parseServer = await initializeParseServer();\r\n\r\n// 3. Middleware\r\napp.use(removeResultMiddleware);\r\napp.use(cors());\r\napp.use(process.env.mountPath, validateEntityRoutes);\r\napp.use(conditionalJsonMiddleware);\r\napp.use(process.env.mountPath, restrictRoutes);\r\n\r\n// 4. Mount Parse Server\r\napp.use(process.env.mountPath, parseServer.app);\r\n\r\n// 5. Initialize registries (after Parse Server mount)\r\nCloudFunctionRegistry.initialize();  // also initializes RouteRegistry\r\nTriggerRegistry.initialize();\r\nCronRegistry.initialize();\r\n\r\n// 6. Swagger docs\r\nsetupSwagger(app, { title: 'My API', version: '1.0.0' });\r\n\r\n// 7. Start server\r\nserver.listen(1337);\r\n```\r\n\r\n---\r\n\r\n## Transactions & Optimistic Locking\r\n\r\nTwo guards against concurrent writes, both enforced at the database adapter so no endpoint has to remember them. Both report the same error — code `5001` (`CONFLICT`) with a user-facing message — because to the person on the screen, \"somebody else got there first\" is one event.\r\n\r\n### Setup\r\n\r\nBoth features are powered by one adapter. Pass it to Parse Server instead of a Mongo URI:\r\n\r\n```ts\r\nimport {createVersionedMongoAdapter} from '@90soft/parse-server-kit';\r\n\r\nconst parseServer = new ParseServer({\r\n  databaseAdapter: createVersionedMongoAdapter({\r\n    uri: process.env.DATABASE_URI,\r\n    collectionPrefix: '',\r\n    mongoOptions: {},\r\n  }),\r\n  directAccess: true,   // REQUIRED for transactions — see below\r\n  // ...\r\n});\r\n```\r\n\r\n**Requirements:**\r\n- MongoDB must run as a **replica set** — a standalone server refuses to open a transaction.\r\n- `directAccess: true` (Parse Server's default). Without it, a `save()` in cloud code goes through an internal HTTP request, arrives in a fresh async context, and silently writes **outside** the transaction. Pin it in your config — that failure has no symptom.\r\n\r\n### `@Transactional` / `withTransaction`\r\n\r\nEverything the body writes lands together, or none of it does. The transaction follows the async call chain (`AsyncLocalStorage`), so every `save()`, `destroy()` and query inside the body joins automatically — no session objects to thread through.\r\n\r\n```ts\r\nimport {Transactional, withTransaction} from '@90soft/parse-server-kit';\r\n\r\nclass JobFunctions {\r\n  @CloudFunction({...})   // sees the wrapped method\r\n  @Transactional()        // wraps it — must sit BELOW @CloudFunction\r\n  static async submitJob(req: Parse.Cloud.FunctionRequest) {\r\n    // every write in here commits or rolls back as one\r\n  }\r\n}\r\n\r\n// Outside a cloud function, or for part of one:\r\nawait withTransaction(async () => {\r\n  await order.save(null, {useMasterKey: true});\r\n  await inventory.save(null, {useMasterKey: true});\r\n});\r\n```\r\n\r\n- **Decorator order matters.** Decorators apply bottom-up and `@CloudFunction` captures the method when applied, so `@Transactional()` must sit *below* it — otherwise the registry keeps the unwrapped method and the transaction silently never opens.\r\n- **Nested calls join** the outer transaction; the outermost caller commits.\r\n- **The body may be re-run** (up to 3 attempts) if it loses a race with another transaction, so it must be safe to repeat. After 3 losses the caller gets the `CONFLICT` error.\r\n- System classes (`_SCHEMA`, `_Idempotency`, `_Hooks`, `_JobStatus`, `_GlobalConfig`) are never dragged into a transaction — schema creation and idempotency keys must survive a rollback.\r\n- Each concurrent request gets its **own** session — unlike Parse Server's built-in transaction support, one caller's transaction cannot swallow another's writes.\r\n\r\n### `@ParseVersionField`\r\n\r\nOptimistic locking declared on the field. Two people reading the same record and both saving is a lost update — the second write silently overwrites the first. With a version field, the stale save is refused instead.\r\n\r\n```ts\r\nimport {ParseVersionField} from '@90soft/parse-server-kit';\r\n\r\n@ParseClass('Job')\r\nclass Job extends BaseModel {\r\n  @ParseField({type: 'String'})\r\n  title!: string;\r\n\r\n  @ParseVersionField()   // declares the Number field itself — no @ParseField needed\r\n  version!: number;\r\n}\r\n```\r\n\r\nThat is the whole feature. No endpoint reads or writes the field:\r\n\r\n- every object **read** from the database carries the version it was read at, and every `save()` / `saveAll()` asserts it automatically;\r\n- the adapter turns the assertion into the write's **filter** (the update only lands if the row is still at that version) and **increments** the field on every update, so the next reader gets a fresh number;\r\n- a save that lost the race is refused with the `CONFLICT` error (`5001`); a genuinely missing row still reads as missing;\r\n- creates get version `1` from the adapter — callers never supply one;\r\n- an object built from a bare id (never read) has nothing to assert, and simply isn't protected.\r\n\r\n### Handling the conflict\r\n\r\n```ts\r\nimport {CONFLICT} from '@90soft/parse-server-kit';\r\n\r\ntry {\r\n  await job.save(null, {useMasterKey: true});\r\n} catch (error) {\r\n  if (error instanceof Parse.Error && error.code === CONFLICT) {\r\n    // Reload, re-apply the change, save again — or surface the message,\r\n    // which is already written for the end user.\r\n  }\r\n  throw error;\r\n}\r\n```\r\n\r\n---\r\n\r\n## API Reference\r\n\r\n### Decorators\r\n\r\n| Decorator | Target | Description |\r\n|---|---|---|\r\n| `@ParseClass(name, options)` | Class | Registers a Parse model with CLP, ACL, indexes |\r\n| `@ParseField(options)` | Property | Defines a field with type, validation, index |\r\n| `@CloudFunction(config)` | Static method | Registers a cloud function with HTTP method, validation, roles |\r\n| `@ProtectedCloudFunction(config)` | Static method | Same as @CloudFunction but requires auth by default |\r\n| `@Route(ModelOrString)` | Class | Maps cloud functions to `/api/{entity}/{action}` routes |\r\n| `@Cron(config)` | Static method | Registers a cron job with schedule |\r\n| `@BeforeSave(config?)` | Static method | Before save trigger |\r\n| `@AfterSave(config?)` | Static method | After save trigger |\r\n| `@BeforeDelete(config?)` | Static method | Before delete trigger |\r\n| `@AfterDelete(config?)` | Static method | After delete trigger |\r\n| `@BeforeFind(config?)` | Static method | Before find trigger |\r\n| `@AfterFind(config?)` | Static method | After find trigger |\r\n| `@BeforeLogin(config?)` | Static method | Before login trigger |\r\n| `@AfterLogin(config?)` | Static method | After login trigger |\r\n| `@AfterLogout(config?)` | Static method | After logout trigger |\r\n| `@BeforePasswordResetRequest(config?)` | Static method | Before a password reset email is sent (parse-server 8.5+) |\r\n| `@BeforeSaveFile` / `@AfterSaveFile` | Static method | File save triggers |\r\n| `@BeforeDeleteFile` / `@AfterDeleteFile` | Static method | File delete triggers |\r\n| `@BeforeFindFile` / `@AfterFindFile` | Static method | File find triggers (parse-server 8.1+) |\r\n| `@BeforeSaveConfig` / `@AfterSaveConfig` | Static method | Parse Config triggers (parse-server 7.3+) |\r\n| `@BeforeConnect` / `@BeforeSubscribe` / `@AfterEvent` | Static method | LiveQuery triggers |\r\n| `@Transactional()` | Static method | Runs the method in a MongoDB transaction (place below `@CloudFunction`) |\r\n| `@ParseVersionField(options?)` | Property | Declares the class's optimistic-lock version field |\r\n\r\n### @ParseField Options\r\n\r\n| Option | Type | Description |\r\n|---|---|---|\r\n| `type` | `'String' \\| 'Number' \\| 'Boolean' \\| 'Date' \\| 'Pointer' \\| 'Array' \\| ...` | Field type |\r\n| `required` | `boolean` | Whether the field is required |\r\n| `targetClass` | `string` | Target class for Pointer/Relation |\r\n| `index` | `boolean \\| 1 \\| -1` | Create an index |\r\n| `unique` | `boolean` | Create a unique index |\r\n| `min` / `max` | `number` | Number range validation |\r\n| `minLength` / `maxLength` | `number` | String length validation |\r\n| `enum` | `string[]` | Allowed values for String fields |\r\n| `pattern` | `string` | Regex pattern for String fields |\r\n| `description` | `string` | Swagger documentation |\r\n\r\n### @Route\r\n\r\n```ts\r\n// Import model class — auto-generates route from className\r\n@Route(Product)  // → /api/products/*\r\n\r\n// Custom string — full control over route prefix\r\n@Route('menu-items')  // → /api/menu-items/*\r\n```\r\n\r\n**The method name IS the route** — no parsing, no prefix stripping, no\r\ncollisions. The route is `/{prefix}/{methodName}`:\r\n\r\n```\r\ncreateProduct  → POST /api/products/createProduct\r\ngetProduct     → POST /api/products/getProduct\r\nlistProducts   → GET  /api/products/listProducts\r\nupdateProduct  → POST /api/products/updateProduct\r\ndeleteProduct  → POST /api/products/deleteProduct\r\n```\r\n\r\nMatching is done against the class's real method list, so `getProduct` and\r\n`getProductCategory` can coexist. Renaming a method renames its route.\r\n\r\n### BaseModel\r\n\r\n```ts\r\n// Create from request params (auto-maps fields, handles pointers)\r\nconst product = Product.fromParams(req.params);\r\n\r\n// Create a pointer reference by ID\r\nconst category = Category.pointer('abc123');\r\n\r\n// Override excluded pointer classes (default: ['IMG', 'File'])\r\nclass MyModel extends BaseModel {\r\n  protected static EXCLUDED_POINTER_CLASSES = ['IMG', 'File', 'CustomFile'];\r\n}\r\n```\r\n\r\n### ACL\r\n\r\n```ts\r\nimport { implementACL, UserRoles } from '@90soft/parse-server-kit';\r\n\r\nobj.setACL(implementACL({\r\n  roleRules: [\r\n    { role: UserRoles.ADMIN, read: true, write: true },\r\n    { role: UserRoles.EMPLOYEE, read: true },\r\n  ],\r\n  owner: [\r\n    { user: userId, read: true, write: true },\r\n  ],\r\n}));\r\n```\r\n\r\n### Utilities\r\n\r\n```ts\r\nimport {\r\n  catchError,          // Wraps promises: const [err, data] = await catchError(promise)\r\n  getUserRoles,        // Get role names for a user\r\n  getUsersRoles,       // Roles for many users — one query per role, not per user\r\n  importFiles,         // Auto-import a directory, for its decorator side effects\r\n  generateRandomPassword,\r\n  generateRandomString,\r\n  sleep,\r\n  formatCount,\r\n} from '@90soft/parse-server-kit';\r\n```\r\n\r\n`importFiles` loads `.js` only by default — the compiled output a production\r\nserver runs. If you start straight from source under ts-node or tsx, say so, or\r\n**nothing is imported and the server boots with an empty schema**:\r\n\r\n```ts\r\nimportFiles(join(__dirname, 'cloudCode/models'), {extensions: ['.js', '.ts']});\r\n```\r\n\r\nPoint it at one directory or the other, never a tree holding both a compiled and\r\na source copy — that registers every class twice.\r\n\r\n### Role Cache (opt-in)\r\n\r\n`@CloudFunction({requireRoles})` and `getUserRoles()` each cost a database\r\nround-trip. Role membership rarely changes, so caching it removes that\r\nround-trip — at the cost of a revoked role continuing to work until the entry\r\nexpires. That trade is yours to make, so the cache does nothing until you turn\r\nit on:\r\n\r\n```ts\r\nimport {configureRoleCache, invalidateRoles} from '@90soft/parse-server-kit';\r\n\r\nconfigureRoleCache({ttlMs: 30_000});   // global; omit entirely to stay off\r\n\r\n// Opt a sensitive endpoint out, whatever the global policy says\r\n@CloudFunction({requireRoles: [UserRoles.ADMIN], roleCacheMs: 0})\r\nstatic async deleteEverything(req) { ... }\r\n\r\n// Wherever you grant or revoke, drop the entry immediately\r\nawait role.getUsers().remove(user);\r\nawait role.save(null, {useMasterKey: true});\r\ninvalidateRoles(user.id);\r\n```\r\n\r\nWith `invalidateRoles` wired into your own grant/revoke paths, the TTL only\r\ncovers changes made outside your code (a dashboard edit, a direct database\r\nwrite). `configureRoleCache(false)` disables it and clears everything held.\r\n\r\n### Middleware\r\n\r\n```ts\r\nimport {\r\n  validateEntityRoutes,       // Maps /api/{entity}/{action} → cloud functions\r\n  restrictRoutes,             // Blocks /classes, /schemas, etc.\r\n  removeResultMiddleware,     // Unwraps Parse {result: ...} wrapper\r\n  conditionalJsonMiddleware,  // JSON parsing with master key extraction\r\n  validateFunctionRoutes,     // Legacy /functions/* validation\r\n} from '@90soft/parse-server-kit';\r\n```\r\n\r\n### Swagger\r\n\r\n```ts\r\nimport { setupSwagger, SwaggerRegistry } from '@90soft/parse-server-kit';\r\n\r\n// Auto-generates API docs from @ParseClass and @CloudFunction metadata\r\nsetupSwagger(app, {\r\n  title: 'My API',\r\n  version: '1.0.0',\r\n  description: 'Auto-generated docs',\r\n});\r\n// Access at: http://localhost:1337/api-docs\r\n```\r\n\r\n### Hooks (for integrations)\r\n\r\n```ts\r\nimport { onClassRegistered, onFieldRegistered, onFunctionRegistered } from '@90soft/parse-server-kit';\r\n\r\n// Runs when @ParseClass is applied\r\nonClassRegistered((className, constructor, fields, options) => {\r\n  // Register with Swagger, setup triggers, etc.\r\n});\r\n\r\n// Runs when @CloudFunction is applied\r\nonFunctionRegistered((name, config, target) => {\r\n  // Register with Swagger docs\r\n});\r\n```\r\n\r\n### Constants\r\n\r\n```ts\r\nimport { UserRoles, roleKey, MAX_QUERY_LIMIT, CronSchedule } from '@90soft/parse-server-kit';\r\n\r\nUserRoles.ADMIN      // 'SuperAdmin'\r\nUserRoles.EMPLOYEE   // 'Employee'\r\nroleKey(UserRoles.ADMIN)  // 'role:SuperAdmin'\r\nMAX_QUERY_LIMIT      // 10000\r\n\r\nCronSchedule.EVERY_HOUR      // '0 * * * *'\r\nCronSchedule.DAILY_MIDNIGHT  // '0 0 * * *'\r\nCronSchedule.WEEKLY_MONDAY   // '0 0 * * 1'\r\n```\r\n\r\n### Validation\r\n\r\n```ts\r\nimport { validateObject, validateOrThrow, applyMongoValidators } from '@90soft/parse-server-kit';\r\n\r\n// Validate against @ParseField constraints (min, max, enum, pattern, etc.)\r\nconst result = validateObject(parseObject);\r\n// { valid: false, errors: [{ field: 'price', message: 'must be at least 0' }] }\r\n\r\n// Throw Parse.Error if invalid (use in BeforeSave triggers)\r\nvalidateOrThrow(parseObject);\r\n\r\n// Apply MongoDB schema validators from decorator metadata\r\nawait applyMongoValidators(parseServerInstance);\r\n```\r\n\r\n---\r\n\r\n## File Structure Convention\r\n\r\n```\r\nbackend/src/cloudCode/\r\n  ├── models/\r\n  │   └── Product.ts              ← @ParseClass + @ParseField + triggers\r\n  ├── modules/\r\n  │   └── Product/\r\n  │       └── functions.ts        ← @Route + @CloudFunction\r\n  ├── cron.ts                     ← @Cron jobs\r\n  ├── main.ts                     ← importFiles for models + modules\r\n  └── decorator/\r\n      └── setupHooks.ts           ← connects package hooks to Swagger + Triggers\r\n```\r\n\r\n## Testing\r\n\r\n```bash\r\nnpm test               # unit tests — fast, no database\r\nnpm run test:integration   # real parse-server + in-memory MongoDB replica set\r\nnpm run test:all\r\n```\r\n\r\nThe integration suite exists to catch parse-server upgrades that move the\r\ninternals the transactions and versioning features lean on: the\r\n`MongoStorageAdapter` module path, `_adaptiveCollection`/`_mongoCollection`,\r\n`_getSaveJSON`, and — verified method by method against the mongodb driver\r\nparse-server actually ships — every options position in `OPTIONS_ARGUMENT`.\r\nIt boots a real parse-server on `mongodb-memory-server` and exercises\r\nversioned saves, stale-save conflicts, and cloud-function transaction\r\ncommit/rollback end to end. The first run downloads a MongoDB binary.\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}