diff --git a/README.md b/README.md index 566bef5..e058482 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,12 @@ go build ## Breaking Changes (For builds before this date) +### 9 February 2025 + +Migrate using polar.sh, if you want to keep using stripe you must add `PAYMENT_PROVIDER=stripe` to .env + +All stripe related features will be removed soon + ### 24 December 2024 New file upload feature requires a tigris/s3 bucket with webhook setup in order to work properly diff --git a/frontend/bun.lock b/frontend/bun.lock index 197b640..07cce66 100644 --- a/frontend/bun.lock +++ b/frontend/bun.lock @@ -7,6 +7,8 @@ "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", "@lucia-auth/adapter-drizzle": "^1.0.7", + "@polar-sh/sdk": "^0.25.0", + "@polar-sh/sveltekit": "^0.3.17", "@prgm/sveltekit-progress-bar": "^2.0.0", "@stripe/stripe-js": "^4.3.0", "@types/he": "^1.2.3", @@ -38,7 +40,7 @@ }, "devDependencies": { "@sveltejs/adapter-node": "^2.0.0", - "@sveltejs/kit": "^2.5.27", + "@sveltejs/kit": "^2.17.1", "@sveltejs/vite-plugin-svelte": "^4.0.0", "@types/pg": "^8.11.6", "autoprefixer": "^10.4.14", @@ -50,7 +52,7 @@ "prettier": "^3.1.0", "prettier-plugin-svelte": "^3.2.6", "prettier-plugin-tailwindcss": "^0.5.7", - "svelte": "^5.0.0", + "svelte": "^5.19.9", "svelte-adapter-bun": "^0.5.1", "svelte-check": "^4.0.0", "tailwindcss": "^3.4.14", @@ -316,6 +318,12 @@ "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + "@polar-sh/adapter-utils": ["@polar-sh/adapter-utils@0.1.11", "", { "dependencies": { "@polar-sh/sdk": "^0.24.0" } }, "sha512-HVQDuFmfU6dDuX7IBbZ5WGPkNnh3WQFklchatfNPjZVd0suTKTQjqbz3NOJwGY+zqbQ/B4Ul9KQZ8fYNe4kN6A=="], + + "@polar-sh/sdk": ["@polar-sh/sdk@0.25.0", "", { "dependencies": { "standardwebhooks": "^1.0.0" }, "peerDependencies": { "zod": ">= 3" } }, "sha512-D4aMPr/XnZeUsZ62g9ZtnQXmudsJDviPuuP4nlE+6JuabQ15G0t+Pq+siQaksg7e1mPUKYPZgA63zYVH9XmMPQ=="], + + "@polar-sh/sveltekit": ["@polar-sh/sveltekit@0.3.17", "", { "dependencies": { "@polar-sh/adapter-utils": "0.1.11", "@polar-sh/sdk": "^0.24.0" }, "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-T7+5htm1TqlYM7RsKNymkaLwAIROLvmHgk2h8UEZeCzp70MAI+MWPsWyHltjV+R4+tVf/m8Q/d4yc3KawNFo7w=="], + "@polka/url": ["@polka/url@1.0.0-next.25", "", {}, "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ=="], "@poppinss/macroable": ["@poppinss/macroable@1.0.2", "", {}, "sha512-xhhEcEvhQC8mP5oOr5hbE4CmUgmw/IPV1jhpGg2xSkzoFrt9i8YVqBQt9744EFesi5F7pBheWozg63RUBM/5JA=="], @@ -478,11 +486,13 @@ "@smithy/util-waiter": ["@smithy/util-waiter@3.1.9", "", { "dependencies": { "@smithy/abort-controller": "^3.1.8", "@smithy/types": "^3.7.1", "tslib": "^2.6.2" } }, "sha512-/aMXPANhMOlMPjfPtSrDfPeVP8l56SJlz93xeiLmhLe5xvlXA5T3abZ2ilEsDEPeY9T/wnN/vNGn9wa1SbufWA=="], + "@stablelib/base64": ["@stablelib/base64@1.0.1", "", {}, "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="], + "@stripe/stripe-js": ["@stripe/stripe-js@4.3.0", "", {}, "sha512-bf8MxzzgD3dybtyIJUQSDMqxjEkJfsmj9IdRqDv609Zw08R41O7eoIy0f8KY41u8MbaFOYsn+XGJZtg1xwR2wQ=="], "@sveltejs/adapter-node": ["@sveltejs/adapter-node@2.1.2", "", { "dependencies": { "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "rollup": "^4.8.0" }, "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-ZfVY5buBclWHoBT+RbkMUViJGEIZ3IfT/0Hvhlgp+qC3LRZwp+wS1Zsw5dgkB2sFDZXctbLNXJtwlkjSp1mw0g=="], - "@sveltejs/kit": ["@sveltejs/kit@2.7.3", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.0.0", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0", "tiny-glob": "^0.2.9" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3" }, "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-Vx7nq5MJ86I8qXYsVidC5PX6xm+uxt8DydvOdmJoyOK7LvGP18OFEG359yY+aa51t6pENvqZAMqAREQQx1OI2Q=="], + "@sveltejs/kit": ["@sveltejs/kit@2.17.1", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.2.2", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0" }, "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-CpoGSLqE2MCmcQwA2CWJvOsZ9vW+p/1H3itrFykdgajUNAEyQPbsaSn7fZb6PLHQwe+07njxje9ss0fjZoCAyw=="], "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@4.0.0", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.0||^3.0.0", "debug": "^4.3.7", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.12", "vitefu": "^1.0.3" }, "peerDependencies": { "svelte": "^5.0.0-next.96 || ^5.0.0", "vite": "^5.0.0" } }, "sha512-kpVJwF+gNiMEsoHaw+FJL76IYiwBikkxYU83+BpqQLdVMff19KeRKLd2wisS8niNBMJ2omv5gG+iGDDwd8jzag=="], @@ -494,7 +504,7 @@ "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], - "@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], "@types/he": ["@types/he@1.2.3", "", {}, "sha512-q67/qwlxblDzEDvzHhVkwc1gzVWxaNxeyHUBF4xElrvjL11O+Ytze+1fGpBHlr/H9myiBUaUXNnNPmBHxxfAcA=="], @@ -656,9 +666,9 @@ "escalade": ["escalade@3.1.1", "", {}, "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="], - "esm-env": ["esm-env@1.0.0", "", {}, "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA=="], + "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], - "esrap": ["esrap@1.2.2", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", "@types/estree": "^1.0.1" } }, "sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw=="], + "esrap": ["esrap@1.4.3", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw=="], "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], @@ -668,6 +678,8 @@ "fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="], + "fast-sha256": ["fast-sha256@1.3.0", "", {}, "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="], + "fast-xml-parser": ["fast-xml-parser@4.4.1", "", { "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw=="], "fastq": ["fastq@1.15.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw=="], @@ -746,7 +758,7 @@ "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - "is-reference": ["is-reference@3.0.2", "", { "dependencies": { "@types/estree": "*" } }, "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg=="], + "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], @@ -986,6 +998,8 @@ "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], + "standardwebhooks": ["standardwebhooks@1.0.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "fast-sha256": "^1.3.0" } }, "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg=="], + "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -1006,7 +1020,7 @@ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "svelte": ["svelte@5.1.3", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "acorn-typescript": "^1.4.13", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "esm-env": "^1.0.0", "esrap": "^1.2.2", "is-reference": "^3.0.2", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-Sl8UFHlBvF54aK8MElFvyvaUfPE2REOz6LnhR2pBClCL11MU4qpn4V+KgAggaXxDyrP2iQixvHbtpHqL/zXlSQ=="], + "svelte": ["svelte@5.19.9", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "acorn-typescript": "^1.4.13", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^1.4.3", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-860s752/ZZxHIsii31ELkdKBOCeAuDsfb/AGUXJyQyzUVLRSt4oqEw/BV5+2+mNg8mbqmD3OK+vMvwWMPM6f8A=="], "svelte-adapter-bun": ["svelte-adapter-bun@0.5.1", "", { "dependencies": { "tiny-glob": "^0.2.9" } }, "sha512-eLbkKuoCaZPzVN20dg/oZOUybO16oEQCOQuzAI2jVLU90VbJ1P099bAlA+7H4KPGI2r2sdkfD1MppGAbk7PdMw=="], @@ -1122,12 +1136,18 @@ "@napi-rs/wasm-runtime/@emnapi/runtime": ["@emnapi/runtime@1.1.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3bfqkzuR1KLx57nZfjr2NLnFOobvyS0aTszaEGCGqmYMVDRaGvgIZbjGSV/MHSSmLgQ/b9JFHQ5xm5WRZYd+XQ=="], + "@polar-sh/adapter-utils/@polar-sh/sdk": ["@polar-sh/sdk@0.24.0", "", { "dependencies": { "standardwebhooks": "^1.0.0" }, "peerDependencies": { "zod": ">= 3" } }, "sha512-bTx5agBShP7L0ZpFGSVO1Ux1Epxk9S1L6iFNZEL0n5JK8ZDwzmnNou7csEycn/FzbTYC8KBEhZP+O6T1Bx8ULA=="], + + "@polar-sh/sveltekit/@polar-sh/sdk": ["@polar-sh/sdk@0.24.0", "", { "dependencies": { "standardwebhooks": "^1.0.0" }, "peerDependencies": { "zod": ">= 3" } }, "sha512-bTx5agBShP7L0ZpFGSVO1Ux1Epxk9S1L6iFNZEL0n5JK8ZDwzmnNou7csEycn/FzbTYC8KBEhZP+O6T1Bx8ULA=="], + "@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="], "@rollup/plugin-commonjs/magic-string": ["magic-string@0.30.5", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA=="], "@rollup/plugin-json/@rollup/pluginutils": ["@rollup/pluginutils@5.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^2.3.1" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g=="], + "@rollup/pluginutils/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + "bits-ui/esm-env": ["esm-env@1.1.4", "", {}, "sha512-oO82nKPHKkzIj/hbtuDYy/JHqBHFlMIW36SDiPCVsj87ntDLcWN+sJ1erdVryd4NxODacFTsdrIE3b7IamqbOg=="], "editorconfig/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], @@ -1138,8 +1158,6 @@ "esbuild-runner/tslib": ["tslib@2.4.0", "", {}, "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="], - "esrap/@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], - "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "js-beautify/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], @@ -1152,6 +1170,8 @@ "postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="], + "rollup/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + "runed/esm-env": ["esm-env@1.1.4", "", {}, "sha512-oO82nKPHKkzIj/hbtuDYy/JHqBHFlMIW36SDiPCVsj87ntDLcWN+sJ1erdVryd4NxODacFTsdrIE3b7IamqbOg=="], "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -1282,8 +1302,12 @@ "@gcornut/valibot-json-schema/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + "@rollup/plugin-commonjs/is-reference/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + "@rollup/plugin-commonjs/magic-string/@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.4.15", "", {}, "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="], + "@rollup/plugin-json/@rollup/pluginutils/@types/estree": ["@types/estree@1.0.5", "", {}, "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="], + "esbuild-register/debug/ms": ["ms@2.1.2", "", {}, "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="], "js-beautify/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -1398,8 +1422,6 @@ "vite/rollup/@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-2mLH46K1u3r6uwc95hU+OR9q/ggYMpnS7pSp83Ece1HUQgF9Nh/QwTK5rcgbFnV9j+08yBrU5sA/P0RK2MSBNA=="], - "vite/rollup/@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], - "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], diff --git a/frontend/drizzle/0029_chemical_wiccan.sql b/frontend/drizzle/0029_chemical_wiccan.sql new file mode 100644 index 0000000..807df9d --- /dev/null +++ b/frontend/drizzle/0029_chemical_wiccan.sql @@ -0,0 +1 @@ +ALTER TABLE "user" ADD COLUMN "polar_customer_id" varchar(255); \ No newline at end of file diff --git a/frontend/drizzle/meta/0029_snapshot.json b/frontend/drizzle/meta/0029_snapshot.json new file mode 100644 index 0000000..cf41a09 --- /dev/null +++ b/frontend/drizzle/meta/0029_snapshot.json @@ -0,0 +1,548 @@ +{ + "id": "f7c94100-ab5e-40a0-82b6-b4f93b459a6c", + "prevId": "ce042384-c48f-4a7b-b067-8808e73834d6", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.email_verification_token": { + "name": "email_verification_token", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.file": { + "name": "file", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "etag": { + "name": "etag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at_epoch": { + "name": "created_at_epoch", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "updated_at_epoch": { + "name": "updated_at_epoch", + "type": "bigint", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.project": { + "name": "project", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "uuid": { + "name": "uuid", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "qr_background": { + "name": "qr_background", + "type": "varchar(7)", + "primaryKey": false, + "notNull": true, + "default": "'#ffffff'" + }, + "qr_foreground": { + "name": "qr_foreground", + "type": "varchar(7)", + "primaryKey": false, + "notNull": true, + "default": "'#000000'" + }, + "domain_status": { + "name": "domain_status", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "'verified'" + }, + "enable_custom_domain": { + "name": "enable_custom_domain", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "custom_ip": { + "name": "custom_ip", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "custom_domain_id": { + "name": "custom_domain_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "custom_domain": { + "name": "custom_domain", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "qr_corner_square_style": { + "name": "qr_corner_square_style", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "'square'" + }, + "qr_dot_style": { + "name": "qr_dot_style", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "'square'" + }, + "qr_image_base64": { + "name": "qr_image_base64", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.shortener": { + "name": "shortener", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "link": { + "name": "link", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "ios": { + "name": "ios", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "ios_link": { + "name": "ios_link", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "android": { + "name": "android", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "android_link": { + "name": "android_link", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "code": { + "name": "code", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "project_id": { + "name": "project_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_file_upload": { + "name": "is_file_upload", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "file_path": { + "name": "file_path", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "uuid": { + "name": "uuid", + "type": "uuid", + "primaryKey": false, + "notNull": false, + "default": "gen_random_uuid()" + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "google_id": { + "name": "google_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "plan": { + "name": "plan", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "'free'" + }, + "stripe_customer_id": { + "name": "stripe_customer_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "polar_customer_id": { + "name": "polar_customer_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "qr_background": { + "name": "qr_background", + "type": "varchar(7)", + "primaryKey": false, + "notNull": true, + "default": "'#fff'" + }, + "qr_foreground": { + "name": "qr_foreground", + "type": "varchar(7)", + "primaryKey": false, + "notNull": true, + "default": "'#000'" + }, + "qr_corner_square_style": { + "name": "qr_corner_square_style", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "'square'" + }, + "qr_dot_style": { + "name": "qr_dot_style", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "'square'" + }, + "qr_image_base64": { + "name": "qr_image_base64", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "file_storage_usage_in_byte": { + "name": "file_storage_usage_in_byte", + "type": "bigint", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.visitor": { + "name": "visitor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "shortener_id": { + "name": "shortener_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "country_code": { + "name": "country_code", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "country": { + "name": "country", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "city": { + "name": "city", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "device_type": { + "name": "device_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "device_vendor": { + "name": "device_vendor", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "os": { + "name": "os", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "browser": { + "name": "browser", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "referer": { + "name": "referer", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "''" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/frontend/drizzle/meta/_journal.json b/frontend/drizzle/meta/_journal.json index c8d597b..7ecf101 100644 --- a/frontend/drizzle/meta/_journal.json +++ b/frontend/drizzle/meta/_journal.json @@ -204,6 +204,13 @@ "when": 1734847628427, "tag": "0028_hard_red_shift", "breakpoints": true + }, + { + "idx": 29, + "version": "7", + "when": 1739092508279, + "tag": "0029_chemical_wiccan", + "breakpoints": true } ] } \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 3b1ab8e..8e74db5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,7 +17,7 @@ }, "devDependencies": { "@sveltejs/adapter-node": "^2.0.0", - "@sveltejs/kit": "^2.5.27", + "@sveltejs/kit": "^2.17.1", "@sveltejs/vite-plugin-svelte": "^4.0.0", "@types/pg": "^8.11.6", "autoprefixer": "^10.4.14", @@ -29,7 +29,7 @@ "prettier": "^3.1.0", "prettier-plugin-svelte": "^3.2.6", "prettier-plugin-tailwindcss": "^0.5.7", - "svelte": "^5.0.0", + "svelte": "^5.19.9", "svelte-adapter-bun": "^0.5.1", "svelte-check": "^4.0.0", "tailwindcss": "^3.4.14", @@ -43,6 +43,8 @@ "@aws-sdk/client-s3": "^3.705.0", "@aws-sdk/s3-request-presigner": "^3.705.0", "@lucia-auth/adapter-drizzle": "^1.0.7", + "@polar-sh/sdk": "^0.25.0", + "@polar-sh/sveltekit": "^0.3.17", "@prgm/sveltekit-progress-bar": "^2.0.0", "@stripe/stripe-js": "^4.3.0", "@types/he": "^1.2.3", diff --git a/frontend/src/lib/components/nav-user.svelte b/frontend/src/lib/components/nav-user.svelte index 3e52f51..9ee753a 100644 --- a/frontend/src/lib/components/nav-user.svelte +++ b/frontend/src/lib/components/nav-user.svelte @@ -87,7 +87,9 @@ {#if !user.isPro} - + Upgrade to Pro diff --git a/frontend/src/lib/db/schema.ts b/frontend/src/lib/db/schema.ts index 23bbff9..75c0745 100644 --- a/frontend/src/lib/db/schema.ts +++ b/frontend/src/lib/db/schema.ts @@ -28,6 +28,7 @@ export const user = pgTable('user', { .$type<'free' | 'pro' | 'owner'>() .default('free'), stripeCustomerId: varchar('stripe_customer_id', { length: 255 }), + polarCustomerId: varchar('polar_customer_id', { length: 255 }), qrBackground: varchar('qr_background', { length: 7 }) .notNull() .default('#fff'), diff --git a/frontend/src/routes/(app)/dashboard/billing/+page.server.ts b/frontend/src/routes/(app)/dashboard/billing/+page.server.ts index 147210a..181287d 100644 --- a/frontend/src/routes/(app)/dashboard/billing/+page.server.ts +++ b/frontend/src/routes/(app)/dashboard/billing/+page.server.ts @@ -4,16 +4,20 @@ import { env } from '$env/dynamic/private' import { fail, setMessage, superValidate } from 'sveltekit-superforms' import { zod } from 'sveltekit-superforms/adapters' import { cancelSubscriptionSchema } from './schema' +import { Polar } from '@polar-sh/sdk' +import { redirect } from '@sveltejs/kit' export const load = (async () => { const breadcrumbs = [ { name: 'Billing', path: '/dashboard/billing' }, ] + return { breadcrumbs, cancel_subscription_form: await superValidate( zod(cancelSubscriptionSchema), ), + isPolar: env.PAYMENT_PROVIDER !== 'stripe', } }) satisfies PageServerLoad @@ -28,22 +32,25 @@ export const actions = { form, }) } - const stripe = new Stripe(env.PRIVATE_STRIPE_SECRET_KEY) + if (env.PAYMENT_PROVIDER === 'stripe') { + const stripe = new Stripe(env.PRIVATE_STRIPE_SECRET_KEY) - const user = event.locals.user + const user = event.locals.user - if (!user.stripeCustomerId) return { form } + if (!user.stripeCustomerId) return { form } - const subscription = await stripe.subscriptions.list({ - customer: user.stripeCustomerId, - price: env.PRIVATE_PRO_PLAN_PRICE_ID, - limit: 1, - }) + const subscription = await stripe.subscriptions.list({ + customer: user.stripeCustomerId, + price: env.PRIVATE_PRO_PLAN_PRICE_ID, + limit: 1, + }) - const cancelSubscription = await stripe.subscriptions.update( - subscription.data[0].id, - { cancel_at_period_end: true }, - ) + const cancelSubscription = await stripe.subscriptions.update( + subscription.data[0].id, + { cancel_at_period_end: true }, + ) + } else { + } setMessage(form, 'Successfully cancelled subsciption') return { form } diff --git a/frontend/src/routes/(app)/dashboard/billing/+page.svelte b/frontend/src/routes/(app)/dashboard/billing/+page.svelte index 96e77d1..eff7406 100644 --- a/frontend/src/routes/(app)/dashboard/billing/+page.svelte +++ b/frontend/src/routes/(app)/dashboard/billing/+page.svelte @@ -1,5 +1,4 @@