{"_id":"remix-easy-mode","_rev":"61-d5e8a64233d5036e76028e819aaf499a","name":"remix-easy-mode","dist-tags":{"latest":"0.2.2","beta":"0.2.2-beta.0"},"versions":{"0.0.19":{"name":"remix-easy-mode","version":"0.0.19","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error ha","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","superjson":"^1","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","superjson","libary","framework"],"gitHead":"3072c65d7a0179953b9ae2d1679f41e7daaf1454","_id":"remix-easy-mode@0.0.19","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-ZiuF2qQBjB7b/i0/OJbv6e7XfaC0ADyV6G8g1+H74O31z8Qgq8s+gf/97p6eDPBo1DMgu5fUYG30JF8r87hIPA==","shasum":"cd6bee54f84152a52b4cac36176308f6c813e51e","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.19.tgz","fileCount":5,"unpackedSize":40209,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfsosLQpJT79NSdxIwlnGBgtMoo8yD8cptS1uCrdf9fAIgPz5JS61UW+GLwi/K7eWF014OoO+TJkdc0+4IjwxHw3s="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLEbvACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpVDQ//ZGdmqKC+z2wFFyc60ENxdYK5Vg8Mk45WIvAsYE8oFbdIVfSg\r\nE6OtuaWWH0RGj3TUr85bCTyF2Jkeams8ICpZp29MaW0oQbImW4rlVGmGMhSs\r\nE1Yd4UwfnMufoMS/LFdpQCvDTlQ0X0R/qHBMBfP+NwT7KK7IC3TM51mBwXGl\r\nidVc1G4OFM7yI473QNtBxkSsZzhcbzejLPCyxF3+ncKeduZ+IajtOYOsXaRw\r\nhIUQeFXnTm/5aRIbPijkRbruPW+ahWFR3PaXvdmX8spfjvtpaJ0f74dFza9p\r\nmmxzGDl0PQ2H28FYHBQ74Gq/BvpkagioKFCsSjV7iGsZtZrtqHIgpUIsIMis\r\nsVojVdzr+EJgPl5+xtxW9ZUvP3VY6X3rjVi/CFd4STQT1FXVUqEcP0SySLyr\r\n74i5CBLRAnVvFjtOYVNmMfGim5Y9WnxLW2QRpAAeX8vBbr9F4ZAovh9mJjrg\r\nTq7eoRNhK5uWGv3kwOULKoTCZZC2Wo+R2WpXqKIIz7LK6f5XPbUDU5rFAcV+\r\n0dYS5Q3qo+Jcdy1zhjikIm4d9fPZgBH7M5hdgqsZhyVlq+PCSI342NthysLG\r\nvn8TdKaXy+7/Tm4/W4J22UEwRJHOBKnr6rA5sjTT39ObkvOPfdvxLhztXXAm\r\nf8MFqKgj9UT50XM1qzXUQMsraMUPhrdTRxQ=\r\n=FtKj\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.19_1680623343191_0.034778955088282215"},"_hasShrinkwrap":false},"0.0.20":{"name":"remix-easy-mode","version":"0.0.20","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error ha","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","superjson":"^1","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","superjson","libary","framework"],"gitHead":"eac75f90f4f1e5d483c839387edba5e2f1122f53","_id":"remix-easy-mode@0.0.20","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-8yUUgSo9FBHBbBaH+mpM8v8cxeOgcLTSckjjZGaTsETZntRMzBQii6Jlk+hU/lL+H0Dx+cTXjLsTaSDATzMikw==","shasum":"b6c5f0a22812a643bc25bbe7da5b7ab52c8ddf8b","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.20.tgz","fileCount":6,"unpackedSize":41766,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCSl3GOhm86pGj9XsbJC3zWoY1V6ykcW8dRSnHJqEPtiAIgb1U+uERHcjuLxl4KVLnXJT9p2G4yvdpvyGJYMGlAzGM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLFQMACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp8RQ/9H180yp0evQQ3JOtH3xge1dWu3DJak+aUE820DK5DDfB+AFgE\r\nyOOxGTTthA3c7voNdYl1aZwp+KyR64XrdLEAhr5xU3vFrniPcoKkKKBjoKB2\r\n3UYZuoX3JmXTQC5LMtS6ZA65tMwC1ykOCZKs0agIhodrHd79WwbKlOlk3Bfo\r\nE3PAZgTod6XS2T8GOnEEE1UDCmqr4M+G4/KnuLEWhMiOnNuOvPGMxg2BuhvI\r\nxCfb5fC4GdnMnaKw2dNXU2Fiec+9xUWwpoaVFFYxV6C79ejLCSIzHmYAg0oa\r\nYS0Ts0I62vLASAIB2hIT/OB8oMfccUYy3nXlrVRhSYCfXOAglaoRfmHSPWti\r\nDXhK6S1e150GJI9kELTGmOXiK6Lw9aaXKXDv4WQEssWXmJAj/ivRADQJki+u\r\ns8iP1R7FpvoUh4eh9EwkB+Tvy+9TbAsM7X5tm3KIMvQqJ3AdjVV6r3mt3Xa3\r\nBy//4plbk0wOojZsGU3h+hSb47u8yQDXlE7TKFrN07iAkkBB/ZgdJtkAAQiJ\r\n4f5W4cGNd6eW8n7EMEuJGXNgcPPfPx9BJwrInjM8BKzhEOBuRbMgHCNCHiOC\r\nRE7OtP5dOxLV76Y7BnPh7ImOO4sJ5c9oQuuMEt+oD0kRul6IIV/uRu6Z5y9z\r\nTT1FCBTPw/onnKIZJcEBIGS18OCvHWVzbcg=\r\n=vOe/\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.20_1680626700419_0.42913619874889775"},"_hasShrinkwrap":false},"0.0.21-beta.0":{"name":"remix-easy-mode","version":"0.0.21-beta.0","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error ha","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","superjson","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson. Inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod superjson\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelperUnstyled } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelperUnstyled\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-TPH47uZI3tZ369e5sgDgFqr/ke7/N3y/oh7meuh/0asxN6b11/PGWJX4yXt1VXj+/oqsDe1pWcvytBTiVMO1PA==","shasum":"70b08c87330892f357973a71f7a6f95d283e02c5","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.0.tgz","fileCount":6,"unpackedSize":43578,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbpy8jle1fcD5E60787zXxjSTd1mt17+Kn5Rf7dXhR/QIgUmo7pJjyzfppIWc4AWycbFzMec+TNEaE5SuRbqXc/bs="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLhuBACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoiRxAAigt0dtgqkwH8OQhX97VGrHrRLLm7E5kS1adBeMBLsP1PqQbc\r\nBJ+cMcz2COyWJ2hPzMiPoE2+VeUGs2BVitOU2qMyeuuKwNzXP3Z5FRIzfRT0\r\nFzuoT66gnZiAl4IfXCSn40KCjcvEVpfq2nudZyOJJn9mQAiCgaMSZFNqhhLv\r\nvN8j8cRWLt6cS9PD/N7GZsZXL/CZz18jHcxQkWwgfCSstDF7Au15GyIOpvBX\r\nw4TMKHQAoCj0eceQKcWkuzTVafPhRsyo8MwE8AQHz8XzbX2kkEnZJJcOu+H3\r\nDXFfJDoQoh+14YugemgkicbxtQ4X7kF376Vgr7a48eQOkjJxyf2TWYUp3335\r\n0suSCsyxuyXx3nvlD1mccJLLWEwy0wjxP10ER2/M+CBzR3IFqjv77dWjfaTX\r\nI55OC0P6Vp7LB09AKjOaSYYBhyTCGDUVquMZhyHLaF2BkOtKqWmMbgONf3EV\r\nXtiVZHe/nLmiujdehMQ4XBz5PTedtDukM/U+1wKYNyRj0yJ+5s/3P57usalr\r\nfURxJ/CVKRQ4EvHCkxW+SxrRyxBfwGEGtwnfO0Hm/tMvz7BKSM6EyA6UfieY\r\nQ9nqFL7wdSpLRDUjnLCKswIV54LtwtDjQ/vZGMCD3KNPAxryk5Qq6ADOgxuD\r\njdSaFXr53Xkjo8Dp06OERq9kZAvk1KokMdo=\r\n=Z6Wg\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.0_1680743297128_0.09308858156515853"},"_hasShrinkwrap":false},"0.0.21-beta.1":{"name":"remix-easy-mode","version":"0.0.21-beta.1","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error ha","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","superjson","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson. Inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod superjson\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelperUnstyled } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelperUnstyled\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.1","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-XYQvceahgDeoy4iSxczyGABStX6MVa0BRlNlTpBxCBIDq+B9/kTqhOzafHBLNrROrlixKO/dkWINx0hHrsQtow==","shasum":"553715640b467ce169b4dd7198211d4d86c0282d","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.1.tgz","fileCount":6,"unpackedSize":43367,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCtw5vchY00YvUkgQbXJp9JJZTpGVzYixrtYfoNZF0+vgIhALf7EX2f6nPasj50XvKYxerk35x4uC3yuXHzqgDSMwkc"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLi9yACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqudxAAk0k9seUD56EC1Wst3Q8cbybzkANVJoZQEbIXO/0AhJqaJjhi\r\noZ56piYVx/oK9bDK/Y5asvlOyvlrV8zBYOeeQWrLd3KmtNUlVhZ0x5wvINFr\r\n69fh+1W7RN3AeRLlimSZznrbrhFGHmaeC3Odjd7TRqnlwWcOsqFt/Nj+Um5r\r\nar2oVJRZBMBNS5iCro/yIdLW11cZvGvy68ngbGckxx8U+79+RylLsKtTEkfS\r\nZu61JpWKPgn2HHCdp3yuY3zT4wOiV3olTiRy0h7/+JDGfNebF+8AaMvKPjlE\r\n/1qDmEjaDP+IhT45y+PpOcKhelgglBqfMjf/Stktq00FkaifCqh2NtE/Zi8m\r\nxFejY/UAOKNZzKooWADaKRK0L+JM7DUb9pdcB49XHrwk7w+JYIlL6k2Xd5RA\r\nET8bzGjlpf76ny2HhsGqCK+4uXAcGlUjoG3pXnN1iKqEM6Oc/FVtGVKFWc10\r\n8wwJqkyt0HRTLeKiM8NpMCGVu/uWPIrNdEEg5FnHd4o+kcXAMzm78miBTbJG\r\n27bSvItjMtKAlxQ1E7grt6B6uu2bis1BSm+jvO7dqgjUsTBuIXPD/eqrdQ4q\r\nI7GWEpZI9Aqh1RnNQ2Hh5Pfw1fsJcWqjZ3x5cmHYgtPUtJvyVYOrQGdI9crb\r\nKJwc2aHtnJLVdBKNuGO8X8pxGi4BX+6Qg4E=\r\n=Wz28\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.1_1680748402744_0.3184913750384877"},"_hasShrinkwrap":false},"0.0.21-beta.2":{"name":"remix-easy-mode","version":"0.0.21-beta.2","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"tsup-devalue":"workspace:*"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.2","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-/ag2KGFtqMJnN3J1KclPQL7EHRiP9S1eb+UjcqDJ3vpjs8r2aTtJGUaeCR+ABB4SkjP4DNKG6eh9nWNwfhShbA==","shasum":"8cf02ada58b3c576cf2e814fe1d18f4ec5415d52","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.2.tgz","fileCount":6,"unpackedSize":44877,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIApCUH+g0LKHvWEdldY2wAMiWxbQaDpB0nA5n94ZTMKUAiEAwblum1RisszsRsPHaJpa2PmYf1JMbRPX7va2JJcg+jA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLkCCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoGxw//Yg8RBgwZUc0HbQTwA/NP84cRnQ+ZOSRZagdLag4R7aewV497\r\nkQmOPszXXyI57ESfkJkohd7K47PTTD7Z12sg7Kx4iBdDouN8ECVK2Yw/dIHl\r\nliW2J2LOsT1M6T6N8yASBaB5/GPZ4WFcGOr+wAyntFrkJmsPI2ZNbLWgEuLV\r\nr92nxQqxRZ5y/AwTc46541/ua6FJ+yRrMn9aWf37ExmYes1HTC0xKT44wO/l\r\n22t0FO/uO0c0NvgVz4XKNLWuSIc7KGef+/E7+6F5iDTiLHoDtktANiTuTR64\r\n4fj2IQ3A1saZOvfHghOVijp2V4jZ8Hve0w5NpqMOR6s6nZ+dIwdJWF0w0e33\r\nOWrYzI61fQC0/AOxIeH4rt+cJFSRh0UwDCMfLo3uCa6PNXKxJxvKkOVoMyT3\r\nWxqEsrOsP02R0G0lK+SvmDnP4sxz6wNU1JmnErUiQT1Nwj9RgqJQs2reIIF/\r\nHcmYJpfuuPyVEK87/s+oPu5iG3wf05NZbYeulqmevv6UK2qcxXOWxuDpr8jX\r\n7jM54uRtoHxu6qB6RfLZ0mgtFmqH7POJ0cOMt3AFfMUNHD/tKSrv5bHLBeos\r\no9/Ed01rh0vXEzncm/9ovbUMbQG+yGJs9Q9X148TToxvmn49RW1rlxv2gZyR\r\nylhoK6MTgEXeUkujcUjGrXpSXgEF0daGr5o=\r\n=YB5E\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.2_1680752770431_0.8257540632357261"},"_hasShrinkwrap":false},"0.0.21-beta.3":{"name":"remix-easy-mode","version":"0.0.21-beta.3","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.3","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-jrNfEx+XX0xPN81HgVcL9vWFPzd3MajlLBoNeySH5p+8zOUoT60DHqOx0eG+N5saxaXe4CdmbM14d14DH5Kh/Q==","shasum":"0d0b9458a83401bbf4141e7dbfe2d6fb84c518b8","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.3.tgz","fileCount":6,"unpackedSize":88934,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFe6gtKAFrH2I1hatmWeWZXMEJNmrXkg9VGX1579SqEpAiEAjoiV0Q9tyu9l3bf4nG1eq/YIY6MvpF/BuBQUmlzOimk="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLkIOACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrBiA//TIPkwdUul/poFVfSSMa8AVCpf4dI/JFXZ7ElbzBn/MHgz9xA\r\nPjes0WY8CxbuoZJjihW3uvLK9Vyff/O4yyRy7dzwIFSu1/nBYwk9RIWhagpy\r\nRzOze8QmaQ7ywDvfHRbQBogcRf6iYUs7tS4/YsqsiCrs2GrTdTVx9Pt/FLNY\r\nIMtFlISVvNmJB6qC/yZ2/ZoVL6NXxxqaN0CFLa56IX1p3ARlnwga3+PNozb3\r\nn6MIvvVJctAyF8ipnlyAKeQFKgeEutHYTUskIcb9qWItGZmYKVScl0G5Z5Sm\r\nDnvXVx0Zy2NIrQjHsBrp3d9dMZxmDkx0pwMa/HkzIL2wFxHZx8AT17WVK2QQ\r\nn+BBPSLHI26tYPwfKCIkTp/s5AbObpg77uE2DnE4lVH87NakKpULaCednux6\r\npVx5HCn7mr2Fwge0jgTnQATcZnRfVzAZwtl0EnLaiX9bvpp8PaZRFlgLj2ly\r\nXtyrZsc3KCmVnkXfztVm8DTNrg+eAY66t8ueHBhRl3ua4XpS9fACEbm6aOo1\r\n9VId85DrqA2ch7dGdg24iq3iUMrltvr2cdC2wwamX7uwN9m9cm1lak9SGADT\r\nRG55w7rfWQ3TZxFKg1MG9NWjTSMVoYR0AcBiJIzAehndv3an5jzQE5mMUeux\r\nYl5G1oz6WDWn1OW6SBeBE07a9wHmAOBVFek=\r\n=5EAz\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.3_1680753165823_0.8813199307900115"},"_hasShrinkwrap":false},"0.0.21-beta.4":{"name":"remix-easy-mode","version":"0.0.21-beta.4","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1.12.2","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.4","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-hbWUjjShHdfNJGx+Shjghz0RWSTE33diwRmW8MwK+Ca+mpKa4ttDtXoGtSJUirU/+qP0rTFWHTu3GCDc6bradA==","shasum":"71c25061f750a928ee81f728e2433f8002f72382","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.4.tgz","fileCount":6,"unpackedSize":44814,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCfhkuYEGrLePu2yV27YsqTXWfLpw039gvQ9eSe3bvqVAIgT3f/o/ZknJ0jmkbznifq+4KrToB2c8u+7w5ADCHCt7c="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLkSIACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqHlw//chPSO8nRx6YpNKSgSjGgR2KVWwdqq7Ul793BR5KlR34q5Eb6\r\nazDWA0on89XVDfqnZPM8hZ5KRp8ChJtU5m5AmWLzOF4KBgrcyp86mF5nIiCz\r\nXXyYUegKHhMT++7X8FEXmJ2ZP9LD+yib+bgY566T6EinQosF/tEZA8oJ3a5B\r\niHLB+fOvnUdvCSxoerTMr+gI6xSiV5VaOaqFjN7SYfukGKIrTVcvBki0f0QK\r\n1gxOF3S3XN5wgt+gTXN/k3+PWS8cbweF6POdmEd12xbpwWON+VkWKeE2psvI\r\n0VCJb0Z4QKIRDV3Mtie6QWRV4Qtf/N8f1aH3heYyDv8KiP8UGCHR+3wf81Cu\r\nblmIQZpaLehPdfmPLjeLWSo63Z8jMJ3EmO27dgzY2sLu6LBQF99BsRLMZ5dp\r\nSETd5v3f62p29Q9l/v+3YKUokyOmcgumHAIHOq7VnNoiLx7ElwQkH5IPorp0\r\nWopVJpwdSwGLpk6RVEDDa4F8JXoQBOoPqEl7yOKb+Urprl+sVRnEurS6wZ1P\r\nKa/mW0WAxDxqrKar/u8dQqhAUV2ZooJTJzzaavhT2x9W078hHstcaNMZaQkQ\r\n4TnLtZPGjKbLi4/ilgRK+NeAeGcXFuQfnT8K2aulVhOa3F8UbMwhKS22zv5w\r\nQ1E35iqkJgUOByPl/sIPA1KWn26wgBxqGR4=\r\n=115C\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.4_1680753800471_0.1299357816107456"},"_hasShrinkwrap":false},"0.0.21-beta.5":{"name":"remix-easy-mode","version":"0.0.21-beta.5","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1.12.2","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.5","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-5MCvn8CuSF7OPG4MwgRgjWNM/H5oHhz1V7ywaptJuHQOKwq9dxvUo8ixkpQaAvrKsNd67YumjJZfuFodicaVGw==","shasum":"5fc884cb3b6681634572827a785d72b9668828b3","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.5.tgz","fileCount":6,"unpackedSize":45313,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC1j1p0YA8FSisKsrdDnOR4CSa2A3yyiAXHgCEowbeh9gIhANPP8Oa0KetwxTSNSoLWLr2jo6GNWW4RKyBsnJCsPU1/"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLk4dACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq6Kg//R/GxlSQzYMrCkPejDlAAyqhMQtgCWKxN/sw1VC7cU+NrjBda\r\nq36dhJ9UmgtRQQwaxGXaS/YtHmojzVO1hyfEM16fo9c91ZfZ8SCs1+MDqKKY\r\nlNIfG0yn1wv/69+GlRPxWVd+OvzCOTOULBNuUkb3RonQC1VQfUIqCu9UyIB/\r\nY9PojWAnmRUOI1sUCuSiTyf1lHDJiRteEIirGugi2n4Q1B4eM1gXsUS+eIxg\r\ny5f+BWhuEkCZrkXj+Jk5uXXNJjBHQaoEIuhWYQlFzyq/2ztE4CEY1QvRU8kW\r\nflEZ/CNjps7ro2aCjJRgXU/OLG7tLr1LQbRRyXJDwRY1lbdDlCJfo08pZ5XP\r\ngbyYPYex5hEjo6qBo4EHPVWTjCzNKMZsSiOTQb8qmaCVdsichSnPe0n1l8/k\r\nkCROzGoWOk61aUGiJIKOsSSlFJ3CEkipeA9LpVI7E7UCL/59PgSltdrREUuP\r\nXHbNrpTe66yVWO3OjhvcoKuck/ZrxjxOWehxOebyVb0wgIoDAENhr1k7i4Lr\r\n/BR35vRRkzQgPX5BBKm8aXUX6heab26EtIaBFvvzlIgIXDiYjRF1kUzpMgMw\r\nA4ee2oA9f2up7aEVmY9TflZ1C6Hwj696AwlP/QKXyIMiInsZ/1hO7jYpv9uD\r\nXusy+EEZh47x6C2BSvgbwnp2bsN4Q6Te+EM=\r\n=C6nY\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.5_1680756253553_0.2908527629622093"},"_hasShrinkwrap":false},"0.0.21-beta.6":{"name":"remix-easy-mode","version":"0.0.21-beta.6","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1.12.2","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.6","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-EWeDDtD4ZF1VB8YCkc/wDZS7R5oRLW8n8Fmv2Fih2ou24O6bV+iSTSi0Mfh/APDMB22n8LSox/mznHg7hdL9Uw==","shasum":"b99c7ce1d37110a77bca77d82aa43a77ceed574f","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.6.tgz","fileCount":6,"unpackedSize":45363,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDoldPuKUSXeoVWtC0gOB1JldxUM251aMu34z+WR67x/AiEAtH0H8WgDnqF2cHnK1r+z4ywMkmzsXrfWRJHKrVvWY9o="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLlCtACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqVwg//dyyicYfscVlR7FdTCtISoN83geB8RaoYkzpU92Q6k7QgPuAp\r\nBAcnC6kn5+5/Tc+W9w7U8av8g0NnbpYfjMJk1BIZioGtzXeZrNC6jX7g1cPx\r\nt/rjb2cJcQZitZ7ipVTTWc73ImEnkprRFpWebd9In2jpGxfVs2miC3lt/JgK\r\nVv7AqjP76AWbZoMDvd+vMtWoFsoyHTXX34bRIYXpcongN31xjtLYN9J/80RO\r\np0ZoUQ0Y4d4jFQvSJEgnO3L4XrPhO51q7dDZ0xUdzsvqzAZAz0WHyFsrH0Sx\r\nzVNe2ijh2AhjwQXE+9FY5Gnd7xeA6Yc9Z4O03E2rR30X+q9+eg7/lyKLr6BA\r\nElHrcS3MJjs+xpTPrnb8UBKP9hZZhqH2B0re95L8znmGxPOZItb6bfnjhMxY\r\npPLpzE5/DN6qGAc43AAm2kCKUZ+8xL1DPpgws7dqNjVgEfg35XelVcdTJVgx\r\n1Nlb11VtyHu+aDYv9Xtd5VwxUTq7bPyj+CpI0ICAOtMXmNDjgbiRD4QVJWJN\r\nHEdA5m+yCJP8Naov0ilNbbqsR59yuzJZNykH+UeD/FaZ/sEOhkre+E9Ez/JO\r\nuqSmg5uL68TvRvKrAow2wUkNzwoai+CA0sM3qYYGwxjRMW1kGfgj6KNI93t3\r\nBbZvtCqEuUrZ0uu2RBpzxLWq4+paReVdL18=\r\n=ejtc\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.6_1680756909255_0.8004546290940058"},"_hasShrinkwrap":false},"0.0.21-beta.7":{"name":"remix-easy-mode","version":"0.0.21-beta.7","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1.12.2","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.7","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-lcuVlj5ubD2WXaUvK9xFw5mHq3RE7KejiNJVtvLQTk3i51GV32BN+F8+g9cz08soSUiqaPvYCx3QUiiDStV4jw==","shasum":"90ceee905590ecbf64ae2d8599c392e413a95b4c","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.7.tgz","fileCount":6,"unpackedSize":45363,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTnre5HK94pedcctzIbRxeNywMVJNN2OqzuR+1RAv9agIgfwOWO9Bmicgcq9c0REkcNnRWhjowFFoIAI8T+y2/0T8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLlS5ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrDag/+JKbMqSPtUE2m4/Zl0qB3tCUXjnthy7Outb7O4QiU1nD0lhi0\r\n7CSMQ80dgWbFLUhS7yrfF2qC1F+eFf1tYFpkmktG0MRN3zt1sCcHxtmvhOYq\r\n3lmfwqXmr8/MqpLvOiVkxtD0xvPKBuXr1szdOeYlGSFYkFxwTPqToaFc1Zb0\r\ndPuucNGmiXp+ndNQXytrBFuOGz9ioCopir5HGdTzH/ViLSu3xia3gkyeyMxh\r\nWkLtiTvvV5onM4DrnP3pKtoW2gkwvTpSgMl0IkbVW/qKQ1QRb9ulaNqdoVdV\r\nntWwbZhIe2Pr5vePwuFvmNIqyVlYuJzYIln1fa27c4wVAzbnU5sQxRrVtSEh\r\nc2pCf20uAbzy9uAz++ddPXw0ZqnHycgT7QsTrWUt5vXtAcQoMM7Cn+YlvgQO\r\ntIIuKstFKyboAkBxjxcG2+KW5P3puYtpS2Lp/XD4IxPIShnll5XrJwamcj6i\r\nOBeBMmbA+W7OhHt5g+Y3qf3TL8yK9XND2Ujf+GlICSzFoEVflSifd3OcOoqj\r\nqNhC5YgfIFyn067HJFe20th74fn1C7EQGEwmB9Q8fTykEYo5veBGQeBiSqAe\r\neWOGAQsDLlYArdLQ4BDDFGfzovUWebCTeqz4BgYhwsaB7jks88+UgbAPqKto\r\nmdLrLQ0Rz16At0Q/HT5izvebIpAhQZ8fKZ8=\r\n=s+Ox\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.7_1680757945662_0.9991305223146276"},"_hasShrinkwrap":false},"0.0.21-beta.8":{"name":"remix-easy-mode","version":"0.0.21-beta.8","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1.12.2","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.8","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-sBxhxuqLl8tMLChcVh9sOu1EIABW0zo0x71SVMRNUBEpY3lLsB5GLnLGNL6sY8XzTxgEhJpD67GCfJiv1cpyag==","shasum":"57ad084ab1b6a608b927cfd0936d10ebbf3b295e","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.8.tgz","fileCount":6,"unpackedSize":45363,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDg2BwhAy1942ct/IKz5D8mnaRBbUB8UY+GUykeBV7soQIhAKmgoVus57yXu/dMJMqiw5JaPWVBpmw0VetMZoiz9QYX"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLldRACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqlFg//eY2uEmxl/3Gu2adT8EpC+HLMBrAhdtol/ZMu/iEs5ReQZ/+P\r\nDcvZpCmK1f0INVmKaNuGuuEiVIpLYB8Awhj+e0OgkXFzGzBhmnqYYIjhHU+L\r\nBI56u/qiknSGr2qcerSKQtI2t5Rqcdtqe+ICwC21cOMDKk36zsrd4A9SsQ4m\r\n4xM9yZm6vxMb/PGWta1O4v4leiIZJwRPAzq9kUQrp7T4H0/KFh+IdAOsOu7C\r\nS0kYXkwzGvwt+rEb7AdfEcq3vsZtHFsYULTbJrmp3gNGY2TeRf81U6ZGpo49\r\n3VDvhuwzziLVkqynfrT+eVwuuoUyWFh1h2zbFBFSru1DCXSf+waMi0jMqqTm\r\nz9DXalGQXgByzgmGD3P3EVvoltPjzQPjpsLrjO/wgsfnCThKdsWcuP3JYw3R\r\nzuYseIZR44GikuPMe5v/bQCAoijdWL9+Tj1/iXIq9+YPM1x9ZH+f5DGkMKGs\r\nrolmUyDYBUkRDrGskasw0A34oPBdgNxL8cqQkI73IovU+FGkJrwNnZBlhssZ\r\n/u68atZTCdb/bBKl0rgdYPdfL+aqrI/qBcq3UqLogc3tbPPikoDRaZpocE9Z\r\nYHk2qU5VpQxD2XL7wJhCcLHmBcdfi+05sLL+JoubA9kotWnjVvJyGGyYOVPX\r\nhPkxkSSjtX+5dX8yjk9qeRrytoW64UH+hZ0=\r\n=clpN\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.8_1680758609259_0.3175091854166663"},"_hasShrinkwrap":false},"0.0.21-beta.9":{"name":"remix-easy-mode","version":"0.0.21-beta.9","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1.12.2","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.9","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-V+l/LzBGSJ4vxRfWUoCxBiZhn4C6MJrqNH6euF9xot29ujEQ/FMsgVvcaVa6BhYjruIqUq1+bw23iV5q9xjEAQ==","shasum":"13c4d57afd6c897b569b426fe2acef68290c9057","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.9.tgz","fileCount":6,"unpackedSize":45726,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCuTaRopAfKp2RE3E2uYyxzCTYXYpPlzS3xPS7BtrK4kQIhANyJcB9LCSVq7++4h+Bcq2laJCFxB3iIBI+KpJAdiqGI"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLlhpACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqs/Q//Wkue3umPY/2AtkOYCWTbvHKe8oG5QM+3zVu/IFHJlTJ0mdSz\r\n8ISa+PHJcOM2vgWAYUu4L4OC9M1hgO2EdxAoQsP4i0X4x0AKC0v5gQM2cYur\r\nYsbmpLa5jnkJDbYfF2vsy3H7hMV0Dpl/+mbwPjynkaMDYLOGePGo8c8avW04\r\nDsJ0kfW0rdoY9cK0LLTOuQZm5cEzsVqntd8JkjyZdMbygrTc2+4GXyOwfzX/\r\nfFsk6E9o6ylyAGHS+DfoN+I5mQjitohhj3GO8QJcasHiHEfPe5JhMzOsp78L\r\nC6bdRAo5a19yDExIKJ3hDpySPLTLKy2atk9TRHBd+mKFdNLwLhZK3P1K8TGM\r\nQOz04qXUd/BW2KQFbaRcvPvvGd56RQ8hWZ5yKaD2Pi5TP6IIz4ycdSmhY3wC\r\nMs2bESSeMz/5SLZYU2Gv0OhPVcscjaORN2vGUldoufaBNxYIxXiE1JOnDSgc\r\nO4g4CnkjeyNYFHP+y3H3cNqNXEs01vABV90TPRS6N5falYY0Cw5d972wh8v3\r\nKeaUO5VWhpc7vP8kDYsKmVP/Y2vd8Ses3tv1p4N53lYdWomD0fLGAEs2DTdq\r\n73xdVngoxkqrm7+wRVvMUvWc43bD7OetQd+CiZZO8CjMgPxlIxKnaWXZR9l/\r\nW4v0lNRxECpcGzjmD9KIvTs17W3dmYLLeLQ=\r\n=1DsQ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.9_1680758888860_0.09015736835602572"},"_hasShrinkwrap":false},"0.0.21-beta.10":{"name":"remix-easy-mode","version":"0.0.21-beta.10","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1.12.2","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, fetcher } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      {fetcher.data?.success ? <div>{fetcher.data.result}</div> : null}\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\ncd packages/example\nnpm i\nnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n","readmeFilename":"README.md","gitHead":"bd51c9853271b227a91b331a24ae3403748d4f5d","_id":"remix-easy-mode@0.0.21-beta.10","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-iFz4fpetI7BNo4fCmprUm/cqjuvD3G2O7mYmqS9Y4SnsAtv++2GEhdVjxe2S/tR4XVEgMG/bT1ew3Nj2THk5iQ==","shasum":"ba195952b4a8fb1f231bd62b4ef6386f8f32fe9e","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.10.tgz","fileCount":6,"unpackedSize":45107,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDjM45uItePiijGykvhtURfIoOnBXLbOUPJNDSX7l2T9wIgPLYaMxz+JU8LnO1aUa+DXD/Xmu38NsKuDelQzzIX0Z8="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLlm0ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrnAA//TfwmL/y+WNva730eYYuQBdmE/qMlgxTixTKyEAXazl2cqGIp\r\nslneJouxkEACtezvQenoNZakpfvNB16hWRrbuXcksfx/HEF5XrA2A+2eNxhz\r\niq/mPjE6ZdnE7eLZsFS7CZwXAaPWxCORbYDLxsjOWAXti5nGDhxlJJTbyRyh\r\n+s9+8M2SBTqKw5/b+a0IuVXL+7B4uVXfluxLQxy0ivv6oUM9J9XCMf4RHmGv\r\nVzQM+tuzi/XP4IHWrMXmW6yEm1w2ZnGcI25ZlEPY2lC/hjlgVvS+TFPTRNUW\r\nTxvkVjYQJaS4FIieTA9k32okZ/XVEZUnippA5zrRigu6N1FSnZDC1G+9bQta\r\nR5B4Af60/l1ueqC6dcNLmGfIzA/TODE5f32Y/MAvxUWLLwMtklFoKQEP6+9b\r\nC4I8pkbScTXsjJVWOJfSZnT18Kgy+Hh89DbkAFVVxuxMWTvcqgDngkA5gdt8\r\nDAnrzJhUooRt/DFcJUAFBj/NVYxDp0PHe6FU7+nvrK1xHc/dqossiufC8RRH\r\njfRdWSNYFfIxgfKJDUObvfgwyO788ZrhDBXBJILf8A2AlkJc9oSB073SFUME\r\nloNvsi//5Qprd3gtPkmNk1TFwI5fjDsnFBXxjwUyqaMNaby/zAe1un1GxK7Q\r\nMopIZpFcbdHAL0gsBUIuDg3wPyIjKqldBEk=\r\n=ShBV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.10_1680759220262_0.10853286614210256"},"_hasShrinkwrap":false},"0.0.21-beta.11":{"name":"remix-easy-mode","version":"0.0.21-beta.11","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error ha","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","superjson","libary","framework"],"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson. Inspired by the TRPC / React Query DX.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod superjson\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // return session or throw error\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input, csrf_token: \"\" })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This library is admittedly super simple and super opinionated. It may evolve to be more flexible over time – we shall see.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"3761048f8a2bd514ee0d45189c87e78d2b319764","_id":"remix-easy-mode@0.0.21-beta.11","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Bv7XYg3wdqg4ct/6FBWfycQXahFtZ1sryrtizJqSYXmW58KgsV+VQwKb/8kpFaIWMf9S0zIfXTDdglM5muAQAQ==","shasum":"05998e9aec2a74c19b6dc1bcb46adb871e440c50","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.11.tgz","fileCount":6,"unpackedSize":44870,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDyOLnT0L3/cvzGJU3E9OxrC45bw7Xn3N76WbjNTPJn4wIgBSaq0sKd8IJyu7PUSCSlzCfVTZars/iWCoFfNkygeaw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkLmrcACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpYlhAAi3CXPcrJ2tTGEPa86fEjRQOU/3OMDJQqcHGvToLw6U4+CwG2\r\nX5MMcqD+gVr6lmAfAmRBx1q9aaaeS0uxnw1cvsBQej3L7gniu3+mizADxsSd\r\nAyICbfiw1sARwBVimHajggEeZQe1gzJej07flGzeWX8E3atokGIljoLauwHH\r\n3ZNbE5uaHJy/xIUnkOfDNoHau14SLli7v6ZP0831OjpdPqqi1g+gmu/7FPPF\r\nDIlKlmaLUOdlUXZBF3lFEkf5zJqmgvjDS140OK6Q+sX0unboskU/S6RI7EjP\r\nWH2yjvS9HVMY75agZv7y/GKF7Tz+NrcjLZxLCeKzzevaHBJxIrzu395KJVJt\r\nVm5pwyfFNYDMtszKpZMm0o0kmHLfM+eskFstlKW+lYys1OS2ypeyxSnEWBsX\r\nk9dXBMwWT66gUPrkCRe9mbwxaH8h1IRp50/zrNvl77myBxo7rig65ll2mxIl\r\nbGsSfnv+50EYXKgj9Z/fDFS+/hffeVK2fSMwwvPB5vjs1JNyESq8u/0LZnx7\r\nxOC4XYwev+HugrTQ9+6CViV4l/+kQfhcW4RvfY+OvdpLAYPMDfvGVY99/FHB\r\nsWZnIg85xi8nbErqWiaQaneVjrYs6c6kfbU55170UhuUwh25OrrqloIZ06z7\r\n3tIfhnOtnDI+VT5x60pIiQv1SpkmGYLsCxY=\r\n=TgAK\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.11_1680763612064_0.23257790859042227"},"_hasShrinkwrap":false},"0.0.21-beta.12":{"name":"remix-easy-mode","version":"0.0.21-beta.12","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built on top of zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling an","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","serialized json","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod. Inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations). Uses @kiliman's remix-typedjson under the hood as a superjson replacement.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.12","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-ywdZ5whj7fCN06bwKqRS+gVtM23/pXvflF6bBpSbu1A/tnGAKB/dYh8Zw8NW9LB4QnF/xf9e4VAiX/yCzq5rmg==","shasum":"1d94422b51d8a555d508783106b50a0a5342efdd","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.12.tgz","fileCount":6,"unpackedSize":46366,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEk/RmEk7sEyIKJVCnVNZAA9BnsJuRHGdCBEJTfMvxivAiAgOnKy60w7Yw8r4DwvMhQBph4Gc4Oso8nBIfkkua9U5g=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL2F3ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp0rhAAlFYykp96muQD9fZ7mVW1WX+zY2TPX0JXATy30vvdhIeCPgJH\r\nlthg6BDpThQvqAc8xgC9TwXgO5JXjGSlkKzp5qC3yTd4ySsx/pfpzESAtNnU\r\nKPLPEb7xMfd4p+w1Uvb4Yl720YqyaALNZOv9vYHSs2C65bMUhalNfNYlyEuW\r\nDIQdNhoEI5qpdrUbkKakPv8NllacPOgep1OmvKRLmFlnn+fzT5RWrS60Ap+8\r\nwyf0BomkH7/EEDfzBAH1KNbSfV4uclZ8a59HcI0z8dkpasHSSOyKYyPJ4dSy\r\nGie3P7MCF3+sAyV+o+0UVU1dngMsrjZM14zD6FnPeTa6A+0Gir8otm3Hx63g\r\nBZTd4VK3kC6F/swnTJ7cDiWHYMJiae8o1IQqY0Iof91n1YSOf0JS/KcNJrQp\r\nlRjvj59HAege6zh7rvOMtJlzzW18+0LL3afVli7TqF8oH9lQkAONbasuSmnt\r\ncE4SVO5OvpGnoyYgbq+xqDNVLWpob3KpGsRY8EN77WjC8KSWN/HhKPiRdcxh\r\nYSTxDSokMejAWxm4Mk0o9YVDuY4sjyo7un5NrS7eIn2RiTcmD7rj5htP7Ue1\r\nC2veRKgw4vkl8Y/NGoALz7C3PEJRNwVsprfPncxpACMs6ajRc0inqw2Sy8UO\r\nHU9V65FkSzst2d07QD5WV+E5w5OSbbFtiMY=\r\n=xMJT\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.12_1680826743399_0.9391297001992422"},"_hasShrinkwrap":false},"0.0.21-beta.13":{"name":"remix-easy-mode","version":"0.0.21-beta.13","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built on top of zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling an","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","serialized json","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod. Inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations). Uses @kiliman's remix-typedjson under the hood as a superjson replacement.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.13","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-o9w+SEgWFbr0yBi4bsiKDHDXSvnhHzDO3Z4Y6bM1SssR3woinCL2UZo3zJBV882pJttru6BP0LX5iFi93JWRrw==","shasum":"b713f53e1b4ed6cfd96742f26f1a25e0a75ef4c7","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.13.tgz","fileCount":6,"unpackedSize":46447,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2tP7rbF/G8MwVnlD+ddMcxIIETGRu9Nh9eS9xQPpSfAIgJMqkL8Xsx1KuMJ2axvgAz4/gBQKd+wMQUkAx71Oae/o="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL2llACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmohDRAAmK3bl40i8+bmwFl8WJPh0xbUj8wtEx6mY42U36oGZLMxS0Xe\r\n1YYU3F9UOcdIhWJtfRDU3IdSovZ8BpZ7Qv/la+H4PnVcMkmva0JnV3S3QIRB\r\nlXj+QuwS0kV025ptvUk0QSt7lIyVDRRRfivXLTugRBfcSkvQWTxjetycuqN7\r\nrJaXsDHKOgNr2OUUV7OmvhaqqN+uKJ+PFqu445mQbkdWEq/berhMiu22FIQt\r\ngFzR/TeYX9I8rySjYgwuXbILr2bLJJJ0yR15+t+T3TN8Ly0Qb4oq6Vt18KwM\r\nlch9gyUtWJimyPEUQFdx4J3C6hXI3Lia1Grq7uxM1vJUTdIsMpcU7oGmfNFq\r\nzHag29HOXyEsul5cHg4xI/RrVZlAtliU7BxqRSemcf6KNmCGBPdPFF/ttDGZ\r\nq9Ib3f6xYQ1oKBwpu07hcUoKGTFyM12v7z1o/V/5nLE2tPXxmXAuFGlHZmkj\r\nZZ1tUycDvmaJwXthy7MVipdz5LjBPllB3v2AR6zprJodmXrrUg+Ox4KiznFQ\r\nz1ezfPnnl15YIrrIo1yQLnyVkga428f3LMXHVGwyeWkzJvYqRulX5phwTbuy\r\nCIilbdyvLBVlD8nXhGhVlMG73EZonOWYX8HfA3x6LCefxavUbCun3HLmgeGZ\r\n3CKd0PhduvVILtvRjfPZPuQf13I3z3+VZ3s=\r\n=4HP5\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.13_1680828773378_0.649930509523547"},"_hasShrinkwrap":false},"0.0.21-beta.14":{"name":"remix-easy-mode","version":"0.0.21-beta.14","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built on top of zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling an","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","serialized json","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod. Inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations). Uses @kiliman's remix-typedjson under the hood as a superjson replacement.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.14","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-rFwEKAWuDC17YpkcGiCRF8BLWZ4Db+bwLwhpVQwqtN84aGwExVd5y8swnYEwk/OzhdNOi456QXwPXm2IJcT6QQ==","shasum":"d2b6f149d819ee5d7db96d4aeb65e4d76e0d21e5","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.14.tgz","fileCount":6,"unpackedSize":46401,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCriTqhnZh13vpNWjZS5me49nDJBpExujnzpoU2CHrFygIhAIwT/UZt38MTT3dS8vzEHLapKeugiuNWEbCFJvGRxv6d"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL6DUACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr7eg/9EkXoga5s8ZMDH/PbolLhrdK8qQP8Jug1p7W3NWUdfSx7+aul\r\nG15MCyI6i4fOzxjGXy3D3B1stlaxBLudQ9evic/jCRsErIjm91R7xL4njNS2\r\np3R/P0SOXPEvdZ8GGg5f6oPQ5SiCIBzCYSSNvUk3zz7HPDI5RS0DWHGfeIrK\r\n0wvuFHSY+cDAntQFUv0iY3q17gxf7Ex7/1Vy8YaEjSWa73coiUhLyYSmxTSd\r\nzwzvjIj0wBL/TIPN1Toj5GomkGdeNyL89WDfRQfvSra5JvRAMXFArFdnQLfK\r\nM3DIlY86Y87jNfPPUoc4l11qmQ4gyVxAZQkH/K2AjzRR8RHpi2Bs7+kVkgyF\r\nePj6Ey+YUr+FSRqkSHfz370YPfwrgGdAbLhp1vAXX0PleYQ0S4Y75sz5F+MC\r\nBKSWIQgZCR2LNOChfTpNGi5n8sW/de1+8wMetWgkiCw3mG8N86NYvOYRsRXy\r\nz6GihwAtl8clVhnCJH/vWqKWOQmpCTerfxlYMiH8t4sbtN71VP7aywBOKwou\r\nW7A8NI535ktPcoZ1EKIV8K1bEuGqQegE0Nm5hfko5H1l0wIQ/XRQV5T48Hh+\r\n2gMIeSPIhc93bgstJvXi16L5BGiqnpB/P76IheJ6BykdoyeqtTpF3IgCARpv\r\n/nMx3vfY519xx4ZKWn1ikR7KtpwuopOZzNE=\r\n=dmOY\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.14_1680842964290_0.8693414839735807"},"_hasShrinkwrap":false},"0.0.21-beta.15":{"name":"remix-easy-mode","version":"0.0.21-beta.15","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built on top of zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling an","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","serialized json","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod. Inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations). Uses @kiliman's remix-typedjson under the hood as a superjson replacement.\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.15","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-6jNjH/CgDxIl8wnc7j+dLDmFjVOfbEOAzf/723vKYOG2M4nwBsEiwjq2Tidn7Y7CrEd4F+3uw+OATJG6LqGz4A==","shasum":"cc87539be8251e1a8350a730910780efb2ad8bf9","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.15.tgz","fileCount":6,"unpackedSize":46426,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDtOV7vnMrTyJvxw08bk0173DwpFeZWECoImO8K7YndkwIhANJHN6/Wz/gcUtZnuCjH5Z68VnYtGQ0TNHYtqXvlwAmM"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL6IqACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrRUg//YaQFqmELQigdgXEaBoIaXOSDTdgH2divt++5gADqiHUO1Hp5\r\nTUtSXvGk6xY0xHfepbb6KyteZihcJ2hvU95TYVOfF0/SpQJM5l8OpzQbmNCo\r\nxqq1zBcdYgDEqbrtbc7rmvuKWDTCrLTbiWBCT2cYEXcjlHABkg2GD3ESuJMm\r\nZj768OemdzPDcPcT+opdQ1AWAc1V2KACbEjsJRl0Kp9AiYREr43tIgIYqzUW\r\nT7KZne2cUbdTGvT3ljYwpze3aTksTU1T8lXUrOuk9aegk6rgMzu3uC0l1dgV\r\nm3KfQanXUf7TSKSH1UweWLwhOCWaDmK79uBX6zKmchTE8n1KppRHdJwztEiU\r\nsPzqdRJa6ib8E068arwryoj5jyhfeH8DFkF1S+UDr60lKu15yJ6rZnu6yLKl\r\nx/9CTxd/456jw7rHImKEKufg5I1lvIaOiiE/GQ01r/GPgMUF71ZiprqJXkxe\r\n4zS7E09LcxAUuG/5a87DsSjNI98ysM1b5V1MsAzvpEOIRLqvCWaKzO5gtkIB\r\nECJtpgeWeQNXg/ysLXRSfnseQEcLVJpg7aYZLnH9p8tZQkIRdaUCV6CUrYfd\r\nizD3h1nqTFKadINMUmD4JdbIjAIzzxnrQFltQ/Np+MfjBMbnFRR5nmD+TJv0\r\n9a3KukhzzCF/rtcGBsGYq3rqg8Zj9Z+C0bs=\r\n=zvib\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.15_1680843306644_0.654186170053267"},"_hasShrinkwrap":false},"0.0.21-beta.16":{"name":"remix-easy-mode","version":"0.0.21-beta.16","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error ha","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","superjson","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson. Inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod superjson\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.16","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-SuExNmu8NIoLJ73e+RPn20GU56jyA2fbrhNBZlZTbUzFI5xJ2Y4IB8nDVWfVQMMoBN23sXiapNqD/hr/DBEPGw==","shasum":"dcd85771f27738beaf6addba0b44f155d081137a","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.16.tgz","fileCount":6,"unpackedSize":46201,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCMIaKGnEd+4h2m4H2T87JfKi27Vyx/9sEXpfHRIa1EdwIhAO24NFfwoF2odHaoUaHz2YBRUbHM9AodCBjhu5I+rqqP"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL6ZgACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqdnw//Z7Zq3R/mDAhUvevzeibZpWT5fx6mrSkqxk67k94HGR20wB5q\r\nlsl4w4bXFlT0eYDzDdkSHbXYENMnb7SDh60F7xv6ONHd1TdvQV4kE+99lKdW\r\np/JDxtgiKEWFeMz2us+hubu1zJp0i3cbIztGVUKg2lXQl9szrHQgD6IputZU\r\n2t5fl4lJ9UVTPhHoi57504vu6/d0/ulGUGypDSdYxKJSAAk9W41OAy/FRA5G\r\noXe0Fa8tPozkA3HA0xXS9ipiiV1g3/Ni/wwR1oSIkm5aYHjwe6S8byFJC084\r\nKHrunxYv2YtjjsuTucasfuBw+cIi3H/oVcVxFgNPtCRoMRh60SQ1uErppwC3\r\ntG8FhGxPhNy3yuwGbeejSXigCDpqysI253ZY+bD4z401B9UleHu2ndBrrWMi\r\n26B9zRDwTWF0nF8JrqezvTIOn10riTWXJlPdfjJi8f3O0kwyI8fBmfY/036M\r\nW8jHbPbUw7DyERAUW5IA0UHFR9fhY6FdMFEe9qnjKYBOxVuuaOqbFBqmjGZj\r\nAMdfXL5xrpRgAs7FS+fWi1iwYtQ/GequndYcMuaO31hh2ijgdv6N4sM55mFx\r\nARkNh1w9OVWcYi8+fapZk6LOiF76t8NUpn4pqzMPpgm1sWm8S0GrG2X7LRRY\r\nVE8igahW5YHQgptI+WhATJXF/9iVsn/nLs8=\r\n=4gHh\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.16_1680844384171_0.004200806056685602"},"_hasShrinkwrap":false},"0.0.21-beta.17":{"name":"remix-easy-mode","version":"0.0.21-beta.17","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error ha","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","superjson","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson. Inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod superjson\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.17","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-9mcOUZOIaWHkCoYre+9e03vc73SR5zpSH/JCpsb7w3Fjj5SwxCDp2Z/iey6Uijjbsm8O8fCYF/VzeFipSVZ7wQ==","shasum":"7950f02cc65e88525279bdcabaa40fad6fcbfeb3","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.17.tgz","fileCount":6,"unpackedSize":46559,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD5r5zqemrjc0ZIZ4Ec8TiyVFbhdP7ssWcmslo6aunb5wIgFPoZgVq3dvO3lLCtVNRiHCpf3Cw1kEug7flMP/68v3c="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL6u0ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo67A//XI/gxIySXITr1KcQVTpPOusJ2z6RRt1sEQBdSSFIqd7tiQJP\r\ne22r8lrQKLBtRtiBVg2fMgt7Ntc3C08+GBWi3puv3SFN+5oKjb9aLMjA7rKS\r\n84KDGEo5M9xzSahXnPhRvNEae6krTgCysQKipcVeV11mS0aeMcvsubPkQPcy\r\nAXPnjmzLJnyIDKh0gzI3xHdRWVJ0xKfGRBpGT8MTtNUBkI4rnsd/0Zu3rt1k\r\nSQQyHIiEjFyM9WENXcVw8PJ55eDDcLKO4U0cUu+lvN3iHdLouXbPZuBMZOiY\r\nG7ko1UCy41u030f7U4D/wlxJFJ7Kjcb8rb4LHXW06Z6UnL1QnoYBM1Cz1I4T\r\nBVJdVTlttObK7uL5lLlJDphFZzcc6z7486Ia0coTKg01tMrcfTRxJF7jgHlD\r\nBlk0Uj07iu1HgsHSI6Usaf5c9htWG2Pp3ZicxM7O1omA0/dVu6I1DgSzyCDD\r\nYxwtKyt042rmjdlmNbKOEjFV1xox1YBmxISz0PJUUG65/JzNwIAezU2t5UBM\r\ngnD1U5XHWDfDZt1yLMbMTDpPmJazL1SgzwP3UtTl1kL37F2nDhHkEEAnee3+\r\nBTt4D3kLMZfoOaPZgozjAU4sR2A8LXf3nxQIJL+EEtaSklqCgeoobbUh8h4D\r\nlNhonbardpebnSGJx1/FXplIjmZ/hS6uVx8=\r\n=9tJ4\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.17_1680845747827_0.7608155376944867"},"_hasShrinkwrap":false},"0.0.21-beta.18":{"name":"remix-easy-mode","version":"0.0.21-beta.18","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error ha","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","superjson":"^1.12.2","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","superjson":"^1","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","superjson","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod and superjson. Inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod superjson\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.18","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-NcCQYItpq4eQQBlJwIhraLXaOm+miy0Z1UhxM7aPwYJW0Ji6bX/9cYjzcxgKKB/Vl2uSFKGCo9x2ZgjJRndxAg==","shasum":"b9665ec8768ff613584b3416ff8f61098dad46c0","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.18.tgz","fileCount":6,"unpackedSize":47008,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD2gzp3wvMxM3tgbuxkMEPRZrDCcJGus60r0c5UN/IlDQIhAJJpWB/nhkZgXtx9xBqoqnEUksVZ0ySc8H7VjHvGfVNR"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL61nACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrFYBAAoHr9asHpJjlxa7DlH9y3GBQ8ZMeaQLoc6RnGZxtB4EZ955iS\r\n1WIsE3GRMwcx7Eu8bIM/zDGuVZ1nEL7WbO7TRHifKdRivzuvKHAzKQ1cMMgt\r\nM1WbEIlZi3SdFWBZ71YMQ9cNz5TWV8e5GfpG6neqHbHJz1uHWDWToA6V695T\r\nwgesLRUD9A6WQL6hjCyRnnmI0gTfrNYa9FZgpLdctRAWpQ979/p7akeO8Am4\r\n3aKpVIiQZZOTPBM//okpbvGPaS5RZgkNbLzvNuXjGM0Py2JL+lTz3CMpAEM2\r\nUCA3frj0wKfAwv5OtdybjypjUFhthLtWq98SWOCysVwQk8MNYCpnZcbuptQL\r\n6277NL1/pz4KsjFs1MjtIq5cIzLfcG0flrUUyNzLshk7R/AHn9at9Q4CBAkV\r\n8v+EiRnkIiAVHhCLSkak/OtOi5RyOxV/dKNTUpGxtX8RAKyKImLSrZs2FQxG\r\nUwTNQTk+VEy7gFgZLlUVzGsoZTcd8vXs1yYofMdO+R+fvlYJfRVRnSK2d28A\r\nAr3mmOczz0oULPKo7c5Pzdm/KKEgegaZe5dn9I4uf17NPabjOhhojeoE0R7t\r\nhueUag/FOSyIXFUggEee0jhJ5/POTvcXaJODFVE8eyylrWzsTNLDwGJy+/w3\r\nn6RlGKp/VDShSY1o3TZSy9qhSK06/AJN3II=\r\n=HwoL\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.18_1680846183655_0.8740975716704114"},"_hasShrinkwrap":false},"0.0.21-beta.19":{"name":"remix-easy-mode","version":"0.0.21-beta.19","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","json serialization","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.19","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-rtlucR/9+KB2mdJhezoN9Gf6J15qLZxUvM6+hV3CD7HeeeinNakTayc+PkkZSUvp/RYW9hQxbC9+Rfa3rZmLIA==","shasum":"a977533e14a87602ea573faa94c9e6924f3ea31c","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.19.tgz","fileCount":6,"unpackedSize":47114,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIARDiXxSh1yu5KuhfH7/piXW6yq0MRHZxbve/aCk4KtwAiEAsBANR07mHFBvKbhy4ALbxyVHgd05OXLvYEQTks//QSw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL69dACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp5Cw/9GsCtL7ImUld70YFl2UfqNw7el8Bs4j9hJZPWoqXznNPSXJyY\r\ne4yWBnC/GYAVYg5PeL1wKYGW2vdtJqMHsDXclozAHk3hpQxq3agfXrjRX9gm\r\nNjXAaFIpJMTkecaA1xee8nPZ9yrYhd43WYaQW2d2s4tcTK9mvfpno25Bc+9p\r\nGdUfdUtkznZqYrTgJx3wPQeTQlZaGKVKs9ig85kOOSNtvtPGzv/CcDKhpTAP\r\nyID4MKB27eDU/Ptfo9R2Ra/BCVcF2g41EowIvhLhRGUT9KXWJJCrGG5FwlGT\r\nTdzt6gyHqDHCXrxhoB2KAzmjHbNpZUgvJhcpU82idx3ZkJgKEpXiMIrBj5Sk\r\nHqKtfxZBqH+iHORv6XP/DGwU0PapyyFwAFWYvBQ1FOJoVf9/3pKnO/6wqt2H\r\n6bFQol2UTyksJ+BfNP0noegVVXtnawAm5WuLtGRq78O2t8n1qT8Eh3XCYD8q\r\n9/Gl32R4El3Xksavp8upTcYa3T+sxWpMHZtipnX9CD+WVSDs6Oy8x7Bgqpum\r\n0+5yLs/l77NWeM3TRJwHOVZrkWWU0byJX6N28gxW49WgZgTRQmXURvVgGHHg\r\nXLRUggDvhwkqkSJD5GCo80nLmDd+a5FNalXYbUAbs0GWehawUKM+6JE/0Z2Z\r\nswPB4z4/3BD4KLc3gc7tw76q4TPa5+mH5/M=\r\n=Peri\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.19_1680846684808_0.5700298715866106"},"_hasShrinkwrap":false},"0.0.21-beta.20":{"name":"remix-easy-mode","version":"0.0.21-beta.20","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","json serialization","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.20","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-spmY8hXWJGp886I8XF0WbzHeMOgdjQkch3BmrCI8FxhbI+TPDm1gaOZ7dhSromhpjYT02uXTImbMXIT6NMNPfg==","shasum":"e7797d010a4b5666b627c194e650ebffddb5e3bb","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.20.tgz","fileCount":6,"unpackedSize":47456,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDubvbym+vMuyOq+iv0YxldfRXb9RS04PqIMnQYE0LmwwIgHiaYk7WCsi/g9CesppicRkUpdQzx9VPClHux6XRZWFc="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL7kpACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp4zQ/+MpuIe9g/l6nySMoSeL+qCkp/1Civmec9F5vU5/xvmvV34ji/\r\nDPuIY1/CxDbu8/w8920HrUwQA1lHbVzdoSjDsFopK0tO+zBX54oplz4F1y7G\r\nev5edv+RNqVQgktVI53ciQ5j//IEeVFOgHVBqr7myS75u9jYFA4mcFq+N34m\r\nxHNTMHdIMUTOU8p2wl2ix9E7uLIrsD77u5k9Eh8RIKfm0/wH5ttssZ2Scnb4\r\niR86MxfPBA5UvdeRu9ffWa0N78bt1Gg1mmrjvjYbOUyluIfAIooERy9hoK2j\r\nCNr0EDXsMEu2OMV51w9E+EIKJoT4MTP9n4832WfibDuxsCaclOTmeCtLags7\r\nxrirYDb0hW4+n3qyTfyalOZuz2A+kvCdATk2pUAjpu3TMNn89Ay0X1JtLjYZ\r\nz9Zd3hVUSl8Mymmt8ZjNPPvjwxoHYHMAajBoH0ytl5SjtKGvqtxMRaFvN+I1\r\nPKSRTLXahuYA7Ka5jRMCGfCf8c8a+uNFwaLFokpFfHSL90Ranf2W++Xw2tR6\r\nWMMY7UnWvSGc28Yi8fpEfTKYzjfCudDrxeDBdsCx7w0PKC60LO4s7Fkrw71z\r\nu3NcG+VvC5jKM94+rx3K2rpwXPmr8TNRA3zcufGMuotzOsqZlJkp5ZzNrhCw\r\nlQ4QPRbOImzjVL4NvoKofrTX7nCXYtGAfB8=\r\n=xTnz\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.20_1680849193743_0.47679525328562544"},"_hasShrinkwrap":false},"0.0.21-beta.21":{"name":"remix-easy-mode","version":"0.0.21-beta.21","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","json serialization","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"308b919ef047de534dd3dbe30f84993e9b244c80","_id":"remix-easy-mode@0.0.21-beta.21","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-lU67VZVBJTeJ1kdk5BZJ9WC5dZykYlsZiJoSFF411L78P4BKeOZgGsaprpnRhjFVhPR4qrMdC+p9I9JilhulIw==","shasum":"37cdfb0c2166225d66a96392c43f9ddca0a7de18","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.21.tgz","fileCount":6,"unpackedSize":44189,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC3MelDeijpzyjjB3xDs+FO6y9xHbz7wCrfTP/QGD5qHwIgDugdwwgPhfAu7ilpdlK6y8LEGCYlV+pUqe+tFSoxalQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL8Q7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp/0w/9GtvKM5P/Awx5+LyAFlnK6sUuD3CQ/PxobcMV4YyvjzZw/zeO\r\niUwHYWTCkJuwCluw3VvCbOH0NlWzqjLmfWqAnLoVf3Ql71MhmlUruRbj2lc7\r\n6HmICSXXPYrGSoRlKqFm6Wbr9rc05R5gujjxmIdlvA05egtf+FEOErVbGsnw\r\nF7S3QyZXsoZUqb/EG8Quyw7F/bRUjx+8HPVfOIdck2O8LxWND9qIXsE2FWay\r\nsu7hC8/AAlA4GduZqd0+Ux25psnfSOjBYe5zNNnqFcjROc8keJK/Rwd4D8Kp\r\ntQalXs7zYpsfyqczoihuM72VVJfUQ74k/cM6pFzxTDS4VdNLMHBe1dZQu/l0\r\n5P/515NwJ0qWaYV9OVHhfELe314XoUwCqHryQeglrRk+h+G9F0c6luaiyGY9\r\n2k3TL/qAmWzqLm1YhJG/LHNPG2LKS6Kk0VXvXTq8ZWd2qiYtHYCVLfa+KOZj\r\nTELjxj/O2LfAJ6zK/rU+YRZrudE8uG1eMteWFZIERxRsyMDB2f/PdoQEGHH6\r\nRo5y2LMRp3YtimWFkY7VOQuGQht4Rh1lRw/1jcZQk7+V3hY0aPa8FJyaM86z\r\nmfCydh2lDXirKwbNN8h0faSeeqiKAuWPsOcOsCfM4PlT7T3ebO36k63jN6vj\r\nrOogRfvwS30Wk15XFB7kM392eqHKhwAYfA4=\r\n=Jv5B\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.21_1680852026937_0.3444300103172109"},"_hasShrinkwrap":false},"0.0.21-beta.22":{"name":"remix-easy-mode","version":"0.0.21-beta.22","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","json serialization","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"8e26f83ecf19c0a0840a0cff1954e806b76d66be","_id":"remix-easy-mode@0.0.21-beta.22","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-rZEmDEeR2IEWyhaEdnLBumYWy5wnAtm7SAYjwmecb0nLK+xF6iQ7vJzX/wZ9eBuo2EFgtS6tc+S+d7RYQSlshQ==","shasum":"d626eab7dc9f3ae10c6814d1d886c675ff5e605f","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.22.tgz","fileCount":6,"unpackedSize":44133,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE9B2BivARAIFE1AfqIGGQwI06LnJwW7vJXdH3AlxSc6AiB8HXAI+ma7Ae7r4PODMXAiZDndh0zJWlbvmsSEvxHG2g=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkL8eKACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqS1g/+ITzp9KZyvVOGsZksKk5a2divtp+bQbUCRlk0nT0R5yVVWwqw\r\ncPVqI/FIkcZMubL33x7L0gjghsKqHg0FZAoBNMeTz8biBqu+WRDoKW2fPUKX\r\nMRUhsOXzuTL4tB4KXA2tVRERqYK0MPsrl3LsN3MjW7VcEjrWUm5YmAjWjKuq\r\nZ4ZQcqFak+UhF0sA5uXCzR5G4kOpH84U/A+1mfLrqeMs/KQr5ySdBjrxPpXA\r\nYZPSoPDYUMpHs1gn3doFQiuR9jQO9HKO0xWiOe2UYHJ3hM2KJUYvGDw4NpUA\r\nvWEetNnOTAW68m9+qMeqHtDcyFt+o+M/hFgYVihCFxij7IkdNdMBYbq/OfUU\r\n7KXOpOHrWyn3sb/0zH5Vd1XjhHpJJWsS4O8L6br+mO8O84O3+niBX0hTwPwi\r\nVj005DrFNbSdSFfm2mgRkpmrS2Kisux7Z+CDMEjTI6NYoWCsf6W8lHpEbOEJ\r\nFLRHXFrPRqpbbHKPQuhpMQbuO/OiAyU9P6ib2dYR6edPNOnV/ypJLJkdrxFx\r\nIs58Mq4jdaMjRJbJMRYaGSwpgVUWbu+9gGC3jkPFBt7bhyDdS9iKD1ATlWls\r\nMs27W5oU7Ap4FPkHFuLXuUiLzte1jH0MBfIqcmqCB0664vDJlKqDHVSGlzIm\r\n+9CWNe7CVoj2Jxj5fvW54hB8vtZsBr1hyH4=\r\n=2VWV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.22_1680852874644_0.3413420154622764"},"_hasShrinkwrap":false},"0.0.21-beta.23":{"name":"remix-easy-mode","version":"0.0.21-beta.23","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.1","@kiruna/promises":"0.0.0-alpha.1","@kiruna/zod":"0.0.0-alpha.1","remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/node":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.37.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","json serialization","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/node\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"07b74d799af0605778f8509ffe4b822ee2bb177a","_id":"remix-easy-mode@0.0.21-beta.23","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Rj3Le1BKEFcmpZB8xK4e4uiU/keNU5/WoFa+7slJFtjFRYOA+2Y5hRlVjSL2leW9DpYI/syp+6zfcqk+/qpaTQ==","shasum":"4fa76029df77c90ea70e94979445a5328c616e3a","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.23.tgz","fileCount":6,"unpackedSize":41063,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHvkXLp/XNVAEvhDF9nHkt9RAx0bvhVXJax5cldRXJZtAiA9vlhwzKkFbayASBW+uBCLi3zywpbRLQgRbnSJV+ZMzg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkMfx/ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoXlA/9HM8YKuUgImjoJ4kRtplgERAIvAHSApsqiLz9CmUr0K+ZourN\r\n4qw26ogFZ7Co7OgD8z0BRFPknL5Fa/iVnL6NugWLlvAkpWJR29ypC773HEMY\r\nQPq3sZkLVh2ZwFt2Bp5fE6aUUq6Qqcj5fltCUTo1mJqfQtuLuGlifZuPfOVW\r\neal09V3EYmL3o5jcHyLoDKIgLTwk41Fr88xh42JbEUwnt9tR9AfMq8g9u7U6\r\naXyvry/oWN/OyUBhIOfAfe2qvFfkTwrnYRXCrdzN2hPihtuDUbXqIuh2PvnJ\r\npK8/nSTTgNQTyiPQizuQM9AdfHaevr3NPYnDg9XQve9j4tEZFBG342rhLaHe\r\nXTZOnG08/bgoguTnBDhNB/dMOHKkfdFTjF6gC7HgwLCZa/b3Fg9drTO245W2\r\n25UZLdBLE/K5GCypgHFYwRYf3ctJCC0JmW4XlKIlUwuZdBiBbI5ju3u7QO63\r\nm7q+LwKtG1yvv+3UhiLtqp/VxiRHEiPLoWzmbT36irTAtNOzBObOmvSRrLc3\r\npo7jdNApjO7qdCmJyPM8SW+BAolJMuULI+fEIHxXjyeJP3UeJjZZC/HBFDzJ\r\nHXq1NRP/iddZ68cAkqB+RuLcX2r8xivrh0AJ9LsQudQZXY/KfSJyrByTAlOT\r\nV1y6DpnQUKEfwlUH1LoXUSMv6c+wXGXV52g=\r\n=TW+C\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.23_1680997502922_0.18765142164728088"},"_hasShrinkwrap":false},"0.0.21-beta.24":{"name":"remix-easy-mode","version":"0.0.21-beta.24","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.1","@kiruna/promises":"0.0.0-alpha.1","@kiruna/zod":"0.0.0-alpha.1","remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.37.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.3","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","json serialization","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/<your-server-runtime>\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and really opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"2bdc5cf77e943a6bc123b30ef970c64cacd32565","_id":"remix-easy-mode@0.0.21-beta.24","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-bK5z/fONdEvp8jIHCOfexJGnC/jqx81Z0YMYpR1q1HVt58mD6VW3ECC7iFvosmQOJyksoFpQAckGmlx5hTatMw==","shasum":"d62a2941c5996101e5d4765b4c203757f9dc0efb","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.24.tgz","fileCount":6,"unpackedSize":35774,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbEOpTnSXdJPekOusvTJeJ02qdrTkw0wKE8oPvL9vEMwIgMM+Jigu40gGhNhAiKNhtq8ALvF1oi7uMjkfvZCxWQto="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkMf+iACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpbeRAAn8ZkKB+/CiKd9ql5GwOO0es5lWtoQEKeceG2VTUpc84sgMx2\r\njMJTFJf73B8N2LTfqfgXmu021J4gGiiL6hlBJ4lOiPYBe6SuVX7rUQlpoQnV\r\nJEnj0jvuoLT9gYT5V/h5lMPqMh/nYxvF5btMqtmphIY7mZXzAYS2L9nwkXzf\r\njR8fPv8too43/OUqNrGtGshryxMAbAdscPPOhpwumv9b5RA4Yja5RA28+D7R\r\nnSDklB87t6Vpkqp3RfQtA1JQ3A2drOQ8Z4Lc7RE1gV5mgDF+WG4BgvFrI2Ej\r\nrH+yMWmDuD5u1gk2AnYcl1w9qaomrMPB2ZoH/T8Eu8WZCPW00gFsxe3gmDoX\r\n1YSMKRemwROSwP/pFLBAtLn1Lv1hCMI82geJ7ayxp7/0g9I/dWYdPKzeTuSz\r\nr9W1kTzmVvtJxnMseQlaV2vPkw0qkj8S32TNdnX9Y7NZpqh7e5K5hGgHf+bP\r\nHzJMYS0/hL7DLrAp52cFAF0VJWi59jcI+7QAA1fE2woWm5FEGxQ4UbxgUWAM\r\nzSS6/f+quCg7FtNGmDpxKXCuM+17Rl0ZSXmS5p1b4+MxneWlxOxlpR1c1EUs\r\niKIxCgRSGRpM84Ppby3cfClxVn+qZu4c3NXW6YvqeW2gt3nw1RcU6rH/DYDt\r\ngJ8skBibH33NHg8HmRsLZcs/SstMokytP8A=\r\n=vXvr\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.24_1680998306055_0.8013851460212802"},"_hasShrinkwrap":false},"0.0.21-beta.25":{"name":"remix-easy-mode","version":"0.0.21-beta.25","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.1","@kiruna/promises":"0.0.0-alpha.1","@kiruna/zod":"0.0.0-alpha.3","remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"170460f2ca68a4ec927765c639447c28ad2afa27","_id":"remix-easy-mode@0.0.21-beta.25","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-vVNpM/Ni8d2qIdgaJtWpvvzY4lcqltuVaHEKXLWL/x3Pii6dRtAhhp3GrkKyQsESzHgasd1gSfpRWOuk953z0g==","shasum":"838b09c6edae520ee243cd98e951d711000d5354","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.25.tgz","fileCount":6,"unpackedSize":35731,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+NwertvUm0ywKuZftnhC9kNAUuJMMSTsz6VQqpZO24gIhAPYJ+p67BEAcyPWQz1a4XcELQTcaEDHD6AC0iOymoOu8"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkMgRCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqEgQ/6AxH0cZkRoQNl2Y9InrB7wMLhDF3g5MR87bEf9Z/1wTBAyFFB\r\nwVdNBgtZMwDs5pH63p+TNv1zUEUUyac9fMVk52oBI9yDuXoo89xMGi2CPKvl\r\n/rZYbDyctht/crhn+sjzpd1qgOfTJzL3iyiwJ59+G7TnyAZy053B1B45G+is\r\nTYgYfpmqjaVfZhnWyU7oQ/kfQmlwwtlSqGZLMwrmf8lYZkznIr0x4G0are4J\r\nGsdCqVUFSgugHUeAYS0PlYnixVvR31TpHy/VD+opcO6uHolsd1u9wEgPP0TM\r\nJ1CWv6ROOQMvhEXbf/UqVb1MYnrI5ORuF1u7187yQhMWX18vvX10xvZ2h0rG\r\nPfjueBHBanANOS+sYEKsygDvPuyygGD7NDBAqE7+LCnR93ZAOvj2/xf2cw62\r\n5Q4Fw+sVCRSFtPDvdZcozlUn7ulMVbohrTRa8/7QwBSLeBWnhy50eclE+eRN\r\nIbSRrkmIcxy/YkYYHfdKXKCeBf+wch+SqhN4FWegKWU6WZ/cAw7gYmOTFo13\r\nM0e60hmESE3Bk2sBFzQTGBqDUQ1PaHU6mEWkTz6ai44TojrInbHXmnS3zKv4\r\nltB1KNX2C0T4Q3CyDx3kxX1rn3h3DLtueyxmYN3tr78DomP2btglooSQrmSX\r\nei7naoQPRGgDUt0mjuK6jM4akVLnH5VKpOw=\r\n=jIdE\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.25_1680999490494_0.2713458619055136"},"_hasShrinkwrap":false},"0.0.21-beta.26":{"name":"remix-easy-mode","version":"0.0.21-beta.26","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.1","@kiruna/promises":"0.0.0-alpha.1","@kiruna/zod":"0.0.0-alpha.3","just-debounce-it":"^3.2.0","remix-typedjson":"^0.1.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"f85f132b4202efa65b60475aa9665e8584aa52cb","_id":"remix-easy-mode@0.0.21-beta.26","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-TWAenI5eNIjrRfJgaT2jy85lkb1X7zsSBeJKAB1qSjfjEGhuHH6FII0JmIj2ecLSrcVV+v8+IvUIWFmI7jW3AA==","shasum":"44ef907267207f8eb224d96deba144293af8b4c1","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.26.tgz","fileCount":6,"unpackedSize":42604,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD6J+W9chBavoP12JSwGmxxAlCfTsPH1C8k/VwX4vS1mAIgRL2xUiOD5vpHnkHhwt60Rwr/RXIaLHR4phwaqT/Yz/g="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkMgoAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrKHg/+N9XX9Bpw3lEptYpyePfRPqpnwGkI3TV7wdnVMO/ORNsb/enG\r\nzn/HM0vDPofmj9xCny8yO12CCuIrWUx+WbLdnuaQmznS41r9jw11XB/6uwuE\r\nGOE9t6qu0u/VlWYaZctqc1fS1tfDk3z96Tz5e4R1TX5ex6c0eCy3MjbHlfAu\r\nWWmW+4TVOv/Vf1VnOqx2xL5S/6PlSQ2LG13kb5R37bzsb0KUjiZEmDeFdyPp\r\nthwit4ihoiy1RzTAVYssLw6yaHpoU8gHEP4cCZZH2qr/x6USE8xF/eYfeEak\r\nGjDslQP8JqqHzLuaYaYDJC44l/kH6X9TCXZByzwsS2/V9EbQuywM0gJRwIxH\r\nUhRH1aAQEJBYBso6dFWRAwZ6oMxcIAfQQXWGFRobniHlWQ4zoZb8Td4Lkv0c\r\n10l/Vz/lCvuuNdgXAmbtxUP71T25V33T77TbsVMvBTr9GkbqXNxoa/QISxJg\r\nB/HKpI/YKqm2Jg1Jdxo7OsMYf5E6kzRQLj5EGjFWQYXo5zROjSRJ6aYuSMsj\r\nW3xaydJgltYzNc6Uy/v/j4pmAxp+lOL+B0d59p+il0yDc9xJ67Q7ABLLszHl\r\nqcK26BIBHETOtZCqHHUOpS2nBpHfJgZi8U7NkLVWe3vF7fldfDBAKyQm+5cV\r\n6AQmdagdjKFUP2r0mRE0dKIZYMMJrgFwnC4=\r\n=jLrV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.26_1681000960654_0.8380741453309357"},"_hasShrinkwrap":false},"0.0.21-beta.27":{"name":"remix-easy-mode","version":"0.0.21-beta.27","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.1","@kiruna/promises":"0.0.0-alpha.1","@kiruna/zod":"0.0.0-alpha.3","just-debounce-it":"^3.2.0"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"6ecadb9ef2c990049927e4271e1b299e58332bb2","_id":"remix-easy-mode@0.0.21-beta.27","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-bfBeuj5YMzehdueaAdNuUGs1T56kh7bXpEHigqow+0+aTacwQqEIjwNABcMkVJpxTZWWO7eKgR1nLPvqJ1Gegg==","shasum":"5bfe058d2f306946753ddce674d6f87a399a275e","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.27.tgz","fileCount":6,"unpackedSize":42571,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFKsmDskKezEha/13S+nz3YuCV5SkcmgQJcEmD2bJS6OAiEAohXCFGFI8HaKkhVE4JUi9nhxMyPMe/3av8Q71dZNaJY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkMhnPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpg+g//XqwFUMV+U6oxc1yK1gYLwUo0Dl5WktzokEYXttQoBrfP4eZo\r\n4ksAwh0g0zTLwi7cRoOZis43za0nO0KX36Gu9YNbR3rJVn1Hmyp1/v6jNjLb\r\nuqpptm32obFi9YVoPLy6jXSN4GsPORFRkh3T7evHk+PcwDTTkO2mmO98JZzk\r\nSSrv1wdYfcrZkkheXfKrea7qOXedscRLw3urJNTJZ6hFRr9+QF4VL3r/Wfwc\r\nzXN/wRaf7GoyZ8vnOz8BeJe0G8a8vsSpw3K0wxSA5T2Hk9tMmarzi/H7R9IS\r\nJUde50W72PLCbQewmu0LKa3zvFxhlZsb0flA2Xs4E6e9jJ3F4tLIZssg2r0d\r\n9keExCLeJl01vMQK7lGDX8NE4f6u5wmDPfLIJ+rJ7OMCuGIUcUpMe6HE1KCZ\r\naGDhczeMZDi8oyhMoV2otEyUsVPLl/fVMK6A3Ou35NB0sZcmbrjSnv3Qba2O\r\npCRCHJAxi6PyVBTPbS1jkXBooLRci51ilSwqS32LOkPPm54g5wYrwObkh5ak\r\nSILF5brSMAVCVfBr4H4QRWsOWrjj1IeWtJfMn0InvvyjySrdEfLkq3XS299o\r\ngSMQ+6tHOwLpS0u5uLgD4em0xc4KvX8T49igTFEMFrVeyaqeYg+O/cQ/ooiS\r\na34ZOPph+MjXl7hiH8ShKSusWOEIDDiL5mU=\r\n=8LTg\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.27_1681005007280_0.9510769620604693"},"_hasShrinkwrap":false},"0.0.21-beta.28":{"name":"remix-easy-mode","version":"0.0.21-beta.28","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.1","@kiruna/promises":"0.0.0-alpha.1","@kiruna/zod":"0.0.0-alpha.3","just-debounce-it":"^3.2.0"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"4adb54055b3edb99e076d6508e7fd0fc6cedd156","_id":"remix-easy-mode@0.0.21-beta.28","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-+DI8xW73PFc14Mdt1q+Tz18Bp5LXoXEGp6SqcKCvyKBAXuKELJvMSsdNu8IECgkCksVl+hpj9ShAyZ6LceswKA==","shasum":"ff560d92737634915689353000656d8bba14c5f7","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.28.tgz","fileCount":6,"unpackedSize":42762,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIB4QrlGMMjfCt8ZC0Un0Yovjpd4kdH0Dkc7p4XFcZlnOAiEAo5VktojGjdU28XfUOylYlqE8N0k5edZAJOhVafWizKQ="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkMiCTACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq7Sw//Q3nX2LYA32ZbQPvI3y76/5cm3O0jlHOQGrs+yzk++lMYIzDV\r\nJiNhDKjkq+tPmg6E/nreVR7MmuruD0vKOtSd3SBMMCEzzg1xVx/tVNTgiifb\r\nvvIKz05vS+lz/NEhpcFnsDLNgRkfUmz+6Wx/dBboeYsWuwGhuDfeNij2UN6E\r\nk7ktGMctMKi1q99VcoKoh9O/K3CRxNbdn0bTQkZa11vyd9mRzagIBTdujw4Q\r\nNpgS+Pwpa4+vG4c2ayLAWb2kngrcy+5fDlu7NPhJIapMJhfevwEBOKrgrMTL\r\nh3zP/9TK0vURI50/3ZrGvd+2tIq2ltgmB/MBpcMLk+DRRbSdnLed4D01vaiJ\r\nrHRzEpcVwSqP+h4HoV3LZ4H8alKMs89uAc8hGH6qMBu5frC4tyLKH0gnGHmj\r\nFRaKYGRlXrx1ye6DAJTaDWUD96Q8t7mwjP7Pv6iGrYp51ayitvMh/4YpeC+G\r\ndPRXUodGBrbYqG2Dc+s0L48TDdzIDv+BbMvM7mtzK+vU1lGnSRC/TALCYDDb\r\nyP6L+i/6a+yPlgXtaPAvTMJbwUAo0nN/QJWnF4x3X7vdO19uO/NQoAWFlMjz\r\nACQwYb0OX9707fZjRyDc3SR1b1RSm28xgzj7T9pc/ul0LxzDSx6J/zDUi/O/\r\nJ+GuttLmRbWAZtX45W9nmsXAIS8ktaKM53Y=\r\n=J5+o\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.28_1681006738940_0.8891332621388526"},"_hasShrinkwrap":false},"0.0.21-beta.29":{"name":"remix-easy-mode","version":"0.0.21-beta.29","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.1","@kiruna/promises":"0.0.0-alpha.1","@kiruna/zod":"0.0.0-alpha.3","just-debounce-it":"^3.2.0"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","release":"pnpm run build && changeset publish","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"4adb54055b3edb99e076d6508e7fd0fc6cedd156","_id":"remix-easy-mode@0.0.21-beta.29","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-UA8DrKRJEbrSTAo8oBzvAFK5oMMtfcznm2NUa4qiFqrsaCPUjg95ceyfhxDEhAMdwS+594y6jJZcPtglolj0kA==","shasum":"84e34f1086c7509ec6dc79fd74fc42bdb09714fd","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.29.tgz","fileCount":6,"unpackedSize":42914,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCh/ae/uPTVD69NYL2R+vb9Vd2oLktIWPFpBpAf8WnQdQIgKI5zUwTlXhZ5a5GQaYOK11BZkEAt8HCooNqILJXwtHM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkMiG7ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqvNw//cbDEu8IVzo1pvkdV6iKDqHCBnv3kznYIQjFbxDClcHwUyeyx\r\nsmXCvayQjfMydL2noOAjrc/UCL5BdpJQor4wxIaTOR4EcN562OfURDHvTv1g\r\nrkxxUBVYstFJ0JwlTW5O6EnGuHhmc5jhcIt2Ia3cw+ZCo2SsnsOdKuXW7vr0\r\nTzk6jRnHVN5WKFR+dNqMfh6nTcrRHQHnGqSViBB+lx94y6ymVnLnQxfVFYDC\r\npGh+oOOiVeteJ+KOgJl9+fFlnhkoQxepQerlQR40KK1XcRoSI2WfOuA7AKtH\r\neZTLVpzPxq32NzKUD+c2YDdWKn9yB/4gwztuH1odB1YB07dmGpK3kSxDPUiR\r\nbvKsU89Lj52dhdXF1WrtgoJCQUJOZOUhDO1fmO+wgU65/sxeBl5orUFL57IB\r\nCjwpCndhCPSNI+JcCvw+1GmFxoyCiLgzDPTSaZBI/ukcMVvinSrAGuZIAbH2\r\nFC1bokCtvPDHNdXUtouBND5sZ25iroFdOC8AmdHATNNA9aGV0hDMEBf/D/Fk\r\nCfNhW/9EqJDF1eicqEd1L1mCLGHysI/Rtq5NinJk1QdvM3++ApVM+FYWwVQp\r\n6kEuifa0zDfEXpTZcRGXTZQEuVw+P8pQyYTkRiPAEf87oPrXvP3wkE6A6MOf\r\n7SW36rV7K+KZ1os+7rCMZeO8b9Y5MqC3clk=\r\n=huvE\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.29_1681007035641_0.4936626181995949"},"_hasShrinkwrap":false},"0.0.21-beta.30":{"name":"remix-easy-mode","version":"0.0.21-beta.30","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.6","@kiruna/promises":"0.0.0-alpha.6","@kiruna/zod":"0.0.0-alpha.6","just-debounce-it":"^3.2.0"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","lint":"tsc","release":"pnpm run build && changeset publish","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"c24d14a863bb87bb4be1bb448b5a44d8fc70e979","_id":"remix-easy-mode@0.0.21-beta.30","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-09xfAt2IHsX8IeuyWAanatAcBgshpcGvm3elkoh4HjP3OiqF/z2bNnDLt7nP6fpV1fWFlhQ3Lt60D16SY4B99g==","shasum":"280d20433e229205482c84dc44415c248510dfa3","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.30.tgz","fileCount":6,"unpackedSize":43952,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDAFxqGHXuG0bj8aD1ziM/63g22n0/X64UJJ6kH4I+T5QIgdQTolcN5pL299JwE0YziGyw2WxYov7SudqX1+5yQuow="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkMuqeACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoyvA//UwAt/3Dw/gIQ6EEnOEkeYYs3mkULOiEFXtY5bCeFoU7yUd7T\r\nsMqvQEKTs4QhKi1rAvbqrxQ1H85g5BZj/9N4i+nN6BJqssAWJ23uWfXHUd6l\r\nCozK0x7ngNy1Is6shxtsupcaqnoCsKPHFJbQ9h3Pc6CdURqande7wWs5seu9\r\ncdgECwhjCjpszj5Da5YTWBru+u6HK+KZNsaiFEmUN0ywBB27BMHirgsvcTWs\r\nN+BNXFRb4wrPYttPF9dPvjJ4LnN1XLQqDvTFwCI3eNTrs9n/sz6H6hZdGSQb\r\nTLorly86ASC3q2bQEam3nT52ZCiKQHh1TJ7GigFdKrFanTd3BqsPMzgc0QAH\r\nd5k65SfxW/zIIjd3NqVk7YvhkYiKNja10PS4f4R7U8sEJMPBQFSYMvtN52UX\r\nAv04hY9Xek+80lSZqO31KvWAwdcW+DF5t6+RSGmX8Bc//h8tycsoadXshhnn\r\neC0oYCQKNjbxiJdfbxqpVekGA7vfeotnEW6wDvN7E9gLqQ5OBX33Eki4Zq9s\r\nORZPjxb2j7X3qcgP137XnA68vzIqgvjKEwdgUg5yxb2xAjc6EUj3RMd38EoZ\r\nBVcXq5mEp9i7bS287ysD35dfV/osUk4VFNpISRIA1ftsJDRjA11uJEXoZV5N\r\nfnqKTZsCnpyVEVysY/Jvn+MUtdIj60zs7u4=\r\n=TvLM\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.30_1681058461836_0.7087673130964856"},"_hasShrinkwrap":false},"0.0.21-beta.31":{"name":"remix-easy-mode","version":"0.0.21-beta.31","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.7"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","lint":"tsc","release":"pnpm run build && changeset publish","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"c24d14a863bb87bb4be1bb448b5a44d8fc70e979","_id":"remix-easy-mode@0.0.21-beta.31","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Qkv0uylYEcCfbrJ5xz0BxBqsr7uO0JJOhQbXIJ7sYXJOGMpi7hMDBFzpEZj8mE9E5uYkP1+8h07ouPsOV0cWHQ==","shasum":"f32f0164427c0da26236b33a8eb352cb3ab49f2d","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.31.tgz","fileCount":6,"unpackedSize":37079,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD2JhYif8Z61dp2Rf1X+91rra23pDu6OxQhGA3/x+oihgIhAJ+nHar326nLPYxfPno5DaRXWilP3bv7GVob4B0cnmy/"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNNxmACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpY4xAAhf+kG8UAE61C5Zg7yGsLRrwfUvF+sJQLicondarueJpJNJDQ\r\n3+wAX1KWREJ4Yoh0EpqhhVHyhKy9++camSiiTFHvk492s/SzHUExmZzMfD6m\r\nWk2xTryzBUZ80XknRX8zEZP2b1xYxi8FGBLTokPYbFx/MR3oNsPHVYFnCLC2\r\nW24bNJI8oRcuRaoYZTcyehMQrWlRgH80DXc6mRZY3SrrU60G+T7IV79ZkiMl\r\nhVn7HlntUhvR8RHRGpZozkIUgin6ejohpHOgJbQ/df3F/09bhCvK/Jd/Qbx3\r\nLCYZXgxe5T8VjLeHUdc6AG6FvijM+i2msZnlRSl1In4AzzdsJvWNDz3mPpuz\r\n7OH1FLAv7tTPf1X2KG9AkODf3EOGNepL8oomvlY0OdNpOn/Uv33Ll33QWK8l\r\nAJRgYYXRhPKgbk7RHuq46J6YDBq3A0fEYAbqzd7O59qs+qciwDldWOX6lFMh\r\nX5Nnh7/XvkNM2Q29u9DUgmij17UrrgyVRaX+9fOkWZK148+J7uzAcFKDtYW3\r\n+0mKF6zq09x3QV6XvKCekzigR0TY+dlEN7b+C9LXcFo1pbHNnJVIkK4zxLJp\r\nULybbwg/456WOJ2lsx3mlmki7lEUBmKfrcFdhJ3FlYrFIKFIZghfC/XBmxwF\r\ntUnXijnqT8W7yzPTPe2bGzewHEFhz7UOxgc=\r\n=fJuj\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.31_1681185894675_0.11816037987440797"},"_hasShrinkwrap":false},"0.0.21-beta.32":{"name":"remix-easy-mode","version":"0.0.21-beta.32","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","lint":"tsc","release":"pnpm run build && changeset publish","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"7ca66212a496ae049c91bd656356ef4b52b9ab2f","_id":"remix-easy-mode@0.0.21-beta.32","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-YGbJXM5F/sTRNHeBkwfJP7OLpCGKDz2ecz+PSH5h+LsVOdZ+vBHOq8AdQGLg6osioG4A9eNXDxLmLVtTCfr1mA==","shasum":"c87d98e86753246e1d4b5d939a11a439053e3f42","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.32.tgz","fileCount":6,"unpackedSize":41382,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAAqASWhh/EJlO/EEWJ8ExXCZavLwDIHsuEpp0zLWoiAIhAJQBEBmL53j68Kj1DS/scAGvIw/8So6MJQWd9eaa+muc"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNfo5ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpqPA/+ImvAuXb2qHjGzIw3ZfPirUIMkzNEhAIIYaVkDCk3+kymGxRQ\r\n1Y0KvncwsrqY/jO8gxa3QKxFG4t+opA5/a5KYPiIcnufy2gapVU83itjSpoe\r\nFOS1KybOeudSfG31Kr+jui0NusYhZdc7amOXs3Er/KJzy9NjWduFjk7PJVFm\r\nNH+j+eqeBzrQY/BJnscke6ZrnkWcFC5h7pQwp2LsjA5DIVS5+Fk3P6s9grn3\r\n+fvNfpQ2bxB/u0Nz1r/RhHaOwUW8/srFT9/MAVp9lVeNeacB8LV/63vk96Qi\r\necM1iud2O36TWsCtc0iMsr4zVJ9FhwQa3n26wbofLvZqmQ3D6vlcjpLrfjPq\r\nEADyd5xbpabOnhiSqqbQJ1cADYsaNaEAPFbgig8aPeStQibw2FAhLiZ2hWla\r\n4U/Jvq7ta48rbJUL4UqeP1UN2wN6r2hapnvYmHeWGHBZ/ZZZvMMNeGf1jcie\r\nhQ4THvxXOE851vo+0vT6/y653+H+MLwvHUYasIy5q7H/BYKgYgz7TGquX8S8\r\nH0mCfuGvQD8z233jyibhYQWuzAzqKP2upmQkjEkK4C8AokZRxP4yaISN2ko7\r\nk4K5OJPn2gTCAnNum68I9yJI6q2y5ONnjcNeBpb9ohBvvuFb3O7xtsTiXaW7\r\nz/FwKBVve/8fxZeNqPLCIXnHoKYoN20cd+A=\r\n=XwKV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.32_1681259065544_0.9146593535443777"},"_hasShrinkwrap":false},"0.0.21-beta.33":{"name":"remix-easy-mode","version":"0.0.21-beta.33","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","lint":"tsc","release":"pnpm run build && changeset publish","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"cb7924254962ae130f9769d2aec7e4033e272aec","_id":"remix-easy-mode@0.0.21-beta.33","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-cx+L2S60QRBifep51gCXGWPbcvSm7WP5QT1mHpPLeZ6vI+rmAjMvFViFr0n/ohQu0df5hbUxakgiyJOALPX73A==","shasum":"756209eea84449959b10f9192b31b2cb64ae63a9","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.33.tgz","fileCount":6,"unpackedSize":41420,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDJsy7Fhb6IWojK640yUCeZwxdAYSBoqOPFMTC4Ru4QwgIgV21uW2+o5n/tbnH1e5jwbGy8XJ8mSem40xXQlGtx0JI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNfsZACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrVsxAAkcu8dopIWTqgYgbQw/Th6Bm3BZwf2ApmspPeaQD4Rxp+DnHy\r\nVzHp9evIUvwTiOamu6l+J6DK5e8hfzDxAIhNbVBUC7XQu3UqAKZUc1avXpVO\r\nlL6BKbCXc7bip2BafmciqCflZRavlNAyHFXlX+eMHYyXHkRnFPx2MRyIXaV+\r\nsX2wNfK4l6PjUjP/0NqplGcRub5IEYCAo3WFUeIyFSXZRWXI0k/uNNOAjwEG\r\n1N3Wb/fq1480BH5Xft0gv+fA0NEZ4QDruSQtUuDosY0HQy6oaQPUNT7Go83M\r\nvWfiZpO7bKOWtqpVEDY2fIf8kwfszSLpuVmoaMLNIvBVHnmX3g5DyIcGq6Ba\r\nZxKEp28ux5R7yNxHUNqsCPCmfq8/ZLFNAcUnz4Zme87dt4MzF62o/MlfO0lq\r\nSLEaA3L5sarMffTVzh2sipZvb5x5XETyrRc7wIndp0R2gxORByz8171ixwQK\r\nSpVlqWZRgtUzaXjLbNA3irs+sHr+NsfQ6bNye00e3tIyVeHBWiNHpKgUeI6Z\r\nS2EsnFA2+08MTUKD2akU2zi3+NF57Liv4QjSJbXZZLIInehYZKdLUCxGuUox\r\n8v5MNNhEyA/xtASpOBRHTrx7PfyXYA4MyN8FMtypwXR8eltitSatidOyodFy\r\nq6j7obs5Yoo5Rb2Mn2vzm8n9fSf0qhgKx0o=\r\n=OAgD\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.33_1681259288838_0.6880189371050156"},"_hasShrinkwrap":false},"0.0.21-beta.34":{"name":"remix-easy-mode","version":"0.0.21-beta.34","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","lint":"tsc","release":"pnpm run build && changeset publish","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"8c97ed76486c6b23c165aa70089b2cf70cc4ae39","_id":"remix-easy-mode@0.0.21-beta.34","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Y8HIMHWkDW9QMiThG2fY2PDo7hH5GbbLd1NRA/gorPsfZVu492zZcUoFVTtq9z8ALXqvbA75ERZa/ZwnZelSXw==","shasum":"8be03d7b65436b3c0933acd2b3a38d6e3a5e0117","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.34.tgz","fileCount":6,"unpackedSize":41496,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDe9HE5p/JxaXDBwwAJ5GcBvO/y1VkUrfISUXSGg1GPpQIgJTfFj9SKSrwj6dcwFbfT1DfphXWuDG6RVx5TMUhfa0c="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNf/nACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoMvxAAglmcrsfLZgVogemSbYH7LTXnZUXzS24DHmw7sGnS/aVQofBh\r\nwskShKNoU+weltGfRkm5uSKs9qPN6nIk940A4Egt7b/eRc+eHOFwcK9GNw/P\r\n4UaOB9JRhiVPcjFJG4i4yMTAR4ssdM0TR1dhv12ovsLFqMiNduOdVkcRhkRW\r\nEmqxHsfk3U0zG5835lFIRT4p60YYwjbaxCl8I7lz0ch7N5mmU9xPbb+6KE2s\r\nPn9P4Z8wOm2J/xfVcnRqWrZDPFjE9Y6KGUBW+d3TxTBXgt3RZIUQwe0RQa07\r\nSUNgiqJYkKuLsWcs6oZzgXqO8fTFcLJd4kDGY9/Xf0l/fqD9Ox4EVAAN3r4a\r\nYKsyPQsfYwOTZXUw2av7Q/NMK1VSzwDDnytcG1uSPzme7u8sXMuucZQafYEb\r\nzcexpqJFMcCs7J76tJXOGD63sv7OOK9sLFPNu2Fvwi8x/IMuxp347F3ZtY6q\r\nix9+QDXfggkyBBoWvLO8c7A/YdUUQUply0MbOId5BQK2m5VcVY++NYJ7J4os\r\njTR3AV3PLLW38BPLcsnpli2xRT+SMMtr+fhm+9mlVVo1jOCXIHIbP5uERmB4\r\nO2ECZa1dXN7hCGzzqahGB2se0IzZSBqFFTJPSryNhHDa3ktdCITfWgJbcWQy\r\nGX4UFMDZ568vSKNvk2+6o315Wd7a3EQvOmw=\r\n=n+Je\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.34_1681260519311_0.5200571424421236"},"_hasShrinkwrap":false},"0.0.21-beta.35":{"name":"remix-easy-mode","version":"0.0.21-beta.35","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","lint":"tsc","release":"pnpm run build && changeset publish","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"8c97ed76486c6b23c165aa70089b2cf70cc4ae39","_id":"remix-easy-mode@0.0.21-beta.35","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-UQiUR+f8vcbEQS33hZnLMOAEoSib7tFGFMf36O3nDVlmz3fD86BUnPy7Ah/nSquqER2+c8W9RYeVaJam/jR5Qg==","shasum":"4fd96e02b4abcb366eaa579981abad9aaf8198b5","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.35.tgz","fileCount":6,"unpackedSize":41123,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFv8YYJTR2vNoeNNcXL4pBWJhvThVUxBcG748/J7hzWHAiEA1psk0rEZx9ywsSfIkq4gD3UaL12aILGLCetcKDIK3z0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNgNDACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrYCA/+NWV4y8b85+DX62INU5PvDPPfLI4/+0fimZfm0w2a//jJ1G37\r\n7bIwfCsf90Th5xuh9EIu4RYjgGii4OnAwZYmSr/flP7yEesQJwAuSZWPb1rg\r\n06ONzBtdTh+hNpj0Y/8FL7qetn+tbuQN8Ldp4gqKnjF/UgXyBIXWg6Us3XaD\r\n0mzPLswQXo3D0FTAYjlm7T7pZg4Oc0NuWhY+gduswznlhRkS0USZgvQfapRJ\r\nKircbnilQi8/vQvnd796McqOreSSwa6vJspWVO6BzfEZUN8/fD3TL32gkO3U\r\n1hwd2hcKjvPvXiE7PVtAOZPhkwbo/rIFNFOaI/q09QlYOyoGsLXdNulbNK1R\r\nK90OoHTIwTk6/ODB0mTwJdhcspejvNaZrhy6MVQe8a6opfb/2ueB0XD65ntL\r\ndwchStBuz/bEBhGaJeBjx9n3x8+rAf7CgvOjN07RM7xWULlC7vYV0bKHnHkW\r\nuBgSaqineYLxlB+b4arDuuGkRdkQNSAJNJE4UKz2uEBumal2V4FOP/cx54/W\r\n3oR2rbsgufA0BJnKnU0pCLhYM22Zo1mKi087qP/mXTbsZ6VtZ83irWksdt09\r\np3p1iZ4zfMCTok02b3+5Z0+c93K7vV7kjpgWf1ST1jCC1CPrcN3bX7v1BZl9\r\nxgPTr9E8Chnp3UFlezJJvx47tqnhxbl+9LM=\r\n=6L5W\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.35_1681261378799_0.7255604538890252"},"_hasShrinkwrap":false},"0.0.21-beta.36":{"name":"remix-easy-mode","version":"0.0.21-beta.36","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","lint":"tsc","release":"pnpm run build && changeset publish","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"4edbb13bf43ea0d7d4d3122dd32c4fd9ddb33e37","_id":"remix-easy-mode@0.0.21-beta.36","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-3bhzY32Tm1lZe6pjn05jMQmg1ituQaZjw9T1w2S0O3Q7+1MkiuY7iz9/cJex7rx5uvTkznxoTaQe5DvxqVmoyw==","shasum":"ae1c2de1619579bfbbf1a1135db184b4efd5ec28","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.36.tgz","fileCount":6,"unpackedSize":39994,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHY1gedGlbOrdkaXoTqYtFDSN+uVWjM4axZhBCIqYq6KAiEAkVdVF9zZS1BoKyhB5Gr0xO9C0YLKTXy2UJEWItfxPPM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkNi9vACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmplvA/9EfzXAXksIinXKHZOs19CMM7BNTbKW+mTSpRh815xVOOwGHH9\r\nykU9uOQxQLkpwHVuEOMO5lIJ/ed2N8G1aUANS4IF/2CS89PpRZi3RGJeLFNv\r\nXwbBbXbamlNczmMXo7JZ91r++LWra9iiwgHVQ/BhVsKOL1pKF0MfLG8xuX7w\r\nEBmkYOfxF4a0Abxrh4EzfghsjnhSQUjWG/xauA5R//KDQamvgTlNIv95LTF0\r\nCs80dOhGuJ8l+bMMOJdgU1NCkBmvnLDtQfDZJMeraWeKMfTgv9t7wDQ2xTcK\r\nQE6rAiN5OPjEdjxS9GAtPqX7f9oLYWhIwWIKSqD88vYuVcl0s1VZcIJ9+t7a\r\nDRIBySoKtrmenYqO9kq+sMwswFwC/yX6LLY7IAqdQQon5qslErzu0gWnwfeY\r\nd4slePp+vzlDQpS5ygG+PCvB7+w2NCwfh0x5IqbSXK1LbGQ5hgP6hbGYH8Sy\r\nSaPzmmVjQHzLFOwBmtXokXbdZuO569HHtkVKQWEPB7VNVkliDu5I9vjcp7IV\r\nZIt75xvS6jWmdPDUKW2bYV/xSOcSlr/ZTHYS3DLfbJbhVEjBLY0mXvTXnzUv\r\n1p7jNhcHjCI9VipZK1Nj+6omym/09kfUWCWWdY71TW6sTThzBN+xNFyvuxB/\r\nL6vmVM4h4SZzHLkzWdt9raxgtv1y4Rf+8Nk=\r\n=vu1s\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.36_1681272686899_0.045115148273340955"},"_hasShrinkwrap":false},"0.0.21-beta.37":{"name":"remix-easy-mode","version":"0.0.21-beta.37","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@changesets/cli":"^2.26.1","@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"tsup index.ts --format cjs,esm --dts","lint":"tsc","release":"pnpm run build && changeset publish","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { data_function_helper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst input_schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return data_function_helper({\n    ctx,\n    input_schema,\n    bouncer: async ({ ctx, csrf_token }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    callback: async ({ input, session }) => {\n      // do whatever you want here\n      return {\n        message: \"Wow, that was easy!\" as const\n        at: new Date()\n      }\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof input_schema>({\n    path: \"/resource-route\",\n    input_schema,\n    on_success: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, form_props, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        form_props={form_props}\n        on_submit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          form_props={form_props}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n- This toolkit is really simple and opinionated. It's not for everyone, and that's OK.\n- If you know of smarter ways to do these things without massively overcomplicating the mental model, please let me know!\n- Yep, snake case. You won't talk me out of it.\n","readmeFilename":"README.md","gitHead":"8ab78169f41bfa461c6c6e4612c18eea6bb30441","_id":"remix-easy-mode@0.0.21-beta.37","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-wOMHo+7rNeo+otSurfEk/t8aQXx/sXa+r0lAiuOfreAR35b14Iq5S5es88EnbAS66qCvyBX1hiLplhNPO2Y73g==","shasum":"8ab6d992585d5398f9d46588e5a98faebed64c41","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21-beta.37.tgz","fileCount":6,"unpackedSize":39994,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDN+mQyKH3mTf0A6XF6Dn9xrm3bvE3EqKXf+8+mG6W60gIgJhPaJs9wUa3M8572IRoG0+rd5j1LgF2KOGnb1NgreWY="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkOd7bACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrhHQ/8CHxBVP84Y6Y2FhhWQ9gDl0vbbCQ5onvRddw2OAKVEozd4Vfd\r\nQmct/TdX8/KsS0tp2mzHHCwLmfkAXKO9L14sNXOzpXFMNFRayf63YcuBRiXi\r\nV1wj62UF0V5qeEC1c6W9gSdDioEXHKOxFm+M8brQB2l+wJeIrvK5yCL1o4FZ\r\nF3YjpZYN6sjGCQ6rJMdVCqc4zR1X9PiDKWDkrKxpukpOjd1vqisuGodEkwo8\r\nm9EAo6ALqzK7HYOwOYsM7TTL6apc4AXgdybR8kdSwhrNyvllXKO1yMFbrB0V\r\nnQuTu8WzfQ0tVi1tPRS3mJzadNvoCTeakY7gxoW6qivQXNmV8/6blUZPrsF6\r\nBn7K10HRg/pInqE7hvb1W1kqqgLiDZeX6D+0pgZ6Ev9RlOOyfvaQTBDOw2zA\r\ntIWFKMlMznGW1xVtRuVCXAAlvdz6aXDgA69R8ctZglfK3trFwHhYbZRuHhxG\r\nQjv8OcQcfM0VMsddUvahxpUou3NmbCsVBseWbCrgCTmwrIq9fLKkMlmtDor7\r\nW8lntP7GtOiPTLTl6mvDdNX653TPEWPOn9Qu2glEH/oOAM/mx83/EEnVQlMI\r\n8mUxj2shsEdC0hBvBF9yzEQXks1/GVGvgzbo1sWNK90chV1aCc6p+66d8XCE\r\neL8RlKv5WJrLG4P+MoD2t2RLQuBm4jbtKAM=\r\n=PtY5\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21-beta.37_1681514202852_0.644169229746917"},"_hasShrinkwrap":false},"0.0.21":{"name":"remix-easy-mode","version":"0.0.21","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"gitHead":"94d7f7f96de3ee5e6650e63d93390641c970933d","_id":"remix-easy-mode@0.0.21","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-YTS//G3q8c/pDfRzit2Bwei+BhhJq/eyRvK81VfZYSm+xe0/PN53iBK/7rvSM7EQJB9px0iCFzT8s9Ut7jwOhA==","shasum":"9e7891debcc5050f375bbf42646e393ba5ee6045","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.21.tgz","fileCount":6,"unpackedSize":39814,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF7PXKSmbQ9Gp3Y6fWwug274PUvM0Gv0RNUETA1618zfAiAnQyq0JySdPrsDgo6X7WHpkPXiKrgNcjpfFtp0yh0XVg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkPGygACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqF0w/8C6zLWMEdYclqbVMSyEr/FzzyV/0OdASFt6rzOmfcfg8nUk2a\r\nZZboMMLby1wlHDCZuI919E81XFOxwOYl36w9pvbr6eBIX2v16Ac06iKiO4kE\r\nELGW1e4df01zghTehZeQ5GapI88QgxiA4jLnyis39UzuLbp+uMQA5SA+R6cX\r\n7dWp1zArGkQtLhPE7nf7HPuUb4s81I8pjl8RhOA+1/J7FQBpw0Fc3xs06l9V\r\nyZCiYw5NTeYOQOjcLv86diN8zBe8iPC4S3Obr7VXT7xsjY4w2dm8xaxuMh/o\r\nuv6cPDLEf0gC7dCMvby2NA3/3GuK/xJfWNkv5aAk5Ku0hIkRzOOhZ6dlneWI\r\nmLwgEwrtUNPZSJISxV4J7hUf3rP1i/nr17hhM75LtMMEkZ9pRJWRMBU3B1Zm\r\nOsNqCc0hWXZF8Mb3ijEelwk8W38KBOPHw+O3+SC90Q0Eh+LsMfx93IQPs25K\r\nY86wrdRieBmpXLNuM0vW6+N449jbtZcLKsZ7hV8A4lrAgolDNgyK895I4Dql\r\nnEJIty90NROKL178zI6EfbhOg2vx0rHyiuQcFZHfG+ISEpKMef6hKoy5adQE\r\nhntNEGZdLtTb6ITO5zcMA+Yrh46UQqYILbZ6YuRlJQYdA0r2bXZI0F3NI7ii\r\nIhG+fjYKK1slQrlkYrJnSlHJDFv7e1BSrag=\r\n=48yZ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.21_1681681567827_0.9721664052139998"},"_hasShrinkwrap":false},"0.0.22":{"name":"remix-easy-mode","version":"0.0.22","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"gitHead":"74ea50d6afb5ea656f4aac7e49bf435a246ab9d9","_id":"remix-easy-mode@0.0.22","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-CfVfQ4UwDRueeHFYOpvKtIFROI+Hpbg85SWXn/s5cuSar/DZpGRKHa916lzQycUix5SgCNFSWvwYcZhJeJBrTQ==","shasum":"26abad2851c0019c792a97d2ce7cdf25c41d33e4","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.22.tgz","fileCount":6,"unpackedSize":39773,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCtJ7z2G6etl2Fj9HJezCnNTRc2/dxX4Xf2G1G/z/3mtQIhAK5IYKpDmJN4vBsx+xECp/f56puVafciHguHU4BmCezC"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkPNTCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo7UQ//bvBKezC6lw25UL+rmsJk0W8wE2zXT48uK6pIG2LbzxPyU/Ju\r\n11lE03Auo4sNr8Iv+wyhJS7WOguWw99l3U+XQZNJ8qrmBFzY7wgP3G8xBKXq\r\nTSjBS8dA9vW7BeueFjJj+3gWr0WingljZI2rTH33MpSIZv4Vl9jyam7dUyKn\r\nupl40zIGNcXQzomsnoXgAv/vBirUFaCBRaWhsKh9ADaXMWMzWLnVWZZdbIvh\r\n0YMfLF/0UQdXntpwn3Gb6sHwCZu77RlRY135TDTZfwyfSY6NmpPBCgAjJoUm\r\n77xUwxgGoRf0pssILIxKgRPsWXoznLIJpeVrr94tg9XCTee46Csp7QZqSmAF\r\nv+A5RDEWdDyRn8CYL5KmTn2JKtzrCagr1DlbBHSe5T8WmJQpa1xfp/2s9mc0\r\n0cV4Ym6WfBofwbFXuxa2dRYMfWOA4QjXeBPh8cehOAMuQSJ7RayUQ35ZMr46\r\nV/WyaEK7ETmC8tAgatvQhuNVRvLDbvl36uIGfh3t0hXCUObPodTwVzddAPZW\r\nEBpGo7vlzZMkyyDYTB0jyiYNqxnWjp8BIeF5jJYrYrPao0XgvEkW1PIObcde\r\nZ2ZAl9XSBx1/TNbe9Ga6hwcqgVXeAIxAqP/gKJOYiNhKiE8KwD0VoFeeE2jQ\r\nBuzoFOm08T8ULdBtMctghgM17MFW3DV1l+A=\r\n=Wsig\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.22_1681708226411_0.09170049178117723"},"_hasShrinkwrap":false},"0.0.23":{"name":"remix-easy-mode","version":"0.0.23","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"gitHead":"f8fb17c05f1d215581bbf228d9b154cfe0297bf8","_id":"remix-easy-mode@0.0.23","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-HYz9KftWgpHynI7TZvA+iLX4Ee7JoTff9o9Ihf33jfGV4lVeV143qColDkzj0lYOwsbuq33Cg4X+YACsn54nfg==","shasum":"f22f36e0b4ac8dc4eafbd968ecb9e9882f094e88","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.23.tgz","fileCount":6,"unpackedSize":39786,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEMqkZxBMRPYr6rzEPWL10BbYmVx3ZIaxyi33opSEKmQAiAy1u+OIPft65TJ33v4Qefsbu5+E4le9jtmrrse2BDbnw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkPNgCACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo7Yg//Ru09EN9T3W3NJbSLV41QCcqu4/e/QSCaLbOUzhB5tKxfzwbO\r\nl4o8n8EVF70zI1qujSZNjzcU+cfWrc9Au5GikWaI6/P0/SfLqchIJGFTLlyr\r\nMCgrKeOu7AmL8MRBcfhXizhqhWVTG91rD549Lep7ymp1HxXOjEtrgGXb+b3K\r\n8E81LROSL3Jsv9sjS1xrE+fM2WyTn2dNsrKhZK6xBZylFxEmIrUM0lIAzxxn\r\n41Q0YXvuCgbsuE3dOSEdmXKMhMog3ZfbC3mN5kU1iLO7nAPO7h1yxyaVJpPJ\r\ncZOz2L0sxnV2IbpdYQLbYPZlLEGq5PktCorcz+MD1hUqUJTopgZG0ZaM69DQ\r\nfOc4ZHjcIMjf79Ug/tId4eTwvTEPM9bfZ9hiPn2ZZEfuhgcCt+54rxpDqNBT\r\nO3sDUATQKjAIA8En2YKd3HYGHHsmwm7xmUMtY/ARHcS6WFcy9uyZWBM/qqgk\r\ngVaxTm3D3znQcytUYA/fTayVqDv/0i47/Swb/MgYsHs0gVh9hV1kDRRjUmS3\r\nCykKRO+FFNcvW3aolgxWm/msTlQTFUSj2tEsgX9y6aFfJsNhoKjNOMal+ABO\r\n2HXLBcfkgI+l1iV4dv9H/euYk33C2dOGzu4+Ga8ldjqzeJObS5bLH4ikvgxW\r\nU5+TVRcVRr7K5OckjlCkb/ly9mG8NQLJgoc=\r\n=4xSm\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.23_1681709057982_0.015585572296096029"},"_hasShrinkwrap":false},"0.0.24":{"name":"remix-easy-mode","version":"0.0.24","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"gitHead":"9c2a2cebb394be6ea1765301b5b942bff9d6777d","_id":"remix-easy-mode@0.0.24","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-rjyIiO+MJL4Q7muLi/uanPcdb+JBqxnHeFo7m5kEeXpVxAX1vD8p6UIwEcSE1xKXxbF/vE+Utxz1hrJubNcDlQ==","shasum":"9268643dfa9405de858f2b7fda58dc43641e1df3","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.24.tgz","fileCount":6,"unpackedSize":39862,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC1c/bQvq2TG3rUtLhMue1zw5EwI7NZ/p+rNZmER3E8FAiAdn5PDIMho5fKpNgR8buz3spA3Zbk0oWyGv4IC9bCycA=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkTpJzACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmow3xAAnvq4x2KGL2DWR+ZOjbMH0SFJUEbp8qcJLWJrHkRuSsQI0bvl\r\nT8MBjQf+Y9mPyuTrvbOLfJ/l4Af3RprPOtAaFoMZnPAmhhjkBi/KdBMNcBTB\r\nk+vvZf0yjA9WYgVfnsEGlJHdo6/gatL0oHyCauqznnbxyzl2XZR4EFLVajKU\r\njTjnYDPebxxZIcMgCnvOWZMdk7IFcO/SEhA0VgtO+pTWBbo5tKoFO8aVVklK\r\nMqhqxFxnSdYEJD7oO64IlV4m2rj3ycfLz/O8dV5/MjijrUzgcGDKPcw+H2xF\r\nyD9vK4viA2BO75Flpl1pu8DspQP8Sdy4xS3iO83JiJjzpuqD6e46nfEV4kHd\r\n5TBpv+nrTJ/n+J/KQApiUuJoUUXtEW008xDUN+WKZZIOJeO3lOTnJKyVv8Bb\r\nK12263/kOIsXbvebpArYynoHogcj0yK4GgbZFwSjvRyKw1zfkGsKACcDWR3e\r\nkbjC7QWDTdEGBOgpgzR3sRGJgkxU+/+187aTR8zZ5Iji6Js7WlghRe6hVz/4\r\nwMsy8rMukY+fZuOqV/PhPiRVu/NtmJRcbW/p1w/fvYv7uLju2NSCRk0bTa5v\r\n04WGKLhBnYMqREmAB80BtCdxZnOskBTYSC3bWk1qAdhVcMjACKmCVksrXRWF\r\nnzcxP59MerRz3Jne2hoLrIjp7P26R/1U8HQ=\r\n=1i1o\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.24_1682870899091_0.8764599362135685"},"_hasShrinkwrap":false},"0.0.3-beta.0":{"name":"remix-easy-mode","version":"0.0.3-beta.0","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode#readme","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, formProps, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        formProps={formProps}\n        onSubmit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          formProps={formProps}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"79a33b94dd1ac41930efa0791437e52bce97e583","_id":"remix-easy-mode@0.0.3-beta.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-LQL89bohywsXvPteKxxc8Zx39ijMZqGYiYGDnyUVc7tgheOIY8H4cTYAdFEks41/bG0DDIj0LKTvT9ZG3t8gfQ==","shasum":"2b6d3bcae925541263a646017c08d1c264debb07","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.3-beta.0.tgz","fileCount":6,"unpackedSize":28465,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCB1bqE8kbCRD9XI/vzoZrXS+2oZE+YagSWbGLPuAvBiQIgCBqqDlvIZpP2KbM2PuszqTrODIJDdGHZCQbF34Wv1Gw="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.3-beta.0_1687740218714_0.07925503384528176"},"_hasShrinkwrap":false},"0.0.3-beta.1":{"name":"remix-easy-mode","version":"0.0.3-beta.1","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, formProps, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        formProps={formProps}\n        onSubmit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          formProps={formProps}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"79a33b94dd1ac41930efa0791437e52bce97e583","_id":"remix-easy-mode@0.0.3-beta.1","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-4MZb2L1Jz41D6ow10nZ7sqXXLUm39ds/lQnllA8o1wz04Jo66i/mdf1prQJPzQssSnr+/4M7DsXR6e/KtDh+GA==","shasum":"a194d6fc08fc280348c2716c17692d20fdafb8eb","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.3-beta.1.tgz","fileCount":6,"unpackedSize":28458,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDkiiCGLtMieJcEPQHSWsb5jrPjg1yGgKTkjt0ArgsRCwIgK4H3/+Zq4Kt3lE1Elivpas5azAGp5hUSK+0pm2o4vPY="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.3-beta.1_1687740888317_0.2670583976077714"},"_hasShrinkwrap":false},"0.0.3-beta.2":{"name":"remix-easy-mode","version":"0.0.3-beta.2","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7","@kiruna/zod":"0.0.0-alpha.8"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, formProps, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        formProps={formProps}\n        onSubmit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          formProps={formProps}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"79a33b94dd1ac41930efa0791437e52bce97e583","_id":"remix-easy-mode@0.0.3-beta.2","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-2+i9ALf97P4XO2iou6fHz4i+dB6SUMEsXqS/zjo988YH4oEeDZUQUmeQhc2PkairXX/Ak1x7kIBPahWemrQnGQ==","shasum":"e4a7a53e77ec51c35f532b49a8527c7901874154","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.3-beta.2.tgz","fileCount":6,"unpackedSize":28200,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC5MGBqiyT/zXY9b0DMBdudkZtl5w3VXx9NqGAZWwSLlAIgJShX5s3bEiUoj42tBtpPwsDbgeaT65sjrkr803tJyA8="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.3-beta.2_1687740971228_0.623628039099388"},"_hasShrinkwrap":false},"0.0.3-beta.3":{"name":"remix-easy-mode","version":"0.0.3-beta.3","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  some_user_input: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { FormHelper, InputHelper } from \"remix-easy-mode\"\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { run, formProps, result } = useExampleHook()\n\n  return (\n    <div>\n      <FormHelper\n        formProps={formProps}\n        onSubmit={({ input }) => {\n          run({ input })\n        }}\n      >\n        <InputHelper\n          formProps={formProps}\n          label=\"Whatever\"\n          name=\"some_user_input\"\n        />\n\n        <button type=\"submit\">Submit</button>\n      </FormHelper>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"79a33b94dd1ac41930efa0791437e52bce97e583","_id":"remix-easy-mode@0.0.3-beta.3","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-GGba/Am5y82SqAHj7aj3hvhCchm5xeTxoh/oN+Bfri1BsrD1EnPMojGyrcLJuE5/F/5qXE4/LfQNIr+qkRY+gw==","shasum":"d1b5b3dc5a8a5fd15e189aa86ff7bfc748c1ca5b","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.0.3-beta.3.tgz","fileCount":6,"unpackedSize":27445,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCCNmoVPAt9dMvdDDubpqPGRcvpsxPjY9gAUzRq2O4QiAIhAK2cxnrSuX95PM1pA2b0zX31NGz1hxF1tIZb7Uo/dnWS"}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.0.3-beta.3_1687741393134_0.2249024676368201"},"_hasShrinkwrap":false},"0.1.0-beta.0":{"name":"remix-easy-mode","version":"0.1.0-beta.0","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { Form, fields, submit, result } = useExampleHook()\n\n  return (\n    <div>\n      <Form onSubmit={({ input }) => submit({ input })}>\n        <input name={fields.someUserInput.name} />\n        <button type=\"submit\">Submit</button>\n      </Form>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"07e94a2e1b3e646c4aa234781bb6b1146239a9dc","_id":"remix-easy-mode@0.1.0-beta.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-YpKkb4jTXGadxM4MVn4pwpHQJ+PuvrZk+2dG1gm8C3g/4XcLUH0PQx5YIJ/GQFLXvHgH0Rd4VK/q92AKygzecA==","shasum":"21d317c5db66f0578bb32cabb20b22c690109234","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.0-beta.0.tgz","fileCount":6,"unpackedSize":27096,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGlD3HYeC08Y2aPqSgTpee8hCNtjeCiAG6N1fKzoX093AiAbwxBfugFklmVww5ho4DWz3VryJa7FIev4La6B8perrA=="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.0-beta.0_1687742932914_0.8887251946410024"},"_hasShrinkwrap":false},"0.1.0-beta.1":{"name":"remix-easy-mode","version":"0.1.0-beta.1","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { Form, fields, submit, result } = useExampleHook()\n\n  return (\n    <div>\n      <Form onSubmit={({ input }) => submit({ input })}>\n        <input name={fields.someUserInput.name} />\n        <button type=\"submit\">Submit</button>\n      </Form>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"51cacb7fef6378fbdc359c68f210d4fb3a6a3712","_id":"remix-easy-mode@0.1.0-beta.1","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-OwZL2aThqt+VAhriiNnjkIm+jV5KlYWX5Ga8L+d/S/pfhfGAHUOUYmhXa/D3BcA9X7+TV4gGaGdXPSHB9fG5dw==","shasum":"da2bc2a06b148973b08ad0083d48116f82a891d5","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.0-beta.1.tgz","fileCount":6,"unpackedSize":28912,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAmIe1Q0QwPaYoCiywy6UIADF3vLdxtd7D1rlpWgqSBDAiBQftt4Z8nKPe6gH1vgCLl16s8hRlS+8JmDxL0YmGe5uA=="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.0-beta.1_1687745452281_0.9011173705395104"},"_hasShrinkwrap":false},"0.1.0-beta.2":{"name":"remix-easy-mode","version":"0.1.0-beta.2","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { Form, fields, submit, result } = useExampleHook()\n\n  return (\n    <div>\n      <Form onSubmit={({ input }) => submit({ input })}>\n        <input name={fields.someUserInput.name} />\n        <button type=\"submit\">Submit</button>\n      </Form>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"16f7c303edcb2e7f75702610798791f29f9398d9","_id":"remix-easy-mode@0.1.0-beta.2","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-sZ6DqkNsVftxxMotJ36cevuUaZAFikyWYlEqqcBoAtNrIVNjI0bIfd0SVDdX3BESqfoyhL/CwX1/2/J7HGCzpw==","shasum":"f6474be438f83a07c230dd6e90b791516a3b6461","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.0-beta.2.tgz","fileCount":6,"unpackedSize":28838,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICXo7ltC+mvukL0jyjY9xja/q8EGyEXBvX+Wf6d1/OjNAiAhr2pX0qRki2ZjIFAGrD58ZyZRroeXERX7roAiN7hHGg=="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.0-beta.2_1687747224497_0.9914566987302986"},"_hasShrinkwrap":false},"0.1.0-beta.3":{"name":"remix-easy-mode","version":"0.1.0-beta.3","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { Form, fields, submit, result } = useExampleHook()\n\n  return (\n    <div>\n      <Form onSubmit={({ input }) => submit({ input })}>\n        <input name={fields.someUserInput.name} />\n        <button type=\"submit\">Submit</button>\n      </Form>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"ac33e51068a2599bf02154eabdebbc8921db5b46","_id":"remix-easy-mode@0.1.0-beta.3","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-tNtNbBcPYSzcMkYZ7K80qiWyf3TCcMwAT6mc1WaHkhnXBUsUmo4xFD1HjbGVuHdwgeOAX1pmlbpN+w+ZsG+23Q==","shasum":"b6807087f33e73b603d8d2716071ddc86d92f4b2","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.0-beta.3.tgz","fileCount":6,"unpackedSize":28610,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH1dOFNvwrcc46vWqh7G+LyF16mSpfByhBC9bR8Zusi3AiAhlsdR06+mzgTo9Fs4d0d+mNEfHmhI2bOiiKAUE/pD0A=="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.0-beta.3_1687747528088_0.7997733058742473"},"_hasShrinkwrap":false},"0.1.0-beta.4":{"name":"remix-easy-mode","version":"0.1.0-beta.4","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.15.0","@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.15.0","@remix-run/server-runtime":"^1.15.0","react":"^17 || ^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { Form, fields, submit, result } = useExampleHook()\n\n  return (\n    <div>\n      <Form onSubmit={({ input }) => submit({ input })}>\n        <input name={fields.someUserInput.name} />\n        <button type=\"submit\">Submit</button>\n      </Form>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"74b8d44ca942d4c7b7e49ad3a51e3d5dd97f827e","_id":"remix-easy-mode@0.1.0-beta.4","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-xmZMgatpwVpFs04OJ9H4bMe1odGyGSlWAglLNHSDA6MkJ1OowkwqB+c9Jfx7b61ecdKDDTTE/V3YbD37T9mGJw==","shasum":"49e9ba290e7b46f1d9c51318832e1f05ba4b5db0","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.0-beta.4.tgz","fileCount":6,"unpackedSize":34233,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIA/ufYon7hEI2u56HciaD0Qtj7CYixpLrkqfmcmy3ex6AiEA3qFDr7xW+GjpxX/+V4aMlPS9BdMxpvJnORFvJk9+YbM="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.0-beta.4_1687765616867_0.6683548036972589"},"_hasShrinkwrap":false},"0.1.0-beta.5":{"name":"remix-easy-mode","version":"0.1.0-beta.5","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.18.0","@remix-run/react":"^1.18.0","@remix-run/server-runtime":"^1.18.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.18.0","@remix-run/server-runtime":"^1.18.0","react":"^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"readme":"# remix-easy-mode\n\n## Description\n\nOpinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX (type-safety + react-query style \"on settled\" mutation callbacks), plus a few extra goodies (such as typesafe form helpers with automatic client-side validations).\n\n## Features\n\n- Automatic form validations (client-side and server-side)\n- Typesafe form inputs and data responses via helper components / hooks\n- Typesafe session middleware support (via \"bouncer\" pattern)\n- Typesafe session and input values passed to server-side callbacks\n- Automatic error handling and error message display\n- Component helpers are unstyled, so you can style them however you want\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Video Tutorial\n\nhttps://www.youtube.com/watch?v=CxrtfHbXKuM\n\n## Usage\n\nExample resource route:\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // do whatever you want here\n      // throw an error if something is wrong\n    },\n    fn: async ({ input, session }) => {\n      // do whatever you want here\n      return \"Wow, that was easy!\" as const\n    },\n  })\n}\n\n// return hook from your resource route to use on client\nexport const useExampleHook = () => {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (data) => console.log(data),\n  })\n}\n```\n\nExample client-side form:\n\n```tsx\nimport { useExampleHook } from \"./resource-route\"\n\nexport default function Index() {\n  const { Form, fields, submit, result } = useExampleHook()\n\n  return (\n    <div>\n      <Form onSubmit={({ input }) => submit({ input })}>\n        <input name={fields.someUserInput.name} />\n        <button type=\"submit\">Submit</button>\n      </Form>\n\n      <pre>{JSON.stringify(result, null, 2)}</pre>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## License\n\nMIT\n\n## Caveats\n\n- This is a work in progress. It's not yet battle-tested, and the API may change without notice. If you want to use this in production, set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"de5336f20ee97a8676c964f174eb41dd73e29210","_id":"remix-easy-mode@0.1.0-beta.5","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-/zccetxxIpl8mZIdNoKJbj2kp4iNEYWCy0oyGM6EPrU4hyRm8X+v7kfuMLLUS0EgBjWO/ypB2qz9MeSksyuuKw==","shasum":"698e38fd632b8c8881a067835d31f8e2b90b0381","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.0-beta.5.tgz","fileCount":6,"unpackedSize":34724,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDH73slJD9NqBI/7DyvKk0at9BTpxFEu0Zz9pAm6h0MlQIgPpIfeqZs5sCmMlNRITcXppbU1NCVy62JTjHjTfDWW2c="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.0-beta.5_1687829397330_0.8002402395244526"},"_hasShrinkwrap":false},"0.1.0":{"name":"remix-easy-mode","version":"0.1.0","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.18.0","@remix-run/react":"^1.18.0","@remix-run/server-runtime":"^1.18.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.18.0","@remix-run/server-runtime":"^1.18.0","react":"^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"gitHead":"f61c1636ad08324195749e5bb055617974f15374","_id":"remix-easy-mode@0.1.0","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-3uVnxy2g3iT9Z6cwjHvGeZ9S15h8anIpvcmvz84ikCR80t1e9P1W8xGkGmdmXmoztbztbqoDUikWB1abnoAC5A==","shasum":"15f1163738f5f142a29d05eb48ac910a78ede1f6","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.0.tgz","fileCount":6,"unpackedSize":34800,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBISFTy9l2z1aEP4a65JEx5aXqjo5j7BC2j3CMsHS5l3AiEAw26crVVSpWWrjSgfyvWqcO1W2uj2Kb8nTb+VglcaaTM="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.0_1687835156910_0.4936270338154207"},"_hasShrinkwrap":false},"0.1.1":{"name":"remix-easy-mode","version":"0.1.1","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.7","@kiruna/promises":"0.0.0-alpha.7"},"devDependencies":{"@remix-run/eslint-config":"^1.18.0","@remix-run/react":"^1.18.0","@remix-run/server-runtime":"^1.18.0","@types/react":"^18.0.33","eslint":"^8.38.0","react":"^18.2.0","rimraf":"^5.0.0","tsup":"^6.7.0","typescript":"^5.0.4","zod":"^3.21.4"},"peerDependencies":{"@remix-run/react":"^1.18.0","@remix-run/server-runtime":"^1.18.0","react":"^18","zod":"^3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","hooks","toolkit","typescript","typesafe","api","zod","easy mode","query","mutation","action","loader","form","validation","form validation","bouncer","session","middleware","zod","libary","framework"],"sideEffects":false,"gitHead":"29f18ccf7abc5c6b14b24220a8c55feb56339da0","_id":"remix-easy-mode@0.1.1","_nodeVersion":"16.18.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-Vub/CyNY74JbYD3224BJa5I+sJFeZT5nTrrMOxyoyx3Z28Fd9V3z6voxiI/ES0AaOS7xh01d5YLXJB/IIxtogg==","shasum":"b524ce95c0e41d6976dd22fc05613097bb33daa4","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.1.tgz","fileCount":6,"unpackedSize":35937,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCcyLiWp9hgObP9l7e7QupSXicbcxYp6/uN3EwnKBZ6EwIgEgWkYJT5nCVCK2sNcuYYkgXlTgGYFWyzqeuy59qW8Qc="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.1_1688430089140_0.600585546904262"},"_hasShrinkwrap":false},"0.1.2":{"name":"remix-easy-mode","version":"0.1.2","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.31"},"devDependencies":{"@remix-run/eslint-config":"^2.2.0","@remix-run/react":"^2.2.0","@remix-run/server-runtime":"^2.2.0","@types/react":"^18.2.33","eslint":"^8.52.0","react":"^18.2.0","rimraf":"^5.0.5","tsup":"^7.2.0","typescript":"^5.2.2","zod":"^3.22.4"},"peerDependencies":{"@remix-run/react":">=1.18.0","@remix-run/server-runtime":">=1.18.0","react":">=18","zod":">=3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","typescript","typesafe","zod","api","react","query","mutation","action","loader","forms","validation","form validation","trpc","bouncer","session","middleware"],"sideEffects":false,"_id":"remix-easy-mode@0.1.2","gitHead":"ba9c980bf0a8bb5515c961cc540c245621c52d07","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-NMps9EgxQq/sr5AsWhh2nXz0S0eXWioDK8tLn1ylKg6XMCghja+fYFFsC3s28+l4mLYVZfmiK93qwl6lgxnIvw==","shasum":"d46ae27dbedb12560f7fca2b0ba33b00b2151071","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.1.2.tgz","fileCount":7,"unpackedSize":41973,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCyihzo4ONDVAJgJfWJ04/BKBiohAWjEtLHw1LigrSQNgIhAICNNQjACxJBQ1rKqH6hMpNQSwH2jPa4mZcWNOQqYSuS"}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.1.2_1698808885144_0.0058079134199469085"},"_hasShrinkwrap":false},"0.2.0-beta.0":{"name":"remix-easy-mode","version":"0.2.0-beta.0","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.31"},"devDependencies":{"@remix-run/eslint-config":"^2.2.0","@remix-run/react":"^2.2.0","@remix-run/server-runtime":"^2.2.0","@types/react":"^18.2.33","eslint":"^8.52.0","react":"^18.2.0","rimraf":"^5.0.5","tsup":"^7.2.0","typescript":"^5.2.2","zod":"^3.22.4"},"peerDependencies":{"@remix-run/react":">=2.2.0","@remix-run/server-runtime":">=2.2.0","react":">=18","zod":">=3"},"scripts":{"build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","typescript","typesafe","zod","api","react","query","mutation","action","loader","forms","validation","form validation","trpc","bouncer","session","middleware"],"sideEffects":false,"_id":"remix-easy-mode@0.2.0-beta.0","readme":"# Remix Easy Mode\n\nSimple, typesafe toolkit for developing highly interactive Remix apps\n\n## Features\n\n- 100% typesafe\n- Built on zod\n- Inspired by TRPC\n- Designed for building highly interactive apps\n- Bone-simple client form validations\n- Server-side input validations _a la_ TRPC\n- Session middleware via \"bouncer\" pattern\n- `onSuccess`, `onError`, and `onSettled` mutation callbacks _a la_ react-query\n- Input helpers are unstyled (and polymorphic, if you want to supply your own input components)\n- Optional custom serializers (_e.g._, `superjson`)\n- MIT licensed\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\n### Resource Route\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\n// this is like a TRPC procedure\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // (1) throw error or (2) return user session\n    },\n    fn: async ({ input, session }) => console.log({ input, session }), // typesafe!,\n  })\n}\n\n// return hook from your resource route to use on client\nexport function useExample() {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (res) => console.log(res), // typesafe!,\n  })\n}\n```\n\n### Client-side Form\n\n```tsx\nimport { InputHelper } from \"remix-easy-mode\"\nimport { useExample } from \"./resource-route\"\nimport { StyledInput } from \"./your-custom-input-component\"\n\nexport default function Index() {\n  const { Form, fields } = useExample()\n\n  return (\n    <div>\n      <Form\n        csrfToken=\"whatever\" // optional\n        onSuccess={(res) => console.log(res)} // typesafe!\n      >\n        <InputHelper {...fields.someUserInput.props} component={StyledInput} />\n\n        <button>Submit</button>\n      </Form>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## Peer Dependencies\n\n`react`, `@remix-run/react`, `@remix-run/server-runtime`, `zod`\n\n## Disclaimer\n\nThis is a work in progress. It's not yet battle-tested, and the pre-1.0.0 API will change without notice. If you want to use this in production, be careful, and set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"ba9c980bf0a8bb5515c961cc540c245621c52d07","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-9U6EoS+x3fVx2Mu9PIYLbKGQbbi4UmQBCd2dPyS6xluTIV6HCChm6un8yftlpacg5BdI4QBx0FYo17Zqls0Xhw==","shasum":"bb6e4a9b9f7520ccd8fccebc97cae123f42b2de4","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.2.0-beta.0.tgz","fileCount":7,"unpackedSize":42004,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIExa9BVNUA3cAKZW1xnObV9VxOex97p98u6U9VyTeyIVAiEA3nzODx9qI25KEh8Plw4orodVQRKurMhkFP/ts5990eg="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.2.0-beta.0_1698811681105_0.054513956256249774"},"_hasShrinkwrap":false},"0.2.0":{"name":"remix-easy-mode","version":"0.2.0","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.31"},"devDependencies":{"@remix-run/eslint-config":"^2.2.0","@remix-run/react":"^2.2.0","@remix-run/server-runtime":"^2.2.0","@types/react":"^18.2.33","eslint":"^8.52.0","react":"^18.2.0","rimraf":"^5.0.5","tsup":"^7.2.0","typescript":"^5.2.2","zod":"^3.22.4"},"peerDependencies":{"@remix-run/react":">=2.2.0","@remix-run/server-runtime":">=2.2.0","react":">=18","zod":">=3"},"scripts":{"dev":"rimraf dist && tsup index.ts --format cjs,esm --dts --watch","build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","typescript","typesafe","zod","api","react","query","mutation","action","loader","forms","validation","form validation","trpc","bouncer","session","middleware"],"sideEffects":false,"_id":"remix-easy-mode@0.2.0","gitHead":"ba9c980bf0a8bb5515c961cc540c245621c52d07","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-AXQGG/Ekz7BHeIUi0VLM5ToK1c3dqdlU2qMIxqDkm04GN+7YSggBvzM8x7YZk6ecZi3V6p/dwCvSRJjAg70wdg==","shasum":"446fccc0b55db41df9e793849fac10351bee7515","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.2.0.tgz","fileCount":7,"unpackedSize":42071,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCawbo1vnqFEO0MpTpcLL9wT0elHVpycha8f0bnFscm7gIhAL/bddet0LZuwuRcLJEsJinIPfF8VKhogdpUGfUihz93"}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.2.0_1698811769495_0.9486320382705675"},"_hasShrinkwrap":false},"0.2.1":{"name":"remix-easy-mode","version":"0.2.1","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.31"},"devDependencies":{"@remix-run/eslint-config":"^2.2.0","@remix-run/react":"^2.2.0","@remix-run/server-runtime":"^2.2.0","@types/react":"^18.2.33","eslint":"^8.52.0","react":"^18.2.0","rimraf":"^5.0.5","tsup":"^7.2.0","typescript":"^5.2.2","zod":"^3.22.4"},"peerDependencies":{"@remix-run/react":">=2.0.0","@remix-run/server-runtime":">=2.0.0","react":">=18","zod":">=3"},"scripts":{"dev":"rimraf dist && tsup index.ts --format cjs,esm --dts --watch","build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","typescript","typesafe","zod","api","react","query","mutation","action","loader","forms","validation","form validation","trpc","bouncer","session","middleware"],"sideEffects":false,"_id":"remix-easy-mode@0.2.1","gitHead":"529a6e729eba1993e34ded247354dcad2240f25b","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-pS6XML0MBY1yfJSo9pClCWhdjCfZZrg9qznkIqNBkBivS1cOPLHOcmxLw+CXanSNUBW4+v2lv6yjsgpGGwCxXg==","shasum":"ccf6351e35e584056c49afb0245339b8967f1f59","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.2.1.tgz","fileCount":7,"unpackedSize":42071,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC/BNsZ3PiwujiSoO2L31KO4u8ES2AkLrmN0YJH0fxx2QIhAPcuGIrCRpDWcvNkqB01STz8vQcJClNDEZcMokrNXrTd"}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.2.1_1698812309449_0.966301704301834"},"_hasShrinkwrap":false},"0.2.2-beta.0":{"name":"remix-easy-mode","version":"0.2.2-beta.0","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.31"},"devDependencies":{"@remix-run/eslint-config":"^2.2.0","@remix-run/react":"^2.2.0","@remix-run/server-runtime":"^2.2.0","@types/react":"^18.2.33","eslint":"^8.52.0","react":"^18.2.0","rimraf":"^5.0.5","tsup":"^7.2.0","typescript":"^5.2.2","zod":"^3.22.4"},"peerDependencies":{"@remix-run/react":">=2.0.0","@remix-run/server-runtime":">=2.0.0","react":">=18","zod":">=3"},"scripts":{"dev":"rimraf dist && tsup index.ts --format cjs,esm --dts --watch","build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","typescript","typesafe","zod","api","react","query","mutation","action","loader","forms","validation","form validation","trpc","bouncer","session","middleware"],"sideEffects":false,"_id":"remix-easy-mode@0.2.2-beta.0","readme":"# Remix Easy Mode\n\nSimple, typesafe toolkit for developing highly interactive Remix apps\n\n## Features\n\n- 100% typesafe\n- Built on zod\n- Inspired by TRPC\n- Designed for building highly interactive apps\n- Bone-simple client form validations\n- Server-side input validations _a la_ TRPC\n- Session middleware via \"bouncer\" pattern\n- `onSuccess`, `onError`, and `onSettled` mutation callbacks _a la_ react-query\n- Input helpers are unstyled (and polymorphic, if you want to supply your own input components)\n- Optional custom serializers (_e.g._, `superjson`)\n- MIT licensed\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\n### Resource Route\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\n// this is like a TRPC procedure\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // (1) throw error or (2) return user session\n    },\n    fn: async ({ input, session }) => console.log({ input, session }), // typesafe!,\n  })\n}\n\n// return hook from your resource route to use on client\nexport function useExample() {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (res) => console.log(res), // typesafe!,\n  })\n}\n```\n\n### Client-side Form\n\n```tsx\nimport { InputHelper } from \"remix-easy-mode\"\nimport { useExample } from \"./resource-route\"\nimport { StyledInput } from \"./your-custom-input-component\"\n\nexport default function Index() {\n  const { Form, fields } = useExample()\n\n  return (\n    <div>\n      <Form\n        csrfToken=\"whatever\" // optional\n        onSuccess={(res) => console.log(res)} // typesafe!\n      >\n        <InputHelper {...fields.someUserInput.props} component={StyledInput} />\n\n        <button>Submit</button>\n      </Form>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## Peer Dependencies\n\n`react`, `@remix-run/react`, `@remix-run/server-runtime`, `zod`\n\n## Disclaimer\n\nThis is a work in progress. It's not yet battle-tested, and the pre-1.0.0 API will change without notice. If you want to use this in production, be careful, and set your dependency to a specific version.\n","readmeFilename":"README.md","gitHead":"a064c2f8d0537191a983582d0dd464f8e06706e3","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-WadHByHp3XFhQaOrCOAzFpKP9YZ8G7f2ygUnNyMFkakgdTi68IRnVMHIGP043dTWOV8u8u6TiHNmNQVYxQhk2g==","shasum":"159c7dfaa493f7b9990c0772636ab23e305310c0","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.2.2-beta.0.tgz","fileCount":7,"unpackedSize":42207,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH5nh6YEv1RPFaOb+Wf2cx9HADIKXqKEAK4dTWYvFJBYAiB6P20F38A6BFKhJGkTwjFD7HHs4Tr4rK8el0HtRhtjyg=="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.2.2-beta.0_1698876860093_0.4390841448928382"},"_hasShrinkwrap":false},"0.2.2":{"name":"remix-easy-mode","version":"0.2.2","author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"license":"MIT","description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","dependencies":{"@kiruna/form-data":"0.0.0-alpha.31"},"devDependencies":{"@remix-run/eslint-config":"^2.2.0","@remix-run/react":"^2.2.0","@remix-run/server-runtime":"^2.2.0","@types/react":"^18.2.33","eslint":"^8.52.0","react":"^18.2.0","rimraf":"^5.0.5","tsup":"^7.2.0","typescript":"^5.2.2","zod":"^3.22.4"},"peerDependencies":{"@remix-run/react":">=2.0.0","@remix-run/server-runtime":">=2.0.0","react":">=18","zod":">=3"},"scripts":{"dev":"rimraf dist && tsup index.ts --format cjs,esm --dts --watch","build":"rimraf dist && tsup index.ts --format cjs,esm --dts","lint":"tsc","publish-beta":"npm publish --tag beta"},"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"homepage":"https://github.com/sjc5/remix-easy-mode","bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"keywords":["remix","typescript","typesafe","zod","api","react","query","mutation","action","loader","forms","validation","form validation","trpc","bouncer","session","middleware"],"sideEffects":false,"_id":"remix-easy-mode@0.2.2","gitHead":"a064c2f8d0537191a983582d0dd464f8e06706e3","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-HOgWcZeiJD13Ru2/6kJqm0ahRwhn0ixMMkh/pfWkUeUkAy5tmeBtFVVitwn0dLOXGfSBoJRHZawaJasTQsNhRA==","shasum":"eaad6fdfde65b378a317fb839b071e136458af20","tarball":"https://registry.npmjs.org/remix-easy-mode/-/remix-easy-mode-0.2.2.tgz","fileCount":7,"unpackedSize":42200,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFpFGFvZO9O4icKiZRma9v8lgia0Xmu48Ni4SGIlZmhLAiEAwHNyNY9C2txk3RU/AGJjCALQ1HDkYEyybLSKH7AKmPw="}]},"_npmUser":{"name":"sjc5","email":"email@samcook.cc"},"directories":{},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/remix-easy-mode_0.2.2_1698876957793_0.010781681291484047"},"_hasShrinkwrap":false}},"time":{"created":"2023-04-04T15:49:03.190Z","0.0.19":"2023-04-04T15:49:03.421Z","modified":"2023-11-01T22:15:58.224Z","0.0.20":"2023-04-04T16:45:00.589Z","0.0.21-beta.0":"2023-04-06T01:08:17.283Z","0.0.21-beta.1":"2023-04-06T02:33:22.934Z","0.0.21-beta.2":"2023-04-06T03:46:10.711Z","0.0.21-beta.3":"2023-04-06T03:52:46.031Z","0.0.21-beta.4":"2023-04-06T04:03:20.636Z","0.0.21-beta.5":"2023-04-06T04:44:13.723Z","0.0.21-beta.6":"2023-04-06T04:55:09.409Z","0.0.21-beta.7":"2023-04-06T05:12:25.834Z","0.0.21-beta.8":"2023-04-06T05:23:29.453Z","0.0.21-beta.9":"2023-04-06T05:28:09.031Z","0.0.21-beta.10":"2023-04-06T05:33:40.370Z","0.0.21-beta.11":"2023-04-06T06:46:52.348Z","0.0.21-beta.12":"2023-04-07T00:19:03.619Z","0.0.21-beta.13":"2023-04-07T00:52:53.601Z","0.0.21-beta.14":"2023-04-07T04:49:24.454Z","0.0.21-beta.15":"2023-04-07T04:55:06.840Z","0.0.21-beta.16":"2023-04-07T05:13:04.349Z","0.0.21-beta.17":"2023-04-07T05:35:48.147Z","0.0.21-beta.18":"2023-04-07T05:43:03.913Z","0.0.21-beta.19":"2023-04-07T05:51:24.992Z","0.0.21-beta.20":"2023-04-07T06:33:13.933Z","0.0.21-beta.21":"2023-04-07T07:20:27.093Z","0.0.21-beta.22":"2023-04-07T07:34:34.866Z","0.0.21-beta.23":"2023-04-08T23:45:03.109Z","0.0.21-beta.24":"2023-04-08T23:58:26.196Z","0.0.21-beta.25":"2023-04-09T00:18:10.686Z","0.0.21-beta.26":"2023-04-09T00:42:40.831Z","0.0.21-beta.27":"2023-04-09T01:50:07.510Z","0.0.21-beta.28":"2023-04-09T02:18:59.146Z","0.0.21-beta.29":"2023-04-09T02:23:55.789Z","0.0.21-beta.30":"2023-04-09T16:41:02.042Z","0.0.21-beta.31":"2023-04-11T04:04:54.819Z","0.0.21-beta.32":"2023-04-12T00:24:25.742Z","0.0.21-beta.33":"2023-04-12T00:28:09.032Z","0.0.21-beta.34":"2023-04-12T00:48:39.473Z","0.0.21-beta.35":"2023-04-12T01:02:59.028Z","0.0.21-beta.36":"2023-04-12T04:11:27.069Z","0.0.21-beta.37":"2023-04-14T23:16:43.031Z","0.0.21":"2023-04-16T21:46:07.997Z","0.0.22":"2023-04-17T05:10:26.558Z","0.0.23":"2023-04-17T05:24:18.206Z","0.0.24":"2023-04-30T16:08:19.303Z","0.0.3-beta.0":"2023-06-26T00:43:38.874Z","0.0.3-beta.1":"2023-06-26T00:54:48.471Z","0.0.3-beta.2":"2023-06-26T00:56:11.368Z","0.0.3-beta.3":"2023-06-26T01:03:13.299Z","0.1.0-beta.0":"2023-06-26T01:28:53.069Z","0.1.0-beta.1":"2023-06-26T02:10:52.494Z","0.1.0-beta.2":"2023-06-26T02:40:24.655Z","0.1.0-beta.3":"2023-06-26T02:45:28.262Z","0.1.0-beta.4":"2023-06-26T07:46:57.094Z","0.1.0-beta.5":"2023-06-27T01:29:57.672Z","0.1.0":"2023-06-27T03:05:57.083Z","0.1.1":"2023-07-04T00:21:29.297Z","0.1.2":"2023-11-01T03:21:25.439Z","0.2.0-beta.0":"2023-11-01T04:08:01.310Z","0.2.0":"2023-11-01T04:09:29.765Z","0.2.1":"2023-11-01T04:18:29.843Z","0.2.2-beta.0":"2023-11-01T22:14:20.248Z","0.2.2":"2023-11-01T22:15:58.059Z"},"maintainers":[{"name":"sjc5","email":"email@samcook.cc"}],"description":"Opinionated toolkit for developing highly interactive, typesafe Remix apps. Built with zod, and inspired by the TRPC / React Query DX. Provides automatic client and server-side form validations, typesafe form input fields, automatic error handling and eas","homepage":"https://github.com/sjc5/remix-easy-mode","keywords":["remix","typescript","typesafe","zod","api","react","query","mutation","action","loader","forms","validation","form validation","trpc","bouncer","session","middleware"],"repository":{"type":"git","url":"git+https://github.com/sjc5/remix-easy-mode.git"},"author":{"name":"Sam Cook","email":"email@samcook.cc","url":"https://samcook.cc"},"bugs":{"url":"https://github.com/sjc5/remix-easy-mode/issues"},"license":"MIT","readme":"# Remix Easy Mode\n\nSimple, typesafe toolkit for developing highly interactive Remix apps\n\n## Features\n\n- 100% typesafe\n- Built on zod\n- Inspired by TRPC\n- Designed for building highly interactive apps\n- Bone-simple client form validations\n- Server-side input validations _a la_ TRPC\n- Session middleware via \"bouncer\" pattern\n- `onSuccess`, `onError`, and `onSettled` mutation callbacks _a la_ react-query\n- Input helpers are unstyled (and polymorphic, if you want to supply your own input components)\n- Optional custom serializers (_e.g._, `superjson`)\n- MIT licensed\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\n### Resource Route\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\n// this is like a TRPC procedure\nexport const action = (ctx: DataFunctionArgs) => {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) => {\n      // (1) throw error or (2) return user session\n    },\n    fn: async ({ input, session }) => console.log({ input, session }), // typesafe!,\n  })\n}\n\n// return hook from your resource route to use on client\nexport function useExample() {\n  return useAction<typeof action, typeof schema>({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (res) => console.log(res), // typesafe!,\n  })\n}\n```\n\n### Client-side Form\n\n```tsx\nimport { InputHelper } from \"remix-easy-mode\"\nimport { useExample } from \"./resource-route\"\nimport { StyledInput } from \"./your-custom-input-component\"\n\nexport default function Index() {\n  const { Form, fields } = useExample()\n\n  return (\n    <div>\n      <Form\n        csrfToken=\"whatever\" // optional\n        onSuccess={(res) => console.log(res)} // typesafe!\n      >\n        <InputHelper {...fields.someUserInput.props} component={StyledInput} />\n\n        <button>Submit</button>\n      </Form>\n    </div>\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## Peer Dependencies\n\n`react`, `@remix-run/react`, `@remix-run/server-runtime`, `zod`\n\n## Disclaimer\n\nThis is a work in progress. It's not yet battle-tested, and the pre-1.0.0 API will change without notice. If you want to use this in production, be careful, and set your dependency to a specific version.\n","readmeFilename":"README.md"}