{"_id":"@alternative-design-and-media/rentman-api-connector","_rev":"16-b8f070ea58ecc47aa03c03b5f64b4cf9","name":"@alternative-design-and-media/rentman-api-connector","dist-tags":{"latest":"2.6.0"},"versions":{"0.1.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"0.1.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@0.1.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"dist":{"shasum":"29e0b8e9e9176c2b2e2a74db07ed47758b158590","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-0.1.0.tgz","fileCount":7,"integrity":"sha512-10x0beIpFgc6J94gc5CIED8dZzf6B4xBKOyug0N6xDqm/KawH+FHDgIr2IL/doWoocuTWSMgnvAT04PMvPCPEg==","signatures":[{"sig":"MEUCIQDasGtx2P2vXkk2wLdSWNocCRHCrP/iz8wCIS0z5Mp89QIgIFwCwujkfs26cm/3PitghzG3aaqMdea1vGq2AJk5hh4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":60879},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"1032f28bd07feaa2a43467494ceb581b27b51782","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.6.0","typescript":"^5.4.0"},"peerDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_0.1.0_1778194974840_0.7067573315864184","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"0.2.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@0.2.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"dist":{"shasum":"1ede206729084330451c002af54a09ec46f87a05","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-0.2.0.tgz","fileCount":7,"integrity":"sha512-ZPP4d6MLqSRcQzpCARGAZhMQC7Mn60YIK5lUOue7ru0hDzuIJKX1K+yqEAif4eg3mCCk1N7Ik16cBZD5TWmlrQ==","signatures":[{"sig":"MEUCIQDVwtrbdU4kO0FQXW4IP3TbeuVQrUv+BDnMHAabxJIesgIgcuX+xOACKFfi3EAG76kN5DjR/tei5IJ5LdYlbBMOmjk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":78421},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"0b5b24e52a000131a6a2e6159c771344632b129e","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.6.0","typescript":"^5.4.0"},"peerDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_0.2.0_1778593486985_0.3313643431190352","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@alternative-design-and-media/rentman-api-connector","version":"0.2.1","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@0.2.1","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"dist":{"shasum":"dc8f9860660841c66803374419d869bf958808ed","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-0.2.1.tgz","fileCount":7,"integrity":"sha512-6PZ8ATdMvOnDxxHXADD8J35oPQeq/TlT+1IJOW/vbS680SVIglSDzo8uxZQ+KNtyIS+Ox3WQFBFz5DaDqCBPyQ==","signatures":[{"sig":"MEQCIDc/cbus2AlaWtHZaeFSY558mTPRb21D9GILHwnj6GCyAiBBhgbQH6wV9IGrmSXcG13J0a5r4L/hYxQkp5qlU3GEqg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":78711},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"ad1e62c4f3ed07f4294724c8fd7e27534b29c597","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.6.0","typescript":"^5.4.0"},"peerDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_0.2.1_1778598287768_0.4252135636367238","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"0.3.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@0.3.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"dist":{"shasum":"5786fe9d858f23dcf4492dff73da9001e3b2b0e2","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-0.3.0.tgz","fileCount":8,"integrity":"sha512-BXD6k5UY2jRqvY28WLpvt5EPOcncfsUIIzN1WZx+C3ZKCdrIaqfS2phhPDLMzeE4r2LcOp030bMdbyQRlUZmjA==","signatures":[{"sig":"MEYCIQDPBKmSTx0LimF+IJxuoQrCfMN59UPZ9BTnFzrmzosDDwIhANikF1lNuVgVov599MYgcfAfIFDYwcwvPGx22LCfSGX4","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87610},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"81836ae18cd63e55f911fecf390010516534a2c0","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.6.0","typescript":"^5.4.0"},"peerDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_0.3.0_1778624099253_0.22592805048950693","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"1.0.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@1.0.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"dist":{"shasum":"117124f459c68fb0dab2c6c7679762e02b2e8b8c","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-1.0.0.tgz","fileCount":10,"integrity":"sha512-ALwHggBA7f8mTLpCUJmeFV25/19sQnQEPIgMkTMoWVySQuyveN2PsnZ8M6k4lCdcL9PcQc+wjH2QGKvRygpIlg==","signatures":[{"sig":"MEQCIH7g5ppWmg+xh2B7A2hO+p7/qCLk+clIQMfvJgNySlD3AiABfbWBf33YsuHGwaavNNu487+K06wBDN67BnnlIW3KSA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":132063},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"699ae25914e0b470787e99c539e529279e3283fc","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.6.0","typescript":"^5.4.0"},"peerDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_1.0.0_1778637547506_0.7402046880380819","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@alternative-design-and-media/rentman-api-connector","version":"1.0.1","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@1.0.1","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"dist":{"shasum":"1efcd8ec99f1626e68992c5b0385fa09094e1674","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-1.0.1.tgz","fileCount":10,"integrity":"sha512-K+okOP8lgVbDUL29iZW+A3joptbB+0KaGM7qCnbwKGa9HCAvfS8K2eajNiaxHgq1i+R6rs+A2brRICOSkhQkfg==","signatures":[{"sig":"MEYCIQDy8jWG8X3mOg8ur5I2iDwBcwIu0y6Rr8l2Z7ERvkoW4AIhAJ+puZytAFe4Cmi+vNdHVIqWykvVekA1lcCK3bX4UplF","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":141183},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"935566a2bdfde59938d97d6c68a90924f053d48b","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.6.0","typescript":"^5.4.0"},"peerDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_1.0.1_1779089469521_0.7359105237591179","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"1.1.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@1.1.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"dist":{"shasum":"64eebb3a8a1f56105c850f465daf28fd3a60186a","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-1.1.0.tgz","fileCount":10,"integrity":"sha512-HQTf8mVUAjYoIenZqL7knla1IEG6YDCGJ3iCGviXHIxaru/l8+5YZC2je+GULPm0gAqW+CJhFGit1uyw97NYjQ==","signatures":[{"sig":"MEYCIQC+jkLsKwP3Ebdbi/Ep/RAdl2Ezbzo3hb7Zb8Bg6c9jjQIhAIMPqw6OBv+N214XUHQq6vvEDmNoJZ1wLOE7WZcNyA7w","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":183437},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"ee8b6011397e1481082e83c3eb7d5c38f882e771","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^1.6.0","typescript":"^5.4.0"},"peerDependencies":{},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_1.1.0_1779106138438_0.9095836240164468","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"1.2.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@1.2.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"dist":{"shasum":"a34ed049f8360ac7dcce485f8e54bf452cf7a74f","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-1.2.0.tgz","fileCount":11,"integrity":"sha512-lrY5huY+ZlFiDIdVOYPCoZqQaVpiQgadihXNk5OwRGzk4I7wwAuiZuFlUqAN5ILSXlPJuYuhtY8bVJeZTnG0hQ==","signatures":[{"sig":"MEUCIBAgYTnMw9EIBh0MBfO3W7RLrLmkThxLhujX6vR/L45EAiEA2pd7iJyEwPUEkkIVdWzZJdvqQ8GlNtSTPUnEv3UXIgE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":208536},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"5b2292d8b7060eef220b70e5394cb88513772250","scripts":{"dev":"tsup --watch --config tsup.config.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup --config tsup.config.ts","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.2","tsup":"^8.0.0","vitest":"^1.6.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_1.2.0_1779143891938_0.47049723245849195","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"2.0.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@2.0.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"dist":{"shasum":"98716c96fa504baa5a926271964b3e4519cac663","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-2.0.0.tgz","fileCount":11,"integrity":"sha512-rDhoUWyJ0xblGHVZ8GpmzIe/bSkqIUlo311oGiouSlWzBUU+Rg9OiIqyGJfP7L+wQt8sB4riOU4scD1c09wbhg==","signatures":[{"sig":"MEYCIQClHqAflMSIsXegOM0gEUSbLvky2wC1PGYxW8Pg18lHFgIhAMgl7aC5+DxJ6w+zriSmxe7/aG3vxVXK3g7/eIC9wz/k","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":253289},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"5d83e13df5354c7c16a944e04ff88f3c18609712","scripts":{"dev":"tsup --watch --config tsup.config.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup --config tsup.config.ts","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.2","tsup":"^8.0.0","vitest":"^4.1.6","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_2.0.0_1779236393376_0.4213877882829511","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"2.1.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@2.1.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"dist":{"shasum":"ef9e96141e1024fccac1392c6cb15bef3ca07ec9","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-2.1.0.tgz","fileCount":11,"integrity":"sha512-YkRpfkyqCKnuJVf7UqADK0kTsHyk/h/8IM467scriownRCfAnoElVLO9KecSh4tKerTiyplemF5iVkzBBHEpJA==","signatures":[{"sig":"MEUCIQDYyClKPfoxSjdxI0VPGu66coogkAyJGkpHntjPBlR6rQIgHV5AEauAPKPt4T8Zz0y5zWjiME1lE/dgsYhBi7EWQEQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":259597},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"a5d2c2ae67a4be10345587b4102f018b1b87708e","scripts":{"dev":"tsup --watch --config tsup.config.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup --config tsup.config.ts","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.2","tsup":"^8.0.0","vitest":"^4.1.6","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_2.1.0_1779715426269_0.7124943333554961","host":"s3://npm-registry-packages-npm-production"}},"2.1.2":{"name":"@alternative-design-and-media/rentman-api-connector","version":"2.1.2","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@2.1.2","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"dist":{"shasum":"c2ea55572f2ce9a9998f041d3b072aa4dda98a54","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-2.1.2.tgz","fileCount":11,"integrity":"sha512-8oKPRzCGgy68RfLz3AEmFW+rpSki+bMstSweqDl8VtwUF14PSW7A3SRfRdBSwNu6Lpa4h2tOlFL1e9Z/Bf06LQ==","signatures":[{"sig":"MEYCIQDko8YRTlJHesSYXK7MZgHJJr9Xwhu0GqGw/P7J9OxnyQIhAIAYLfuSWi/748WmXhDIkSKkC8jqiCezon8xAF+8DYcH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":394252},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"843d8d074bc32e30595fabb8297f59917a88f458","scripts":{"dev":"tsup --watch --config tsup.config.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup --config tsup.config.ts","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.2","tsup":"^8.0.0","vitest":"^4.1.6","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_2.1.2_1779844330938_0.7403205253542025","host":"s3://npm-registry-packages-npm-production"}},"2.2.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"2.2.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@2.2.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"dist":{"shasum":"9b0e8b6fc7b4cd6a6bba0b321bcd236109851b07","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-2.2.0.tgz","fileCount":11,"integrity":"sha512-MLUuuiBWIoDiqn6MVdMGx8OsR4MfknZt4If8Bx4o1fF+z/1g3F5ZqLpbBedYy8a0r7Xat8G2YF3QWBgh5vYwIw==","signatures":[{"sig":"MEQCIFAtHFW60eLYI3l3IGTpPc1x+I5P0mKedcKooeB8o3T+AiAs0RNedW76jeUhErVci4w6wEr56SO3EAupJc/2Qki5/w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":400187},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"7c43d6e45d63822f38b46b0d7ac2f81887c59525","scripts":{"dev":"tsup --watch --config tsup.config.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup --config tsup.config.ts","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.2","tsup":"^8.0.0","vitest":"^4.1.6","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_2.2.0_1780001986894_0.5201695041788961","host":"s3://npm-registry-packages-npm-production"}},"2.3.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"2.3.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@2.3.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"dist":{"shasum":"73e25ca11dbca054242320965f97687608462f8a","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-2.3.0.tgz","fileCount":11,"integrity":"sha512-gD+8ZfpPC7KShu3AUaXhc5K63WCyLB87JJkd/J1W30rcOEnBjNZvmYSJc9G5WGtY2QWKBwyBMMz5VkEjZtXpgw==","signatures":[{"sig":"MEUCIQC+XEWIjcxXh/Y44WWZMVRrBiysBuemo79Ezy1s0ysQtQIgBzEGRPV8SfSBCBc7XsP9LfEwB7/2LCtkXXchrhhmG+4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":413854},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"c753bade6db99f0cab1b9adb95f7e4b14ec76200","scripts":{"dev":"tsup --watch --config tsup.config.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup --config tsup.config.ts","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.2","tsup":"^8.0.0","vitest":"^4.1.6","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_2.3.0_1780675824406_0.3854493277982627","host":"s3://npm-registry-packages-npm-production"}},"2.4.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"2.4.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@2.4.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"dist":{"shasum":"9b91016e23faff020b9d594381978907bd31406e","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-2.4.0.tgz","fileCount":11,"integrity":"sha512-YeqcxUHyfx0dJfSkMUJas6VfJBzTB3HxRMHNJ9JuzUOrh7DCU/DiTGPu3Zj5cB9KBX5Sg2fSBYAE5g98ykTSgw==","signatures":[{"sig":"MEUCIQD8Pn1H1tD8Ep3J2Ojkj3j1Ll/GSrSv0jFlEKQpJvw4GwIgeekscYaIwn2xuecmbpTYYpCvuaXYUMYQpWdliYJjfiI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":425122},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"d70c06bfbb5409b7e71213694566c96becc0926e","scripts":{"dev":"tsup --watch --config tsup.config.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup --config tsup.config.ts","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.2","tsup":"^8.0.0","vitest":"^4.1.6","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_2.4.0_1781036962618_0.7513683428590159","host":"s3://npm-registry-packages-npm-production"}},"2.5.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"2.5.0","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","_id":"@alternative-design-and-media/rentman-api-connector@2.5.0","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"dist":{"shasum":"f9c55c66e77522aefa0519c95a101b306948d1c7","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-2.5.0.tgz","fileCount":11,"integrity":"sha512-KsnoGsC6HvjlAZFJSkGMDKSG5B9XJwBYgjTjKdgGANYJFQHc5vIjuWXPSuoSM3BfgGzqcD722r4HjnGMfIiiaw==","signatures":[{"sig":"MEQCIA+YxwfebZXWz1KHtehUnAlWglvcu7AvdENOEZaTplwIAiBdsI0WS6ErCy1K0KUyGG//X7nDgOrb1pQCLtSP6LDoUw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":459261},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"d8759747ba9e290d8f6e50f4f190233bee30b7c2","scripts":{"dev":"tsup --watch --config tsup.config.ts","lint":"eslint src --ext .ts","test":"vitest run","build":"tsup --config tsup.config.ts","docs:ai":"node scripts/generate-ai-docs.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"repository":{"url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git","type":"git"},"_npmVersion":"10.8.2","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","directories":{},"_nodeVersion":"20.20.2","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.2","tsup":"^8.0.0","vitest":"^4.1.6","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/rentman-api-connector_2.5.0_1785258936367_0.2468935185630281","host":"s3://npm-registry-packages-npm-production"}},"2.6.0":{"name":"@alternative-design-and-media/rentman-api-connector","version":"2.6.0","description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","bin":{"generate-rentman-custom-fields":"dist/scripts/generate-custom-fields.js"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"build":"tsup --config tsup.config.ts","dev":"tsup --watch --config tsup.config.ts","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","lint":"eslint src --ext .ts","docs:ai":"node scripts/generate-ai-docs.mjs","prepublishOnly":"npm run typecheck && npm run build","generate:custom-fields":"tsx scripts/generate-custom-fields.ts"},"keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"author":{"name":"Alternative Design and Media"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git"},"bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","devDependencies":{"tsup":"^8.0.0","tsx":"^4.22.2","typescript":"^5.4.0","vitest":"^4.1.6"},"_id":"@alternative-design-and-media/rentman-api-connector@2.6.0","gitHead":"5bd58a22e159f35c1609e7f40ee8f897f28c931d","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-LXREGwQeCOAwlTRTThi9LVl35o5dbt8gDXaNu7Bc4oTn9Cu6V6Mj9+mj1MwarI5f7GglZl1mtYh/YGrGCtMpPg==","shasum":"ae3446c39ad254ae138d1fe8fc90a32159fa0e6c","tarball":"https://registry.npmjs.org/@alternative-design-and-media/rentman-api-connector/-/rentman-api-connector-2.6.0.tgz","fileCount":11,"unpackedSize":466319,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFGd4LqV2W2+mKZKDsR+1R50fZ7MdxMy5Hqsxf6gETpLAiAktPELvcFtPg+JYltley+vK0+FutZqKXuCuUj7V2xDIQ=="}]},"_npmUser":{"name":"szantob","email":"szantobenedek@gmail.com"},"directories":{},"maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/rentman-api-connector_2.6.0_1786044867284_0.9798211251997857"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-07T23:02:54.752Z","modified":"2026-08-06T19:34:27.658Z","0.1.0":"2026-05-07T23:02:55.002Z","0.2.0":"2026-05-12T13:44:47.159Z","0.2.1":"2026-05-12T15:04:47.915Z","0.3.0":"2026-05-12T22:14:59.429Z","1.0.0":"2026-05-13T01:59:07.641Z","1.0.1":"2026-05-18T07:31:09.662Z","1.1.0":"2026-05-18T12:08:58.594Z","1.2.0":"2026-05-18T22:38:12.164Z","2.0.0":"2026-05-20T00:19:53.518Z","2.1.0":"2026-05-25T13:23:46.450Z","2.1.2":"2026-05-27T01:12:11.101Z","2.2.0":"2026-05-28T20:59:47.039Z","2.3.0":"2026-06-05T16:10:24.547Z","2.4.0":"2026-06-09T20:29:22.800Z","2.5.0":"2026-07-28T17:15:36.508Z","2.6.0":"2026-08-06T19:34:27.491Z"},"bugs":{"url":"https://github.com/Alternative-Design-And-Media/rentman-api-connector/issues"},"author":{"name":"Alternative Design and Media"},"license":"MIT","homepage":"https://github.com/Alternative-Design-And-Media/rentman-api-connector#readme","keywords":["rentman","api","client","typescript","mcp","cloudflare-workers"],"repository":{"type":"git","url":"git+https://github.com/Alternative-Design-And-Media/rentman-api-connector.git"},"description":"Type-safe Rentman REST API client for Node.js and edge runtimes (Cloudflare Workers). Synced to OAS v1.7.0.","maintainers":[{"name":"szantob","email":"szantobenedek@gmail.com"}],"readme":"# @alternative-design-and-media/rentman-api-connector\n\nv2.3.0\n\n> Type-safe Rentman REST API connector for Node.js and edge runtimes (Cloudflare Workers).\n> Synced to **OAS v1.7.0** (deployment 2025-11-13).\n\n[![npm](https://img.shields.io/npm/v/@alternative-design-and-media/rentman-api-connector)](https://www.npmjs.com/package/@alternative-design-and-media/rentman-api-connector)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n\n---\n\n## Features\n\n- ✅ Full TypeScript types for 55+ Rentman resources (`RentmanEquipmentItem`, `RentmanProject`, `RentmanContact`, …)\n- ✅ Typed response wrappers with **all pagination metadata** (`data`, `itemCount`, `limit`, `offset`, `next_page_url`)\n- ✅ Explicit `updateHash` on every entity for change tracking\n- ✅ Type-safe query builder — `fields`, `sort`, relational operators, `isnull` filters\n- ✅ Cursor-aware auto-pagination helpers for collections larger than 300 items\n- ✅ Preserve-slashes collection helper (`listWithPreservedSlashes`) for resource-path filters\n- ✅ Token normalization helper (`normalizeToken`) — accepts bare JWTs and `\"Bearer ...\"` tokens\n- ✅ Edge-runtime compatible — uses native `fetch` only (Node.js 18+, Cloudflare Workers)\n- ✅ Token rotation via callback — no need to recreate the client on token refresh\n- ✅ Kit/set content via `rentman.equipment.listSetContents()` (+ helper alias `listEquipmentSetContents`)\n- ✅ Equipment field normalizer (`normalizeEquipmentItem`) for mixed OAS/legacy payloads\n- ✅ Typed custom fields — narrow `custom_<number>` keys per entity at compile time\n- ✅ **Prisma-style typed client** — `createTypedClient` integrates account-specific custom fields into the OOP facade\n- ✅ Resource path utilities — `parseResourcePath`, `resourceId`, `buildResourcePath`\n- ✅ Lookup cache helpers — `fetchLookupMap`, `fetchStatusCache`, `fetchFolderNameCache`\n\n---\n\n## Installation\n\n```bash\nnpm install @alternative-design-and-media/rentman-api-connector\n# or\npnpm add @alternative-design-and-media/rentman-api-connector\n```\n\n---\n\n## For AI agents / coding assistants\n\n- Compact reference: [`llms.txt`](./llms.txt)\n- Detailed machine-oriented reference: [`llms-full.txt`](./llms-full.txt)\n\n---\n\n## Quick Start\n\n```ts\nimport {\n  createRentmanClient,\n  projectQuery,\n  equipmentQuery,\n} from '@alternative-design-and-media/rentman-api-connector';\n\n// Create a client once; reuse everywhere.\nconst rentman = createRentmanClient({\n  token: process.env.RENTMAN_TOKEN!, // bare JWT or \"Bearer ...\" also accepted\n  // or an async function: token: () => getTokenFromVault()\n});\n\n// --- OOP facade list with typed query builder ---\nconst projects = await rentman.projects.listAll(\n  projectQuery()\n    .startingAfter('2025-01-01')\n    .sortByStartDate('desc')\n    .build(),\n);\n\n// --- Domain-specific sub-resource helper ---\nconst equipmentLines = await rentman.projects.listEquipment(projects[0].id);\n\n// --- Equipment query builder ---\nconst activeEquipment = await rentman.equipment.listAll(\n  equipmentQuery().notArchived().sortByName().build(),\n);\n\nconsole.log(`Projects: ${projects.length}, active equipment: ${activeEquipment.length}`);\n```\n\n---\n\n## OOP interface (consumer API)\n\nThe supported way to use this package is through the **domain-level OOP facade** — no `ENDPOINTS.*` constants, raw path strings, or manual `RentmanQueryOptions` construction required in your code.\n\n```ts\nimport {\n  createRentmanClient,\n  projectQuery,\n  equipmentQuery,\n  contactQuery,\n  invoiceQuery,\n} from '@alternative-design-and-media/rentman-api-connector';\n\nconst rentman = createRentmanClient({ token: process.env.RENTMAN_TOKEN! });\n\n// 1. List confirmed projects starting after a given date\nconst projects = await rentman.projects.listAll(\n  projectQuery()\n    .startingAfter('2025-01-01')\n    .withStatus('/statuses/3')\n    .sortByStartDate('desc')\n    .build(),\n);\n\n// 2. Equipment lines on the first project\nconst gear = await rentman.projects.listEquipment(projects[0].id);\n\n// 3. Create a new contact\nconst { data: contact } = await rentman.contacts.create({\n  displayname: 'Teszt Kft.',\n  email: 'info@teszt.hu',\n});\n\n// 4. All active equipment, sorted by name\nconst activeGear = await rentman.equipment.listAll(\n  equipmentQuery().notArchived().sortByName().build(),\n);\n\n// 5. Invoice lines for a specific invoice\nconst lines = await rentman.invoices.listLines(42);\n```\n\n### Domain facades at a glance\n\n| Property | Type | Extra methods |\n|---|---|---|\n| `rentman.projects` | `ResourceApi<RentmanProject>` | `listEquipment`, `listCrew`, `listFunctions`, `listVehicles` |\n| `rentman.subProjects` | `ResourceApi<RentmanSubProject>` | — |\n| `rentman.contacts` | `ResourceApi<RentmanContact>` | — |\n| `rentman.contactPersons` | `ResourceApi<RentmanContactPerson>` | — |\n| `rentman.equipment` | `ResourceApi<RentmanEquipmentItem>` | `listSetContents` |\n| `rentman.invoices` | `ResourceApi<RentmanInvoice>` | `listLines`, `listMoments` |\n| `rentman.quotes` | `ResourceApi<RentmanQuote>` | `listLines` |\n| `rentman.crew` | `CrewResourceApi` | — |\n| `rentman.crewAvailabilities` | `ResourceApi<RentmanCrewAvailability>` | — |\n| `rentman.crewRates` | `ResourceApi<RentmanCrewRate>` | — |\n| `rentman.vehicles` | `ResourceApi<RentmanVehicle>` | — |\n| `rentman.payments` | `ResourceApi<RentmanPayment>` | — |\n| `rentman.appointments` | `ResourceApi<RentmanAppointment>` | `listCrew` |\n| `rentman.subrentals` | `ResourceApi<RentmanSubrental>` | `listEquipment`, `listEquipmentGroups` |\n| `rentman.files` | `ResourceApi<RentmanFile>` | — |\n| `rentman.fileFolders` | `ResourceApi<RentmanFileFolder>` | — |\n| `rentman.folders` | `ResourceApi<RentmanFolder>` | — |\n| `rentman.contracts` | `ResourceApi<RentmanContract>` | — |\n| `rentman.costs` | `ResourceApi<RentmanCost>` | — |\n| `rentman.stockMovements` | `ResourceApi<RentmanStockMovement>` | — |\n| `rentman.stockLocations` | `ResourceApi<RentmanStockLocation>` | — |\n| `rentman.timeRegistrations` | `ResourceApi<RentmanTimeRegistration>` | — |\n| `rentman.timeRegistrationActivities` | `ResourceApi<RentmanTimeRegistrationActivity>` | — |\n| `rentman.leaveMutations` | `ResourceApi<RentmanLeaveMutation>` | — |\n| `rentman.leaveRequests` | `ResourceApi<RentmanLeaveRequest>` | — |\n| `rentman.leaveTypes` | `ResourceApi<RentmanLeaveType>` | — |\n| `rentman.repairs` | `ResourceApi<RentmanRepair>` | — |\n| `rentman.serialNumbers` | `ResourceApi<RentmanSerialNumber>` | — |\n| `rentman.accessories` | `ResourceApi<RentmanAccessory>` | — |\n| `rentman.rates` | `ResourceApi<RentmanRate>` | — |\n| `rentman.rateFactors` | `ResourceApi<RentmanRateFactor>` | — |\n| `rentman.factorGroups` | `ResourceApi<RentmanFactorGroup>` | — |\n| `rentman.factors` | `ResourceApi<RentmanFactor>` | — |\n| `rentman.projectTypes` | `ResourceApi<RentmanProjectType>` | — |\n| `rentman.statuses` | `ResourceApi<RentmanStatus>` | — |\n| `rentman.projectStatuses` | `ResourceApi<RentmanProjectStatus>` | — |\n| `rentman.warehouseStatuses` | `ResourceApi<RentmanWarehouseStatus>` | — |\n| `rentman.taxClasses` | `ResourceApi<RentmanTaxClass>` | — |\n| `rentman.ledgerCodes` | `ResourceApi<RentmanLedgerCode>` | — |\n| `rentman.projectRequests` | `ResourceApi<RentmanProjectRequest>` | — |\n| `rentman.projectRequestEquipment` | `ResourceApi<RentmanProjectRequestEquipment>` | — |\n| `rentman.actualContent` | `ResourceApi<RentmanActualContent>` | — |\n| `rentman.equipmentAssignedSerials` | `ResourceApi<RentmanEquipmentAssignedSerial>` | — |\n\nEvery `ResourceApi<T>` exposes:\n\n```ts\ninterface ResourceApi<T, TCreate = Partial<T>> {\n  list(query?: RentmanQueryOptions): Promise<RentmanCollectionResponse<T>>;\n  listAll(query?: Omit<RentmanQueryOptions, 'limit' | 'offset'>): Promise<T[]>;\n  getById(id: number, query?: Pick<RentmanQueryOptions, 'fields'>): Promise<RentmanItemResponse<T>>;\n  create(body: TCreate): Promise<RentmanItemResponse<T>>;\n  update(id: number, body: TCreate): Promise<RentmanItemResponse<T>>;\n  delete(id: number): Promise<void>;\n}\n```\n\n### Typed query builders\n\nUse the typed query builder helpers to compose `RentmanQueryOptions` without touching the raw type:\n\n| Builder | Factory | Domain-specific methods |\n|---|---|---|\n| `ProjectQueryBuilder` | `projectQuery()` | `startingAfter(date)`, `startingBefore(date)`, `withStatus(path)`, `forCustomer(path)`, `forCustomerId(id)`, `forProjectType(id)`, `notArchived()`, `inFolder(path)`, `sortByStartDate(dir?)`, `sortByName(dir?)` |\n| `EquipmentQueryBuilder` | `equipmentQuery()` | `notArchived()`, `inFolder(path)`, `sortByName(dir?)` |\n| `ContactQueryBuilder` | `contactQuery()` | `inCountry(code)`, `notArchived()`, `sortByName(dir?)` |\n| `InvoiceQueryBuilder` | `invoiceQuery()` | `withStatus(path)`, `forContact(path)`, `dueBefore(date)`, `dueAfter(date)`, `sortByDate(dir?)`, `sortByDueDate(dir?)` |\n\nAll builders also inherit `fields(...)`, `sort(...)`, `limit(n)`, `offset(n)`, and `.build()`.\n\n> ⚠️ **`offset(n)` is deprecated.** Rentman removes `?offset=` pagination in Q4 2026. `listAll` / `listAllSub` / `scanAll` already follow cursor pages (`next_page_url`) automatically — but the API only returns a cursor when the result set is sorted by `id`. Sort by `id` and re-sort client-side if you need a different order.\n\n> ⚠️ **Deprecated**: low-level direct API-call methods (`client.list`, `client.listAll`, `client.listSub`, `client.listAllSub`, `client.get`, `client.create`, `client.update`, `client.delete`) are kept only for migration and are no longer supported for new implementations.\n\n---\n\n## Implemented API Connectors\n\nAll 52 top-level collection endpoints from OAS v1.7.0 are available as typed constants in `ENDPOINTS`.\n\n### Equipment & Inventory\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `equipment` | `/equipment` | `RentmanEquipmentItem` | Equipment items (gear, props, sets) |\n| `equipmentSetsContent` | `/equipmentsetscontent` | `RentmanEquipmentSetContent` | Kit / set components |\n| `actualContent` | `/actualcontent` | `RentmanActualContent` | Actual serial content of combinations |\n| `equipmentAssignedSerials` | `/equipmentassignedserials` | `RentmanEquipmentAssignedSerial` | Assigned serial links for combinations |\n| `accessories` | `/accessories` | `RentmanAccessory` | Equipment accessories |\n| `stockMovements` | `/stockmovements` | `RentmanStockMovement` | Inventory in/out movements |\n| `stockLocations` | `/stocklocations` | `RentmanStockLocation` | Warehouse stock locations |\n| `serialNumbers` | `/serialnumbers` | `RentmanSerialNumber` | Serial-tracked equipment |\n| `repairs` | `/repairs` | `RentmanRepair` | Repair / service records |\n\n### Contacts & People\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `contacts` | `/contacts` | `RentmanContact` | Companies and persons |\n| `contactPersons` | `/contactpersons` | `RentmanContactPerson` | Persons linked to a contact |\n| `crew` | `/crew` | `RentmanCrewMember` | Crew / staff members |\n| `crewAvailabilities` | `/crewavailability` | `RentmanCrewAvailability` | Crew availability windows |\n| `crewRates` | `/crewrates` | `RentmanCrewRate` | Crew rate assignments |\n\n### Projects\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `projects` | `/projects` | `RentmanProject` | Top-level projects |\n| `subProjects` | `/subprojects` | `RentmanSubProject` | Sub-projects / sections |\n| `projectEquipment` | `/projectequipment` | `RentmanProjectEquipment` | Equipment lines on a project |\n| `projectEquipmentGroups` | `/projectequipmentgroup` | `RentmanProjectEquipmentGroup` | Equipment line groups |\n| `projectFunctions` | `/projectfunctions` | `RentmanProjectFunction` | Crew function lines on a project |\n| `projectFunctionGroups` | `/projectfunctiongroups` | `RentmanProjectFunctionGroup` | Function line groups |\n| `projectCrew` | `/projectcrew` | `RentmanProjectCrew` | Crew assignments on a project |\n| `projectVehicles` | `/projectvehicles` | `RentmanProjectVehicle` | Vehicle assignments on a project |\n| `projectRequests` | `/projectrequests` | `RentmanProjectRequest` | Incoming project requests |\n| `projectRequestEquipment` | `/projectrequestequipment` | `RentmanProjectRequestEquipment` | Equipment linked to project requests |\n| `projectTypes` | `/projecttypes` | `RentmanProjectType` | Project type lookup values |\n\n### Finance\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `invoices` | `/invoices` | `RentmanInvoice` | Invoices |\n| `invoiceLines` | `/invoicelines` | `RentmanInvoiceLine` | Individual invoice lines |\n| `quotes` | `/quotes` | `RentmanQuote` | Quotes / offers |\n| `payments` | `/payments` | `RentmanPayment` | Payments against invoices |\n| `costs` | `/costs` | `RentmanCost` | Additional costs on a project |\n| `taxClasses` | `/taxclasses` | `RentmanTaxClass` | VAT / tax class definitions |\n| `ledgerCodes` | `/ledgercodes` | `RentmanLedgerCode` | Accounting ledger codes |\n| `rates` | `/rates` | `RentmanRate` | Rate / pricing rules |\n| `rateFactors` | `/ratefactors` | `RentmanRateFactor` | Crew rate factor ranges |\n| `factors` | `/factors` | `RentmanFactor` | Pricing factors |\n| `factorGroups` | `/factorgroups` | `RentmanFactorGroup` | Factor groups |\n\n### Subrentals\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `subrentals` | `/subrentals` | `RentmanSubrental` | Subrental orders |\n| `subrentalEquipment` | `/subrentalequipment` | `RentmanSubrentalEquipment` | Equipment lines on a subrental |\n| `subrentalEquipmentGroups` | `/subrentalequipmentgroup` | `RentmanSubrentalEquipmentGroup` | Equipment groups on a subrental |\n\n### Appointments & Vehicles\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `appointments` | `/appointments` | `RentmanAppointment` | Calendar appointments |\n| `appointmentCrew` | `/appointmentcrew` | `RentmanAppointmentCrew` | Crew on an appointment |\n| `vehicles` | `/vehicles` | `RentmanVehicle` | Vehicle records |\n\n### Time & Leave\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `timeRegistrations` | `/timeregistration` | `RentmanTimeRegistration` | Time registration records |\n| `timeRegistrationActivities` | `/timeregistrationactivities` | `RentmanTimeRegistrationActivity` | Time registration activity types |\n| `leaveMutations` | `/leavemutation` | `RentmanLeaveMutation` | Leave balance mutations |\n| `leaveRequests` | `/leaverequest` | `RentmanLeaveRequest` | Leave requests from crew |\n| `leaveTypes` | `/leavetypes` | `RentmanLeaveType` | Leave type definitions |\n\n### Files & Folders\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `files` | `/files` | `RentmanFile` | File attachments |\n| `fileFolders` | `/file_folders` | `RentmanFileFolder` | File folders |\n| `folders` | `/folders` | `RentmanFolder` | General folder structure |\n\n### Reference / Lookup Tables\n\n| `ENDPOINTS` key | API path | Type | Description |\n|---|---|---|---|\n| `statuses` | `/statuses` | `RentmanStatus` | Status lookup values (union of both views below) |\n| `projectStatuses` | `/projectstatuses` | `RentmanProjectStatus` | Project statuses only — Pending, Canceled, Confirmed, Inquiry, Concept |\n| `warehouseStatuses` | `/warehousestatuses` | `RentmanWarehouseStatus` | Warehouse statuses only — Confirmed, Prepped, On location, Returned, Contracted, Finalized, Completed |\n| `contracts` | `/contracts` | `RentmanContract` | Contracts on a project |\n\n#### Comparing statuses (Q4 2026 endpoint split)\n\nRentman is splitting `/statuses` into `/projectstatuses` + `/warehousestatuses`, and has **not** documented whether references such as `subprojects.status` will keep returning `/statuses/{id}` or switch to `/projectstatuses/{id}`.\n\nThat question does not need an answer, because the **ID space is shared**. Measured live on 2026-07-28: `Canceled` is `2` and `Confirmed` is `3` on all three endpoints. Compare IDs, not path strings:\n\n```ts\nimport { statusIdFromPath, isSameStatus } from '@alternative-design-and-media/rentman-api-connector';\n\n// ❌ Breaks silently the moment the prefix moves — no error, just `false` for every row.\nif (subproject.status === '/statuses/2') { /* cancelled */ }\n\n// ✅ Correct today and after the split.\nif (statusIdFromPath(subproject.status) === 2) { /* cancelled */ }\nif (isSameStatus(subproject.status, cancelledPath)) { /* cancelled */ }\n```\n\n`statusIdFromPath()` returns `null` for non-status paths, so a `/projects/2` reference can never be mistaken for status `2`. `isSameStatus()` returns `false` when either side is unresolvable — an unknown status never reads as a match.\n\nThe lookup cache is prefix-proof too:\n\n```ts\nconst statuses = await fetchStatusCache(client);           // or fetchProjectStatusCache(client)\nstatuses.byId.get(3);                                      // \"Confirmed\"\nstatuses.nameForPath('/projectstatuses/3');                // \"Confirmed\" — any prefix resolves\n```\n\n> `/statuses` itself is **not** deprecated — the changelog does not announce its removal. What Q4 2026 forbids is *writing* a warehouse status into `subprojects.status`.\n>\n> `itemtype` does not tell the two views apart: requesting it explicitly returns rows with no `itemtype` key at all. The endpoint you call is the only discriminator.\n\n### Known TypeScript ↔ OAS field-name mappings\n\nThese legacy aliases are intentionally preserved for backward compatibility:\n\n| TypeScript field | OAS field | Entity | Note |\n|---|---|---|---|\n| `postcode` | `postal_code` | `RentmanCrewMember` | Legacy abbreviation |\n| `middle` | `middle_name` | `RentmanCrewMember` | Simplified name |\n| `surname` | `lastname` | `RentmanCrewMember` | Terminology difference |\n| `tag` | `tags` | `RentmanCrewMember` | Singular vs plural |\n| `contact` | `customer` / `cust_contact` | `RentmanProject`, `RentmanInvoice` | OAS uses two related fields |\n| `projecttype` | `project_type` | `RentmanProject` | Legacy casing mismatch |\n| `due_date` | `expiration` | `RentmanInvoice` | Different legacy semantic naming |\n\n---\n\n## Detailed Usage Examples (legacy low-level API, deprecated)\n\n> ⚠️ This section documents the old direct endpoint-based API for migration only. New implementations should use the OOP facade (`rentman.projects`, `rentman.equipment`, `rentman.contacts`, ...).\n\n### Listing with field selection and sorting\n\nOnly request the fields you need to keep responses lean. Pass `fields` as an array of field names; the API returns only those keys.\n\n```ts\nimport { createRentmanClient, ENDPOINTS, type RentmanEquipmentItem } from '@alternative-design-and-media/rentman-api-connector';\n\nconst rentman = createRentmanClient({ token: process.env.RENTMAN_TOKEN! });\n\nconst { data, itemCount } = await rentman.list<RentmanEquipmentItem>(ENDPOINTS.equipment, {\n  fields: ['id', 'name', 'code', 'in_quantity', 'current_quantity', 'location_in_warehouse'],\n  sort: ['+name'],          // prefix '+' = ascending, '-' = descending\n  limit: 100,\n  // No `offset` — it is deprecated (removed by Rentman in Q4 2026). Use cursor\n  // pagination via `listAll` / `scanAll`, which follow `next_page_url` for you.\n});\n\nfor (const item of data) {\n  console.log(`[${item.code}] ${item.name} — stock: ${item.current_quantity}`);\n}\n```\n\n### Auto-pagination (`listAll`)\n\nCollection requests are now **cursor-based by default**. Rentman still defaults to **300** items per page, but now allows up to **1500**. `listAll` follows `next_page_url` automatically and falls back to offset pagination only when the API omits `next_page_url` (for example when sorting by a non-`id` field).\n\n```ts\nconst allProjects = await rentman.listAll<RentmanProject>(ENDPOINTS.projects, {\n  fields: ['id', 'number', 'name', 'status', 'planperiod_start', 'planperiod_end'],\n  sort: ['-planperiod_start'],\n});\n\nconsole.log(`Total projects: ${allProjects.length}`);\n```\n\n### Filtering\n\n#### Exact-match filter (`filters`)\n\nPass key/value pairs to filter by equality. Multiple pairs are ANDed together.\n\n```ts\nconst ukContacts = await rentman.list<RentmanContact>(ENDPOINTS.contacts, {\n  filters: { country: 'gb' },\n  fields: ['id', 'displayname', 'email'],\n});\n```\n\n#### Relational filter (`relFilters`)\n\nUse `rel(field, operator, value)` for comparisons. Supported operators: `gt`, `gte`, `lt`, `lte`, `neq`.\n\n```ts\nimport { rel } from '@alternative-design-and-media/rentman-api-connector';\n\n// Equipment items with a replacement cost greater than 500\nconst expensive = await rentman.list<RentmanEquipmentItem>(ENDPOINTS.equipment, {\n  relFilters: [rel('replacement_cost', 'gt', 500)],\n  sort: ['-replacement_cost'],\n});\n```\n\n#### Null / not-null filter (`nullFilters`)\n\nUse `notNull(field)` or `isNull(field)` to check for the presence or absence of a value.\n\n```ts\nimport { notNull, isNull } from '@alternative-design-and-media/rentman-api-connector';\n\n// Projects that have a contact assigned and are not archived\nconst activeProjects = await rentman.list<RentmanProject>(ENDPOINTS.projects, {\n  nullFilters: [notNull('contact')],\n  filters: { status: 'confirmed' },\n});\n\n// Equipment without a folder (unorganised items)\nconst unorganised = await rentman.list<RentmanEquipmentItem>(ENDPOINTS.equipment, {\n  nullFilters: [isNull('folder')],\n});\n```\n\n#### Combining all filter types\n\n```ts\nconst result = await rentman.list<RentmanEquipmentItem>(ENDPOINTS.equipment, {\n  filters: { type: 'set' },\n  relFilters: [rel('in_quantity', 'gte', 1)],\n  nullFilters: [notNull('folder'), notNull('code')],\n  sort: ['+name'],\n  fields: ['id', 'name', 'code', 'in_quantity'],\n  limit: 50,\n});\n```\n\n### Getting a single item\n\n```ts\nconst { data: project } = await rentman.get<RentmanProject>(ENDPOINTS.projects, 1234);\n\nconsole.log(project.name);          // typed string\nconsole.log(project.planperiod_start); // typed string | null\nconsole.log(project.updateHash);    // use to detect changes\n```\n\n### Creating a resource\n\n```ts\nconst { data: newMovement } = await rentman.create<Partial<RentmanStockMovement>, RentmanStockMovement>(\n  ENDPOINTS.stockMovements,\n  {\n    equipment: '/equipment/42',\n    quantity: 10,\n    type: 'manual',\n    date: new Date().toISOString(),\n    remark: 'Received from supplier',\n  }\n);\nconsole.log(`Created movement id: ${newMovement.id}`);\n```\n\n### Updating a resource\n\nOnly send the fields you want to change. The connector issues a `PUT` request with your partial payload.\n\n```ts\nawait rentman.update(ENDPOINTS.equipment, 42, {\n  remark: 'Calibrated 2025-01',\n  location_in_warehouse: 'Shelf A3',\n});\n```\n\n### Deleting a resource\n\n```ts\nawait rentman.delete(ENDPOINTS.equipment, 99);\n```\n\n### Token rotation (zero-downtime)\n\nPass an async factory instead of a static string. The client calls it before every request.\n\n```ts\nconst rentman = createRentmanClient({\n  token: async () => {\n    // Fetch a fresh JWT from your vault / KV store\n    return await getTokenFromKV('rentman_token');\n  },\n});\n```\n\n---\n\n## Custom Fields\n\nRentman supports account-specific custom fields on many entities. They are returned by the API as `custom_<number>` keys inside the `custom` object (e.g. `custom_16`, `custom_57`).\n\n### Default behaviour (open type)\n\nBy default the `custom` field is typed as `Partial<Record<\\`custom_\\${number}\\`, string | number | boolean | null>>`. This keeps backward compatibility but loses autocomplete for specific keys.\n\n```ts\nconst { data: item } = await rentman.get<RentmanEquipmentItem>(ENDPOINTS.equipment, 42);\n// custom is typed as Partial<Record<`custom_${number}`, ...>>\nconsole.log(item.custom?.custom_16); // works, but no autocomplete for the key name\n```\n\n### Narrowing custom fields (recommended)\n\nDefine an interface with the exact keys used in your Rentman account and pass it as the `TCustom` type argument. You get full autocomplete and compile-time safety.\n\n```ts\nimport {\n  createRentmanClient,\n  ENDPOINTS,\n  type RentmanEquipmentItem,\n} from '@alternative-design-and-media/rentman-api-connector';\n\n// Define YOUR account's custom fields for equipment\ninterface EquipmentCustom {\n  custom_16?: string;  // \"Name EN\" — English description\n  custom_57?: string;  // \"Safety ID\" — safety certification code\n  custom_88?: number;  // \"Weight net (kg)\"\n}\n\n// Apply the type argument\ntype MyEquipmentItem = RentmanEquipmentItem<EquipmentCustom>;\n\nconst rentman = createRentmanClient({ token: process.env.RENTMAN_TOKEN! });\n\nconst { data: item } = await rentman.get<MyEquipmentItem>(ENDPOINTS.equipment, 42);\n\n// Now fully typed and autocompleted:\nconsole.log(item.custom?.custom_16); // string | undefined\nconsole.log(item.custom?.custom_57); // string | undefined\nconsole.log(item.custom?.custom_88); // number | undefined\n```\n\n### Custom fields on other entities\n\nThe same pattern works on any entity that extends `RentmanBaseEntityWithCustom`:\n\n| Type | Supports `TCustom` |\n|---|---|\n| `RentmanEquipmentItem` | ✅ |\n| `RentmanContact` | ✅ |\n| `RentmanContactPerson` | ✅ |\n| `RentmanCrewMember` | ✅ |\n| `RentmanProject` | ✅ |\n| `RentmanSubProject` | ✅ |\n| `RentmanVehicle` | ✅ |\n| `RentmanSubrental` | ✅ |\n| `RentmanSubrentalEquipment` | ✅ |\n| `RentmanTimeRegistration` | ✅ |\n| `RentmanRepair` | ✅ |\n| `RentmanSerialNumber` | ✅ |\n\n### Example: typed custom fields on a project\n\n```ts\ninterface ProjectCustom {\n  custom_3?: string;   // \"PO Number\"\n  custom_11?: boolean; // \"Requires insurance\"\n  custom_24?: number;  // \"Estimated crew hours\"\n}\n\ntype MyProject = RentmanProject<ProjectCustom>;\n\nconst { data: project } = await rentman.get<MyProject>(ENDPOINTS.projects, 500);\n\nif (project.custom?.custom_11) {\n  console.log(`Project ${project.name} requires insurance. PO: ${project.custom.custom_3}`);\n}\n```\n\n### Accessing unknown / unmapped fields\n\nIf you need to access a field that is not yet in the type definitions (e.g. after a Rentman API update), use `WithUnknownFields<T>`:\n\n```ts\nimport { type WithUnknownFields, type RentmanEquipmentItem } from '@alternative-design-and-media/rentman-api-connector';\n\nconst { data: raw } = await rentman.get<WithUnknownFields<RentmanEquipmentItem>>(ENDPOINTS.equipment, 42);\nconsole.log(raw.someNewUnmappedField); // typed as `unknown`, no compile error\n```\n\n### Custom fields + OOP facade (Prisma-style DX)\n\nUse `createTypedClient` to integrate account-specific custom fields directly into the OOP facade — no low-level API calls needed. The pattern is inspired by Prisma's `prisma generate` / graphql-codegen workflow.\n\n#### Step 1 — Define your custom fields config\n\n```json\n// custom-fields.config.json\n[\n  { \"id\": 11, \"name\": \"budget\", \"belongs_to\": \"project\", \"type\": \"price\", \"input_fields_group\": \"General\", \"required\": false },\n  { \"id\": 12, \"name\": \"category\", \"belongs_to\": \"project\", \"type\": \"dropdown\", \"input_fields_group\": \"General\", \"required\": true,\n    \"options\": [{ \"id\": 1, \"name\": \"Conference\" }, { \"id\": 2, \"name\": \"Wedding\" }] },\n  { \"id\": 21, \"name\": \"serial_prefix\", \"belongs_to\": \"equipment\", \"type\": \"text\", \"input_fields_group\": \"General\", \"required\": false }\n]\n```\n\n#### Step 2 — Regenerate types (run once per config change)\n\n```bash\nnpx generate-rentman-custom-fields\n# or inside your project:\nnpm run generate:custom-fields\n```\n\nThis writes `src/generated/custom-fields.generated.ts` which includes a `RentmanCustomFields extends CustomFieldMap` interface alongside per-model helpers.\n\n#### Step 3 — Create the typed client (written once by hand)\n\n```ts\n// src/lib/rentman.ts\nimport {\n  createRentmanClient,\n  createTypedClient,\n} from '@alternative-design-and-media/rentman-api-connector';\nimport type { RentmanCustomFields } from './generated/custom-fields.generated';\n\nconst base = createRentmanClient({ token: process.env.RENTMAN_TOKEN! });\n\n// The second argument is only used for TypeScript inference.\n// {} as RentmanCustomFields is sufficient at runtime.\nexport const rentman = createTypedClient(base, {} as RentmanCustomFields);\n```\n\n#### Step 4 — Use in your application code\n\n```ts\nimport { rentman } from './lib/rentman';\n\nconst projects = await rentman.projects.listAll();\nprojects[0].custom?.budget;   // ✅ number\nprojects[0].custom?.category; // ✅ 'Conference' | 'Wedding'\n\nconst items = await rentman.equipment.listAll();\nitems[0].custom?.serial_prefix; // ✅ string | undefined\n\nconst crew = await rentman.crew.listAll();\ncrew[0].custom?.has_driving_license; // ✅ boolean\n\nconst contactPersons = await rentman.contactPersons.listAll();\n// Requires a `contactPersons` schema in your generated CustomFieldMap.\ncontactPersons[0].custom?.has_signing_authority; // ✅ boolean\n\n// Deprecated low-level API (migration only)\nconst raw = await rentman.list(ENDPOINTS.projects);\n\n// Sub-resource methods are preserved on the typed client\nconst equipment = await rentman.projects.listEquipment(123);\n```\n\nEntities without custom fields in your `CustomFieldMap` fall back to `Record<string, never>` (typed, but no false positives). Backward compatible: `createRentmanClient` without `createTypedClient` continues to work unchanged.\n\n---\n\n## Resource Path Utilities\n\nRentman resource references are path strings like `\"/contacts/123\"`. These helpers let you parse, extract, and build those paths in a null-safe, type-safe way.\n\n### `parseResourcePath(path)`\n\nParses a path into its entity name and numeric ID. Returns `null` for any invalid or missing input.\n\n```ts\nimport { parseResourcePath } from '@alternative-design-and-media/rentman-api-connector';\n\nparseResourcePath('/contacts/123') // → { entity: 'contacts', id: 123 }\nparseResourcePath('/equipment/42') // → { entity: 'equipment', id: 42 }\nparseResourcePath(null)            // → null\nparseResourcePath('/contacts')     // → null  (no ID segment)\nparseResourcePath('/contacts/abc') // → null  (non-numeric ID)\n```\n\n### `resourceId(path)`\n\nExtracts only the numeric ID from a path. Returns `null` for any invalid or missing input.\n\n```ts\nimport { resourceId } from '@alternative-design-and-media/rentman-api-connector';\n\nresourceId('/folders/42')  // → 42\nresourceId('/contacts/0')  // → 0\nresourceId(null)           // → null\nresourceId('/contacts')    // → null\n```\n\n### `buildResourcePath(endpoint, id)`\n\nBuilds a canonical Rentman resource path from a typed `ENDPOINTS` constant and a numeric ID.\n\n```ts\nimport { buildResourcePath, ENDPOINTS } from '@alternative-design-and-media/rentman-api-connector';\n\nbuildResourcePath(ENDPOINTS.contacts, 123)  // → '/contacts/123'\nbuildResourcePath(ENDPOINTS.equipment, 42)  // → '/equipment/42'\n\n// Use the result directly as a field value in create/update payloads:\nawait rentman.create(ENDPOINTS.stockMovements, {\n  equipment: buildResourcePath(ENDPOINTS.equipment, 42),\n  quantity: 10,\n  type: 'manual',\n});\n```\n\n---\n\n## Lookup Cache Helpers\n\nThese helpers fetch an entire reference endpoint and build a `Map` for fast lookups.\nThey are useful for resolving Rentman resource paths (e.g. `\"/statuses/3\"`) to display names without repeated API calls.\n\n### `fetchLookupMap<T, V>(client, endpoint, query, toEntry)`\n\nGeneric helper that fetches **all pages** of any endpoint and builds a `Map` using a caller-supplied key/value extractor. First-wins when `toEntry` returns duplicate keys.\n\n```ts\nimport {\n  createRentmanClient,\n  ENDPOINTS,\n  fetchLookupMap,\n  type RentmanTaxClass,\n} from '@alternative-design-and-media/rentman-api-connector';\n\nconst rentman = createRentmanClient({ token: process.env.RENTMAN_TOKEN! });\n\n// Build an id → name map for tax classes\nconst taxMap = await fetchLookupMap<RentmanTaxClass, string>(\n  rentman,\n  ENDPOINTS.taxClasses,\n  {},\n  (tc) => [String(tc.id), tc.name],\n);\n\nconsole.log(taxMap.get('1')); // e.g. \"21%\"\n```\n\n### `fetchStatusCache(client)`\n\nFetches all Rentman statuses and returns **two** Maps for bidirectional lookups:\n\n- `byName` — lowercase status name → resource path (e.g. `\"confirmed\"` → `\"/statuses/3\"`)\n- `byPath` — resource path → display name (e.g. `\"/statuses/3\"` → `\"Confirmed\"`)\n\n```ts\nimport {\n  createRentmanClient,\n  fetchStatusCache,\n} from '@alternative-design-and-media/rentman-api-connector';\n\nconst rentman = createRentmanClient({ token: process.env.RENTMAN_TOKEN! });\n\nconst { byName, byPath } = await fetchStatusCache(rentman);\n\nconst path  = byName.get('confirmed');     // \"/statuses/3\"\nconst label = byPath.get('/statuses/3');   // \"Confirmed\"\n```\n\n### `fetchFolderNameCache(client)`\n\nFetches all equipment folders and returns a `Map` of resource path → folder name.\n\n```ts\nimport {\n  createRentmanClient,\n  fetchFolderNameCache,\n} from '@alternative-design-and-media/rentman-api-connector';\n\nconst rentman = createRentmanClient({ token: process.env.RENTMAN_TOKEN! });\n\nconst folderNames = await fetchFolderNameCache(rentman);\n\nconsole.log(folderNames.get('/folders/116')); // \"Lighting\"\n```\n\n---\n\n## API Reference\n\n### `createRentmanClient(options)`\n\n| Option | Type | Required | Description |\n|---|---|---|---|\n| `token` | `string \\| () => string \\| Promise<string>` | ✅ | JWT token or async factory. Using a function enables zero-downtime token rotation. |\n| `baseUrl` | `string` | — | Override the API base URL (default: `https://api.rentman.net`). Useful for testing. |\n| `fetch` | `typeof fetch` | — | Custom fetch implementation. Defaults to `globalThis.fetch`. |\n\nStatic `token` values may be provided either as a bare JWT or as a `\"Bearer ...\"` string. The client normalizes the prefix internally.\n\n### `client.list<T>(path, query?)` (deprecated)\n\nFetch a collection. Returns `RentmanCollectionResponse<T>` with `data`, `itemCount`, `limit`, `offset`, and optional `next_page_url`.\n\n### `client.listAll<T>(path, query?, pageSize?)` (deprecated)\n\nAuto-paginate through all items. `pageSize` defaults to `1500` (the Rentman API max), while the API itself still defaults to `300` when no limit is sent.\n\n### `listWithPreservedSlashes<T>(client, endpoint, query, options?)` (deprecated)\n\nFetch a collection while keeping `/` characters unescaped in resource-path filter values such as `equipment[eq]=/equipment/4362`.\n\n### `scanAll<T>(client, endpoint, query, options?)` (deprecated)\n\nPaginated scan helper that returns `{ items, totalCount, limitReached }`.\n\n```ts\nimport { ENDPOINTS, scanAll } from '@alternative-design-and-media/rentman-api-connector';\n\nconst { items, limitReached, totalCount } = await scanAll(rentman, ENDPOINTS.subProjects, {\n  sort: ['modified'],\n}, {\n  pageSize: 300,\n  scanLimit: 1500,\n});\n```\n\n### `normalizeToken(token)`\n\nStrips an optional `\"Bearer \"` prefix from a token string.\n\n```ts\nimport { normalizeToken } from '@alternative-design-and-media/rentman-api-connector';\n\nconst token = normalizeToken('Bearer eyJhbGciOi...');\n```\n\n### `client.listSub<T>(parentPath, parentId, subPath, query?)` (deprecated)\n\nFetch a sub-resource collection via path-level URL generation (`${parentPath}/${parentId}${subPath}`).\n\n```ts\nconst { data } = await rentman.listSub(\n  ENDPOINTS.equipment,\n  3473,\n  '/equipmentsetscontent',\n);\n```\n\n### `client.listAllSub<T>(parentPath, parentId, subPath, query?, pageSize?)` (deprecated)\n\nBackward-compatible sub-resource list helper. When `query.limit` is omitted, auto-paginates\nthrough all items starting from `query.offset` (defaults to `0`) and returns a flat array.\nWhen `query.limit` is provided, returns only that single page's `data` array without\nauto-paginating. Use the explicit `*Paged` methods when page metadata (e.g. `itemCount`) is\nrequired.\n\n### `listEquipmentSetContents(client, kitId)` (deprecated)\n\nBackward-compatible wrapper around `client.equipment.listSetContents(kitId)`.\n\n```ts\nimport {\n  listEquipmentSetContents,\n  type RentmanEquipmentSetContent,\n} from '@alternative-design-and-media/rentman-api-connector';\n\nconst contents: RentmanEquipmentSetContent[] = await listEquipmentSetContents(rentman, 3473);\n```\n\n### `client.get<T>(path, id, query?)` (deprecated)\n\nFetch a single item by numeric ID.\n\n### `client.create<TIn, TOut>(path, body)` (deprecated)\n\nPOST a new item.\n\n### `client.update<TIn, TOut>(path, id, body)` (deprecated)\n\nPUT an updated item.\n\n### `client.delete(path, id)` (deprecated)\n\nDELETE an item by ID.\n\n### `normalizeEquipmentItem(item)`\n\nNormalizes mixed Rentman equipment payloads into a single predictable shape. It merges OAS fields (for example `current_quantity`) with legacy aliases (for example `currentquantity`), and also keeps the raw item in `_raw`.\n\n```ts\nimport {\n  normalizeEquipmentItem,\n  type RentmanEquipmentItem,\n} from '@alternative-design-and-media/rentman-api-connector';\n\nconst { data: rawItem } = await rentman.equipment.getById(42);\nconst normalized = normalizeEquipmentItem(rawItem);\n\nconsole.log(normalized.currentQuantity, normalized.locationInWarehouse);\n```\n\n### Query builder helpers\n\n```ts\nimport {\n  rel,\n  notNull,\n  isNull,\n  buildQueryParams,\n  buildQueryString,\n  buildRentmanQuery,\n} from '@alternative-design-and-media/rentman-api-connector';\n\n// rel(field, op, value) — relational filter\nrel('distance', 'lte', 300)    // → distance[lte]=300\n\n// notNull(field) / isNull(field) — null-check filter\nnotNull('folder')              // → folder[isnull]=false\nisNull('archive')              // → archive[isnull]=true\n\n// buildQueryParams(options) — returns a plain Record<string, string>\nconst queryParams = buildQueryParams({\n  filters: { 'in_archive[eq]': false },\n});\n// → { 'in_archive[eq]': '0' }\n\n// buildQueryString(options, { preserveSlashes: true }) — keeps path filter slashes readable\nconst queryString = buildQueryString(\n  { filters: { 'status[eq]': '/statuses/3' } },\n  { preserveSlashes: true },\n);\n// → ?status%5Beq%5D=/statuses/3\n\n// buildRentmanQuery(options) — returns URLSearchParams\nconst params = buildRentmanQuery({\n  fields: ['id', 'name'],\n  sort: ['+name'],\n  filters: { country: 'gb' },\n  relFilters: [rel('distance', 'lte', 300)],\n  nullFilters: [notNull('folder')],\n  limit: 50,\n  offset: 0,\n});\n```\n\n### Preserving slashes in resource-path filters\n\nSome Rentman collection filters expect a resource path value such as `/equipment/4362`. In these cases, `%2F`-encoding the slash can break Rentman’s parser. Use `listWithPreservedSlashes()` for collection requests that need this encoding behavior.\n\n```ts\nimport {\n  ENDPOINTS,\n  listWithPreservedSlashes,\n  type RentmanEquipmentSetContent,\n} from '@alternative-design-and-media/rentman-api-connector';\n\nconst query = {\n  filters: { 'equipment[eq]': '/equipment/4362' },\n};\n\nconst { data } = await listWithPreservedSlashes<RentmanEquipmentSetContent>(\n  rentman,\n  ENDPOINTS.equipmentSetsContent,\n  query,\n  { limit: 100, offset: 0 },\n);\n```\n\n`listWithPreservedSlashes()` still percent-encodes other reserved characters in values; it only keeps `/` readable for resource-path filters.\n\n---\n\n## OAS Alignment\n\n| OAS version | Deployment date | Synced |\n|---|---|---|\n| 1.7.0 | 2025-11-13 | ✅ |\n\n### Conventions\n\n- **Field names** follow the OAS schema (mostly `snake_case`, matching Rentman's API).\n- **Generated fields** (marked in the OAS as `GENERATED FIELD`) are annotated with a JSDoc comment on the type. They cannot be sorted on when `limit`/`offset` are set, and cannot be used as filter keys.\n- **`updateHash`** is present on every entity. Use it to detect changes cheaply without comparing all fields.\n- **`custom`** exposes the `custom_<number>` keys returned by the API. Narrow the type at compile time by passing a `TCustom` type argument (see [Custom Fields](#custom-fields)).\n- **Pagination**: collection responses are cursor-based by default. The API default page size is 300, the max is 1500, and `listAll()` / `listAllSub()` follow `next_page_url` automatically.\n- **Rate limits**: 50 000 requests/day, 10 req/s, max 20 concurrent requests.\n\n---\n\n## Contributing\n\nPull requests are welcome. When adding a new resource type:\n\n1. Add the interface to `src/types.ts`, extending `RentmanBaseEntity` (or `RentmanBaseEntityWithCustom<TCustom>` if the entity has custom fields).\n2. Annotate any `GENERATED FIELD` with a JSDoc comment.\n3. Add the endpoint path to `src/endpoints.ts`.\n4. Run `npm test` before submitting.\n\n---\n\n## License\n\nMIT © Alternative Design and Media\n","readmeFilename":"README.md"}