Compare commits

..

1 Commits

Author SHA1 Message Date
David Barroso
adfec57d63 feat(stripe-graphql-js): update dependencies and modernize build 2025-11-04 13:01:27 +01:00
182 changed files with 3378 additions and 2843 deletions

View File

@@ -32,11 +32,11 @@ Where `PKG` is:
- `deps`: For changes to dependencies
- `docs`: For changes to the documentation
- `examples`: For changes to the examples
- `internal/lib`: For changes to Nhost's common libraries (internal)
- `mintlify-openapi`: For changes to the Mintlify OpenAPI tool
- `nhost-js`: For changes to the Nhost JavaScript SDK
- `nixops`: For changes to the NixOps
- `storage`: For changes to the Nhost Storage service
- `stripe-graphql-js`: For changes to the Stripe GraphQL JS SDK
Where `SUMMARY` is a short description of what the PR does.

View File

@@ -17,7 +17,7 @@ runs:
# Define valid types and packages
VALID_TYPES="feat|fix|chore"
VALID_PKGS="auth|ci|cli|codegen|dashboard|deps|docs|examples|internal\/lib|mintlify-openapi|nhost-js|nixops|storage"
VALID_PKGS="auth|ci|cli|codegen|dashboard|deps|docs|examples|mintlify-openapi|nhost-js|nixops|storage|stripe-graphql-js"
# Check if title matches the pattern TYPE(PKG): SUMMARY
if [[ ! "$PR_TITLE" =~ ^(${VALID_TYPES})\((${VALID_PKGS})\):\ .+ ]]; then

View File

@@ -17,7 +17,6 @@ on:
- '.golangci.yaml'
- 'go.mod'
- 'go.sum'
- 'internal/lib/**'
- 'vendor/**'
# auth

View File

@@ -40,7 +40,7 @@ jobs:
cd ${{ matrix.project }}
TAG_NAME=$(make release-tag-name)
VERSION=$(nix develop .\#cliff -c make changelog-next-version)
if git tag | grep -qx "$TAG_NAME@$VERSION"; then
if git tag | grep -q "$TAG_NAME@$VERSION"; then
echo "Tag $TAG_NAME@$VERSION already exists, skipping release preparation"
else
echo "Tag $TAG_NAME@$VERSION does not exist, proceeding with release preparation"

View File

@@ -17,7 +17,6 @@ on:
- '.golangci.yaml'
- 'go.mod'
- 'go.sum'
- 'internal/lib/**'
- 'vendor/**'
# storage

View File

@@ -0,0 +1,18 @@
import { Context, createStripeGraphQLServer } from '@nhost/stripe-graphql-js';
const isAllowed = async (_stripeCustomerId: string, context: Context) => {
const { isAdmin } = context;
if (isAdmin) {
return true;
}
//TODO: Make sure the user can only access their own stripe customer id
return true;
};
process.env.NODE_ENVIRONMENT = 'development';
const server = createStripeGraphQLServer({ isAllowed });
export default server;

View File

@@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@nhost/stripe-graphql-js": "^1.3.0-beta.6",
"@swc/core": "^1.6.5",
"graphql-yoga": "^5.16.0",
"jsonwebtoken": "^9.0.2",
@@ -63,12 +64,12 @@
"license": "MIT"
},
"node_modules/@graphql-tools/executor": {
"version": "1.4.9",
"resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.4.9.tgz",
"integrity": "sha512-SAUlDT70JAvXeqV87gGzvDzUGofn39nvaVcVhNf12Dt+GfWHtNNO/RCn/Ea4VJaSLGzraUd41ObnN3i80EBU7w==",
"version": "1.4.10",
"resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.4.10.tgz",
"integrity": "sha512-/o7QScMdJpx/qIJlQcYs9ohB2qU2jSpuMyPStQy30kKTLHKyMETWpbljvRsuQxHJ2MJmEF3bYZgBHzdNAQHhug==",
"license": "MIT",
"dependencies": {
"@graphql-tools/utils": "^10.9.1",
"@graphql-tools/utils": "^10.10.0",
"@graphql-typed-document-node/core": "^3.2.0",
"@repeaterjs/repeater": "^3.0.4",
"@whatwg-node/disposablestack": "^0.0.6",
@@ -83,12 +84,12 @@
}
},
"node_modules/@graphql-tools/merge": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.1.1.tgz",
"integrity": "sha512-BJ5/7Y7GOhTuvzzO5tSBFL4NGr7PVqTJY3KeIDlVTT8YLcTXtBR+hlrC3uyEym7Ragn+zyWdHeJ9ev+nRX1X2w==",
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.1.2.tgz",
"integrity": "sha512-Ny9YhWKv+KxZFdXYt+wlyEW55GzhFiq4daV4wYgpP0aRbwQaczNJd1L3VjjBsPKjmW8lctZXUoqYTqU5QPcBGw==",
"license": "MIT",
"dependencies": {
"@graphql-tools/utils": "^10.9.1",
"@graphql-tools/utils": "^10.10.0",
"tslib": "^2.4.0"
},
"engines": {
@@ -99,13 +100,13 @@
}
},
"node_modules/@graphql-tools/schema": {
"version": "10.0.25",
"resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.25.tgz",
"integrity": "sha512-/PqE8US8kdQ7lB9M5+jlW8AyVjRGCKU7TSktuW3WNKSKmDO0MK1wakvb5gGdyT49MjAIb4a3LWxIpwo5VygZuw==",
"version": "10.0.26",
"resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.26.tgz",
"integrity": "sha512-KOmjuiWa9poP/Lza4HV0ZBPYGJI3VE3QzXA/8e0+wjcsRuEmxMLP82re1PUg0QRzp2UzifAB/gd7DoXmVGG9Fg==",
"license": "MIT",
"dependencies": {
"@graphql-tools/merge": "^9.1.1",
"@graphql-tools/utils": "^10.9.1",
"@graphql-tools/merge": "^9.1.2",
"@graphql-tools/utils": "^10.10.0",
"tslib": "^2.4.0"
},
"engines": {
@@ -116,9 +117,9 @@
}
},
"node_modules/@graphql-tools/utils": {
"version": "10.9.1",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.9.1.tgz",
"integrity": "sha512-B1wwkXk9UvU7LCBkPs8513WxOQ2H8Fo5p8HR1+Id9WmYE5+bd51vqN+MbrqvWczHCH2gwkREgHJN88tE0n1FCw==",
"version": "10.10.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.10.0.tgz",
"integrity": "sha512-OOeab5Y9qeKq0zfoJCSScMcDfGcIxp05+LW2xYVCS2l3su+K3lYcg5+cAAx9n0SFxpJl8zF5denq2QDsfM7NnQ==",
"license": "MIT",
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
@@ -183,6 +184,38 @@
"node": ">=18.0.0"
}
},
"node_modules/@nhost/stripe-graphql-js": {
"version": "1.3.0-beta.6",
"resolved": "https://registry.npmjs.org/@nhost/stripe-graphql-js/-/stripe-graphql-js-1.3.0-beta.6.tgz",
"integrity": "sha512-ImGZNn66UNelL+MtFyZOUB2djdBg9jbIMBRysdCeGgalbpQO/e4f5APcEiJKyZh0EESqpvnj9xSWYjdurEq3Rg==",
"license": "MIT",
"dependencies": {
"@pothos/core": "^3.41.0",
"graphql": "16.8.1",
"graphql-scalars": "^1.23.0",
"graphql-yoga": "^5.16.0",
"jsonwebtoken": "^9.0.2",
"stripe": "^11.18.0"
}
},
"node_modules/@nhost/stripe-graphql-js/node_modules/graphql": {
"version": "16.8.1",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz",
"integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==",
"license": "MIT",
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
},
"node_modules/@pothos/core": {
"version": "3.41.2",
"resolved": "https://registry.npmjs.org/@pothos/core/-/core-3.41.2.tgz",
"integrity": "sha512-iR1gqd93IyD/snTW47HwKSsRCrvnJaYwjVNcUG8BztZPqMxyJKPAnjPHAgu1XB82KEdysrNqIUnXqnzZIs08QA==",
"license": "ISC",
"peerDependencies": {
"graphql": ">=15.1.0"
}
},
"node_modules/@repeaterjs/repeater": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz",
@@ -190,14 +223,14 @@
"license": "MIT"
},
"node_modules/@swc/core": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.9.2.tgz",
"integrity": "sha512-dYyEkO6mRYtZFpnOsnYzv9rY69fHAHoawYOjGOEcxk9WYtaJhowMdP/w6NcOKnz2G7GlZaenjkzkMa6ZeQeMsg==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.0.tgz",
"integrity": "sha512-8SnJV+JV0rYbfSiEiUvYOmf62E7QwsEG+aZueqSlKoxFt0pw333+bgZSQXGUV6etXU88nxur0afVMaINujBMSw==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@swc/counter": "^0.1.3",
"@swc/types": "^0.1.15"
"@swc/types": "^0.1.25"
},
"engines": {
"node": ">=10"
@@ -207,19 +240,19 @@
"url": "https://opencollective.com/swc"
},
"optionalDependencies": {
"@swc/core-darwin-arm64": "1.9.2",
"@swc/core-darwin-x64": "1.9.2",
"@swc/core-linux-arm-gnueabihf": "1.9.2",
"@swc/core-linux-arm64-gnu": "1.9.2",
"@swc/core-linux-arm64-musl": "1.9.2",
"@swc/core-linux-x64-gnu": "1.9.2",
"@swc/core-linux-x64-musl": "1.9.2",
"@swc/core-win32-arm64-msvc": "1.9.2",
"@swc/core-win32-ia32-msvc": "1.9.2",
"@swc/core-win32-x64-msvc": "1.9.2"
"@swc/core-darwin-arm64": "1.15.0",
"@swc/core-darwin-x64": "1.15.0",
"@swc/core-linux-arm-gnueabihf": "1.15.0",
"@swc/core-linux-arm64-gnu": "1.15.0",
"@swc/core-linux-arm64-musl": "1.15.0",
"@swc/core-linux-x64-gnu": "1.15.0",
"@swc/core-linux-x64-musl": "1.15.0",
"@swc/core-win32-arm64-msvc": "1.15.0",
"@swc/core-win32-ia32-msvc": "1.15.0",
"@swc/core-win32-x64-msvc": "1.15.0"
},
"peerDependencies": {
"@swc/helpers": "*"
"@swc/helpers": ">=0.5.17"
},
"peerDependenciesMeta": {
"@swc/helpers": {
@@ -228,9 +261,9 @@
}
},
"node_modules/@swc/core-darwin-arm64": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.9.2.tgz",
"integrity": "sha512-nETmsCoY29krTF2PtspEgicb3tqw7Ci5sInTI03EU5zpqYbPjoPH99BVTjj0OsF53jP5MxwnLI5Hm21lUn1d6A==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.0.tgz",
"integrity": "sha512-TBKWkbnShnEjlIbO4/gfsrIgAqHBVqgPWLbWmPdZ80bF393yJcLgkrb7bZEnJs6FCbSSuGwZv2rx1jDR2zo6YA==",
"cpu": [
"arm64"
],
@@ -244,9 +277,9 @@
}
},
"node_modules/@swc/core-darwin-x64": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.9.2.tgz",
"integrity": "sha512-9gD+bwBz8ZByjP6nZTXe/hzd0tySIAjpDHgkFiUrc+5zGF+rdTwhcNrzxNHJmy6mw+PW38jqII4uspFHUqqxuQ==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.0.tgz",
"integrity": "sha512-f5JKL1v1H56CIZc1pVn4RGPOfnWqPwmuHdpf4wesvXunF1Bx85YgcspW5YxwqG5J9g3nPU610UFuExJXVUzOiQ==",
"cpu": [
"x64"
],
@@ -260,9 +293,9 @@
}
},
"node_modules/@swc/core-linux-arm-gnueabihf": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.9.2.tgz",
"integrity": "sha512-kYq8ief1Qrn+WmsTWAYo4r+Coul4dXN6cLFjiPZ29Cv5pyU+GFvSPAB4bEdMzwy99rCR0u2P10UExaeCjurjvg==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.0.tgz",
"integrity": "sha512-duK6nG+WyuunnfsfiTUQdzC9Fk8cyDLqT9zyXvY2i2YgDu5+BH5W6wM5O4mDNCU5MocyB/SuF5YDF7XySnowiQ==",
"cpu": [
"arm"
],
@@ -276,9 +309,9 @@
}
},
"node_modules/@swc/core-linux-arm64-gnu": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.9.2.tgz",
"integrity": "sha512-n0W4XiXlmEIVqxt+rD3ZpkogsEWUk1jJ+i5bQNgB+1JuWh0fBE8c/blDgTQXa0GB5lTPVDZQussgdNOCnAZwiA==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.0.tgz",
"integrity": "sha512-ITe9iDtTRXM98B91rvyPP6qDVbhUBnmA/j4UxrHlMQ0RlwpqTjfZYZkD0uclOxSZ6qIrOj/X5CaoJlDUuQ0+Cw==",
"cpu": [
"arm64"
],
@@ -292,9 +325,9 @@
}
},
"node_modules/@swc/core-linux-arm64-musl": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.9.2.tgz",
"integrity": "sha512-8xzrOmsyCC1zrx2Wzx/h8dVsdewO1oMCwBTLc1gSJ/YllZYTb04pNm6NsVbzUX2tKddJVRgSJXV10j/NECLwpA==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.0.tgz",
"integrity": "sha512-Q5ldc2bzriuzYEoAuqJ9Vr3FyZhakk5hiwDbniZ8tlEXpbjBhbOleGf9/gkhLaouDnkNUEazFW9mtqwUTRdh7Q==",
"cpu": [
"arm64"
],
@@ -308,9 +341,9 @@
}
},
"node_modules/@swc/core-linux-x64-gnu": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.9.2.tgz",
"integrity": "sha512-kZrNz/PjRQKcchWF6W292jk3K44EoVu1ad5w+zbS4jekIAxsM8WwQ1kd+yjUlN9jFcF8XBat5NKIs9WphJCVXg==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.0.tgz",
"integrity": "sha512-pY4is+jEpOxlYCSnI+7N8Oxbap9TmTz5YT84tUvRTlOlTBwFAUlWFCX0FRwWJlsfP0TxbqhIe8dNNzlsEmJbXQ==",
"cpu": [
"x64"
],
@@ -324,9 +357,9 @@
}
},
"node_modules/@swc/core-linux-x64-musl": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.9.2.tgz",
"integrity": "sha512-TTIpR4rjMkhX1lnFR+PSXpaL83TrQzp9znRdp2TzYrODlUd/R20zOwSo9vFLCyH6ZoD47bccY7QeGZDYT3nlRg==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.0.tgz",
"integrity": "sha512-zYEt5eT8y8RUpoe7t5pjpoOdGu+/gSTExj8PV86efhj6ugB3bPlj3Y85ogdW3WMVXr4NvwqvzdaYGCZfXzSyVg==",
"cpu": [
"x64"
],
@@ -340,9 +373,9 @@
}
},
"node_modules/@swc/core-win32-arm64-msvc": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.9.2.tgz",
"integrity": "sha512-+Eg2d4icItKC0PMjZxH7cSYFLWk0aIp94LNmOw6tPq0e69ax6oh10upeq0D1fjWsKLmOJAWEvnXlayZcijEXDw==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.0.tgz",
"integrity": "sha512-zC1rmOgFH5v2BCbByOazEqs0aRNpTdLRchDExfcCfgKgeaD+IdpUOqp7i3VG1YzkcnbuZjMlXfM0ugpt+CddoA==",
"cpu": [
"arm64"
],
@@ -356,9 +389,9 @@
}
},
"node_modules/@swc/core-win32-ia32-msvc": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.9.2.tgz",
"integrity": "sha512-nLWBi4vZDdM/LkiQmPCakof8Dh1/t5EM7eudue04V1lIcqx9YHVRS3KMwEaCoHLGg0c312Wm4YgrWQd9vwZ5zQ==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.0.tgz",
"integrity": "sha512-7t9U9KwMwQblkdJIH+zX1V4q1o3o41i0HNO+VlnAHT5o+5qHJ963PHKJ/pX3P2UlZnBCY465orJuflAN4rAP9A==",
"cpu": [
"ia32"
],
@@ -372,9 +405,9 @@
}
},
"node_modules/@swc/core-win32-x64-msvc": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.9.2.tgz",
"integrity": "sha512-ik/k+JjRJBFkXARukdU82tSVx0CbExFQoQ78qTO682esbYXzjdB5eLVkoUbwen299pnfr88Kn4kyIqFPTje8Xw==",
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.0.tgz",
"integrity": "sha512-VE0Zod5vcs8iMLT64m5QS1DlTMXJFI/qSgtMDRx8rtZrnjt6/9NW8XUaiPJuRu8GluEO1hmHoyf1qlbY19gGSQ==",
"cpu": [
"x64"
],
@@ -394,18 +427,18 @@
"license": "Apache-2.0"
},
"node_modules/@swc/types": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.15.tgz",
"integrity": "sha512-XKaZ+dzDIQ9Ot9o89oJQ/aluI17+VvUnIpYJTcZtvv1iYX6MzHh3Ik2CSR7MdPKpPwfZXHBeCingb2b4PoDVdw==",
"version": "0.1.25",
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz",
"integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==",
"license": "Apache-2.0",
"dependencies": {
"@swc/counter": "^0.1.3"
}
},
"node_modules/@types/body-parser": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
"integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
"version": "1.19.6",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
"integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
"license": "MIT",
"dependencies": {
"@types/connect": "*",
@@ -422,21 +455,21 @@
}
},
"node_modules/@types/express": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
"version": "4.17.25",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
"integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
"license": "MIT",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.33",
"@types/qs": "*",
"@types/serve-static": "*"
"@types/serve-static": "^1"
}
},
"node_modules/@types/express-serve-static-core": {
"version": "4.19.6",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz",
"integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==",
"version": "4.19.7",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz",
"integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==",
"license": "MIT",
"dependencies": {
"@types/node": "*",
@@ -446,17 +479,18 @@
}
},
"node_modules/@types/http-errors": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
"integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
"integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
"license": "MIT"
},
"node_modules/@types/jsonwebtoken": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz",
"integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==",
"version": "9.0.10",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
"integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==",
"license": "MIT",
"dependencies": {
"@types/ms": "*",
"@types/node": "*"
}
},
@@ -466,19 +500,25 @@
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
"license": "MIT"
},
"node_modules/@types/ms": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.9.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz",
"integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==",
"version": "24.10.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz",
"integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.8"
"undici-types": "~7.16.0"
}
},
"node_modules/@types/qs": {
"version": "6.9.17",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz",
"integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==",
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
"license": "MIT"
},
"node_modules/@types/range-parser": {
@@ -488,24 +528,33 @@
"license": "MIT"
},
"node_modules/@types/send": {
"version": "0.17.4",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
"integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
"integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
"license": "MIT",
"dependencies": {
"@types/mime": "^1",
"@types/node": "*"
}
},
"node_modules/@types/serve-static": {
"version": "1.15.7",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
"integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
"version": "1.15.10",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
"integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==",
"license": "MIT",
"dependencies": {
"@types/http-errors": "*",
"@types/node": "*",
"@types/send": "*"
"@types/send": "<1"
}
},
"node_modules/@types/serve-static/node_modules/@types/send": {
"version": "0.17.6",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
"integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==",
"license": "MIT",
"dependencies": {
"@types/mime": "^1",
"@types/node": "*"
}
},
"node_modules/@whatwg-node/disposablestack": {
@@ -547,9 +596,9 @@
}
},
"node_modules/@whatwg-node/node-fetch": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.8.0.tgz",
"integrity": "sha512-+z00GpWxKV/q8eMETwbdi80TcOoVEVZ4xSRkxYOZpn3kbV3nej5iViNzXVke/j3v4y1YpO5zMS/CVDIASvJnZQ==",
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.8.1.tgz",
"integrity": "sha512-cQmQEo7IsI0EPX9VrwygXVzrVlX43Jb7/DBZSmpnC7xH4xkyOnn/HykHpTaQk7TUs7zh59A5uTGqx3p2Ouzffw==",
"license": "MIT",
"dependencies": {
"@fastify/busboy": "^3.1.1",
@@ -574,9 +623,9 @@
}
},
"node_modules/@whatwg-node/server": {
"version": "0.10.12",
"resolved": "https://registry.npmjs.org/@whatwg-node/server/-/server-0.10.12.tgz",
"integrity": "sha512-MQIvvQyPvKGna586MzXhgwnEbGtbm7QtOgJ/KPd/tC70M/jbhd1xHdIQQbh3okBw+MrDF/EvaC2vB5oRC7QdlQ==",
"version": "0.10.13",
"resolved": "https://registry.npmjs.org/@whatwg-node/server/-/server-0.10.13.tgz",
"integrity": "sha512-Otmxo+0mp8az3B48pLI1I4msNOXPIoP7TLm6h5wOEQmynqHt8oP9nR6NJUeJk6iI5OtFpQtkbJFwfGkmplvc3Q==",
"license": "MIT",
"dependencies": {
"@envelop/instrumentation": "^1.0.0",
@@ -595,6 +644,35 @@
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
"license": "BSD-3-Clause"
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/cross-inspect": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.1.tgz",
@@ -608,9 +686,9 @@
}
},
"node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -633,6 +711,20 @@
"node": ">=4"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
@@ -642,16 +734,119 @@
"safe-buffer": "^5.0.1"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/graphql": {
"version": "16.11.0",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz",
"integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==",
"version": "16.12.0",
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz",
"integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==",
"license": "MIT",
"peer": true,
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
},
"node_modules/graphql-scalars": {
"version": "1.25.0",
"resolved": "https://registry.npmjs.org/graphql-scalars/-/graphql-scalars-1.25.0.tgz",
"integrity": "sha512-b0xyXZeRFkne4Eq7NAnL400gStGqG/Sx9VqX0A05nHyEbv57UJnWKsjNnrpVqv5e/8N1MUxkt0wwcRXbiyKcFg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.5.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/graphql-yoga": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/graphql-yoga/-/graphql-yoga-5.16.0.tgz",
@@ -679,11 +874,29 @@
"graphql": "^15.2.0 || ^16.0.0"
}
},
"node_modules/graphql-yoga/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/jose": {
"version": "4.15.9",
@@ -717,26 +930,26 @@
}
},
"node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
"integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
"license": "MIT",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"buffer-equal-constant-time": "^1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jwks-rsa": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.1.0.tgz",
"integrity": "sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.2.0.tgz",
"integrity": "sha512-PwchfHcQK/5PSydeKCs1ylNym0w/SSv8a62DgHJ//7x2ZclCoinlsjAfDxAAbpoTPybOum/Jgy+vkvMmKz89Ww==",
"license": "MIT",
"dependencies": {
"@types/express": "^4.17.17",
"@types/jsonwebtoken": "^9.0.2",
"@types/express": "^4.17.20",
"@types/jsonwebtoken": "^9.0.4",
"debug": "^4.3.4",
"jose": "^4.14.6",
"jose": "^4.15.4",
"limiter": "^1.1.5",
"lru-memoizer": "^2.2.0"
},
@@ -808,16 +1021,10 @@
"license": "MIT"
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
"node_modules/lru-memoizer": {
"version": "2.3.0",
@@ -829,12 +1036,60 @@
"lru-cache": "6.0.0"
}
},
"node_modules/lru-memoizer/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -856,9 +1111,9 @@
"license": "MIT"
},
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -867,6 +1122,91 @@
"node": ">=10"
}
},
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-list": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/stripe": {
"version": "11.18.0",
"resolved": "https://registry.npmjs.org/stripe/-/stripe-11.18.0.tgz",
"integrity": "sha512-OUA32uhNoSoM6wOodyFbV+3IBCoO140uzdXmBArQ0S88D4EbH91xl2v+Ml1sKalcFKUBadHLeHfU/p9AbsOfGw==",
"license": "MIT",
"dependencies": {
"@types/node": ">=8.1.0",
"qs": "^6.11.0"
},
"engines": {
"node": ">=12.*"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -874,9 +1214,9 @@
"license": "0BSD"
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"license": "MIT"
},
"node_modules/urlpattern-polyfill": {

View File

@@ -10,6 +10,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"@nhost/stripe-graphql-js": "^1.3.0-beta.6",
"@swc/core": "^1.6.5",
"graphql-yoga": "^5.16.0",
"jsonwebtoken": "^9.0.2",

View File

@@ -1,653 +0,0 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@swc/core':
specifier: ^1.6.5
version: 1.6.5
graphql-yoga:
specifier: ^5.16.0
version: 5.16.0(graphql@16.11.0)
jsonwebtoken:
specifier: ^9.0.2
version: 9.0.2
jwks-rsa:
specifier: ^3.1.0
version: 3.1.0
packages:
'@envelop/core@5.3.2':
resolution: {integrity: sha512-06Mu7fmyKzk09P2i2kHpGfItqLLgCq7uO5/nX4fc/iHMplWPNuAx4iYR+WXUQoFHDnP6EUbceQNQ5iyeMz9f3g==}
engines: {node: '>=18.0.0'}
'@envelop/instrumentation@1.0.0':
resolution: {integrity: sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==}
engines: {node: '>=18.0.0'}
'@envelop/types@5.2.1':
resolution: {integrity: sha512-CsFmA3u3c2QoLDTfEpGr4t25fjMU31nyvse7IzWTvb0ZycuPjMjb0fjlheh+PbhBYb9YLugnT2uY6Mwcg1o+Zg==}
engines: {node: '>=18.0.0'}
'@fastify/busboy@3.2.0':
resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==}
'@graphql-tools/executor@1.4.9':
resolution: {integrity: sha512-SAUlDT70JAvXeqV87gGzvDzUGofn39nvaVcVhNf12Dt+GfWHtNNO/RCn/Ea4VJaSLGzraUd41ObnN3i80EBU7w==}
engines: {node: '>=16.0.0'}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
'@graphql-tools/merge@9.1.1':
resolution: {integrity: sha512-BJ5/7Y7GOhTuvzzO5tSBFL4NGr7PVqTJY3KeIDlVTT8YLcTXtBR+hlrC3uyEym7Ragn+zyWdHeJ9ev+nRX1X2w==}
engines: {node: '>=16.0.0'}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
'@graphql-tools/schema@10.0.25':
resolution: {integrity: sha512-/PqE8US8kdQ7lB9M5+jlW8AyVjRGCKU7TSktuW3WNKSKmDO0MK1wakvb5gGdyT49MjAIb4a3LWxIpwo5VygZuw==}
engines: {node: '>=16.0.0'}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
'@graphql-tools/utils@10.9.1':
resolution: {integrity: sha512-B1wwkXk9UvU7LCBkPs8513WxOQ2H8Fo5p8HR1+Id9WmYE5+bd51vqN+MbrqvWczHCH2gwkREgHJN88tE0n1FCw==}
engines: {node: '>=16.0.0'}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
'@graphql-typed-document-node/core@3.2.0':
resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
'@graphql-yoga/logger@2.0.1':
resolution: {integrity: sha512-Nv0BoDGLMg9QBKy9cIswQ3/6aKaKjlTh87x3GiBg2Z4RrjyrM48DvOOK0pJh1C1At+b0mUIM67cwZcFTDLN4sA==}
engines: {node: '>=18.0.0'}
'@graphql-yoga/subscription@5.0.5':
resolution: {integrity: sha512-oCMWOqFs6QV96/NZRt/ZhTQvzjkGB4YohBOpKM4jH/lDT4qb7Lex/aGCxpi/JD9njw3zBBtMqxbaC22+tFHVvw==}
engines: {node: '>=18.0.0'}
'@graphql-yoga/typed-event-target@3.0.2':
resolution: {integrity: sha512-ZpJxMqB+Qfe3rp6uszCQoag4nSw42icURnBRfFYSOmTgEeOe4rD0vYlbA8spvCu2TlCesNTlEN9BLWtQqLxabA==}
engines: {node: '>=18.0.0'}
'@repeaterjs/repeater@3.0.6':
resolution: {integrity: sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==}
'@swc/core-darwin-arm64@1.6.5':
resolution: {integrity: sha512-RGQhMdni2v1/ANQ/2K+F+QYdzaucekYBewZcX1ogqJ8G5sbPaBdYdDN1qQ4kHLCIkPtGP6qC7c71qPEqL2RidQ==}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
'@swc/core-darwin-x64@1.6.5':
resolution: {integrity: sha512-/pSN0/Jtcbbb9+ovS9rKxR3qertpFAM3OEJr/+Dh/8yy7jK5G5EFPIrfsw/7Q5987ERPIJIH6BspK2CBB2tgcg==}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
'@swc/core-linux-arm-gnueabihf@1.6.5':
resolution: {integrity: sha512-B0g/dROCE747RRegs/jPHuKJgwXLracDhnqQa80kFdgWEMjlcb7OMCgs5OX86yJGRS4qcYbiMGD0Pp7Kbqn3yw==}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
'@swc/core-linux-arm64-gnu@1.6.5':
resolution: {integrity: sha512-W8meapgXTq8AOtSvDG4yKR8ant2WWD++yOjgzAleB5VAC+oC+aa8YJROGxj8HepurU8kurqzcialwoMeq5SZZQ==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
'@swc/core-linux-arm64-musl@1.6.5':
resolution: {integrity: sha512-jyCKqoX50Fg8rJUQqh4u5PqnE7nqYKXHjVH2WcYr114/MU21zlsI+YL6aOQU1XP8bJQ2gPQ1rnlnGJdEHiKS/w==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
'@swc/core-linux-x64-gnu@1.6.5':
resolution: {integrity: sha512-G6HmUn/RRIlXC0YYFfBz2qh6OZkHS/KUPkhoG4X9ADcgWXXjOFh6JrefwsYj8VBAJEnr5iewzjNfj+nztwHaeA==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
'@swc/core-linux-x64-musl@1.6.5':
resolution: {integrity: sha512-AQpBjBnelQDSbeTJA50AXdS6+CP66LsXIMNTwhPSgUfE7Bx1ggZV11Fsi4Q5SGcs6a8Qw1cuYKN57ZfZC5QOuA==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
'@swc/core-win32-arm64-msvc@1.6.5':
resolution: {integrity: sha512-MZTWM8kUwS30pVrtbzSGEXtek46aXNb/mT9D6rsS7NvOuv2w+qZhjR1rzf4LNbbn5f8VnR4Nac1WIOYZmfC5ng==}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
'@swc/core-win32-ia32-msvc@1.6.5':
resolution: {integrity: sha512-WZdu4gISAr3yOm1fVwKhhk6+MrP7kVX0KMP7+ZQFTN5zXQEiDSDunEJKVgjMVj3vlR+6mnAqa/L0V9Qa8+zKlQ==}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
'@swc/core-win32-x64-msvc@1.6.5':
resolution: {integrity: sha512-ezXgucnMTzlFIxQZw7ls/5r2hseFaRoDL04cuXUOs97E8r+nJSmFsRQm/ygH5jBeXNo59nyZCalrjJAjwfgACA==}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
'@swc/core@1.6.5':
resolution: {integrity: sha512-tyVvUK/HDOUUsK6/GmWvnqUtD9oDpPUA4f7f7JCOV8hXxtfjMtAZeBKf93yrB1XZet69TDR7EN0hFC6i4MF0Ig==}
engines: {node: '>=10'}
peerDependencies:
'@swc/helpers': '*'
peerDependenciesMeta:
'@swc/helpers':
optional: true
'@swc/counter@0.1.3':
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
'@swc/types@0.1.9':
resolution: {integrity: sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg==}
'@types/body-parser@1.19.5':
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
'@types/connect@3.4.38':
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
'@types/express-serve-static-core@4.19.6':
resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==}
'@types/express@4.17.21':
resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
'@types/http-errors@2.0.4':
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
'@types/jsonwebtoken@9.0.7':
resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==}
'@types/mime@1.3.5':
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
'@types/node@22.9.0':
resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==}
'@types/qs@6.9.17':
resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==}
'@types/range-parser@1.2.7':
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
'@types/send@0.17.4':
resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
'@types/serve-static@1.15.7':
resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
'@whatwg-node/disposablestack@0.0.6':
resolution: {integrity: sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==}
engines: {node: '>=18.0.0'}
'@whatwg-node/events@0.1.2':
resolution: {integrity: sha512-ApcWxkrs1WmEMS2CaLLFUEem/49erT3sxIVjpzU5f6zmVcnijtDSrhoK2zVobOIikZJdH63jdAXOrvjf6eOUNQ==}
engines: {node: '>=18.0.0'}
'@whatwg-node/fetch@0.10.11':
resolution: {integrity: sha512-eR8SYtf9Nem1Tnl0IWrY33qJ5wCtIWlt3Fs3c6V4aAaTFLtkEQErXu3SSZg/XCHrj9hXSJ8/8t+CdMk5Qec/ZA==}
engines: {node: '>=18.0.0'}
'@whatwg-node/node-fetch@0.8.0':
resolution: {integrity: sha512-+z00GpWxKV/q8eMETwbdi80TcOoVEVZ4xSRkxYOZpn3kbV3nej5iViNzXVke/j3v4y1YpO5zMS/CVDIASvJnZQ==}
engines: {node: '>=18.0.0'}
'@whatwg-node/promise-helpers@1.3.2':
resolution: {integrity: sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==}
engines: {node: '>=16.0.0'}
'@whatwg-node/server@0.10.12':
resolution: {integrity: sha512-MQIvvQyPvKGna586MzXhgwnEbGtbm7QtOgJ/KPd/tC70M/jbhd1xHdIQQbh3okBw+MrDF/EvaC2vB5oRC7QdlQ==}
engines: {node: '>=18.0.0'}
buffer-equal-constant-time@1.0.1:
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
cross-inspect@1.0.1:
resolution: {integrity: sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==}
engines: {node: '>=16.0.0'}
debug@4.3.7:
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dset@3.1.4:
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
engines: {node: '>=4'}
ecdsa-sig-formatter@1.0.11:
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
graphql-yoga@5.16.0:
resolution: {integrity: sha512-/R2dJea7WgvNlXRU4F8iFwWd95Qn1mN+R+yC8XBs1wKjUzr0Pvv8cGYtt6UUcVHw5CiDEtu7iQY5oOe3sDAWCQ==}
engines: {node: '>=18.0.0'}
peerDependencies:
graphql: ^15.2.0 || ^16.0.0
graphql@16.11.0:
resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==}
engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
jose@4.15.9:
resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==}
jsonwebtoken@9.0.2:
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
engines: {node: '>=12', npm: '>=6'}
jwa@1.4.1:
resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
jwks-rsa@3.1.0:
resolution: {integrity: sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==}
engines: {node: '>=14'}
jws@3.2.2:
resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
limiter@1.1.5:
resolution: {integrity: sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==}
lodash.clonedeep@4.5.0:
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
lodash.includes@4.3.0:
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
lodash.isboolean@3.0.3:
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
lodash.isinteger@4.0.4:
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
lodash.isnumber@3.0.3:
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
lodash.isstring@4.0.1:
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
lodash.once@4.1.1:
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
lru-memoizer@2.3.0:
resolution: {integrity: sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
semver@7.6.3:
resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
engines: {node: '>=10'}
hasBin: true
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
undici-types@6.19.8:
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
urlpattern-polyfill@10.1.0:
resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==}
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
snapshots:
'@envelop/core@5.3.2':
dependencies:
'@envelop/instrumentation': 1.0.0
'@envelop/types': 5.2.1
'@whatwg-node/promise-helpers': 1.3.2
tslib: 2.8.1
'@envelop/instrumentation@1.0.0':
dependencies:
'@whatwg-node/promise-helpers': 1.3.2
tslib: 2.8.1
'@envelop/types@5.2.1':
dependencies:
'@whatwg-node/promise-helpers': 1.3.2
tslib: 2.8.1
'@fastify/busboy@3.2.0': {}
'@graphql-tools/executor@1.4.9(graphql@16.11.0)':
dependencies:
'@graphql-tools/utils': 10.9.1(graphql@16.11.0)
'@graphql-typed-document-node/core': 3.2.0(graphql@16.11.0)
'@repeaterjs/repeater': 3.0.6
'@whatwg-node/disposablestack': 0.0.6
'@whatwg-node/promise-helpers': 1.3.2
graphql: 16.11.0
tslib: 2.8.1
'@graphql-tools/merge@9.1.1(graphql@16.11.0)':
dependencies:
'@graphql-tools/utils': 10.9.1(graphql@16.11.0)
graphql: 16.11.0
tslib: 2.8.1
'@graphql-tools/schema@10.0.25(graphql@16.11.0)':
dependencies:
'@graphql-tools/merge': 9.1.1(graphql@16.11.0)
'@graphql-tools/utils': 10.9.1(graphql@16.11.0)
graphql: 16.11.0
tslib: 2.8.1
'@graphql-tools/utils@10.9.1(graphql@16.11.0)':
dependencies:
'@graphql-typed-document-node/core': 3.2.0(graphql@16.11.0)
'@whatwg-node/promise-helpers': 1.3.2
cross-inspect: 1.0.1
dset: 3.1.4
graphql: 16.11.0
tslib: 2.8.1
'@graphql-typed-document-node/core@3.2.0(graphql@16.11.0)':
dependencies:
graphql: 16.11.0
'@graphql-yoga/logger@2.0.1':
dependencies:
tslib: 2.8.1
'@graphql-yoga/subscription@5.0.5':
dependencies:
'@graphql-yoga/typed-event-target': 3.0.2
'@repeaterjs/repeater': 3.0.6
'@whatwg-node/events': 0.1.2
tslib: 2.8.1
'@graphql-yoga/typed-event-target@3.0.2':
dependencies:
'@repeaterjs/repeater': 3.0.6
tslib: 2.8.1
'@repeaterjs/repeater@3.0.6': {}
'@swc/core-darwin-arm64@1.6.5':
optional: true
'@swc/core-darwin-x64@1.6.5':
optional: true
'@swc/core-linux-arm-gnueabihf@1.6.5':
optional: true
'@swc/core-linux-arm64-gnu@1.6.5':
optional: true
'@swc/core-linux-arm64-musl@1.6.5':
optional: true
'@swc/core-linux-x64-gnu@1.6.5':
optional: true
'@swc/core-linux-x64-musl@1.6.5':
optional: true
'@swc/core-win32-arm64-msvc@1.6.5':
optional: true
'@swc/core-win32-ia32-msvc@1.6.5':
optional: true
'@swc/core-win32-x64-msvc@1.6.5':
optional: true
'@swc/core@1.6.5':
dependencies:
'@swc/counter': 0.1.3
'@swc/types': 0.1.9
optionalDependencies:
'@swc/core-darwin-arm64': 1.6.5
'@swc/core-darwin-x64': 1.6.5
'@swc/core-linux-arm-gnueabihf': 1.6.5
'@swc/core-linux-arm64-gnu': 1.6.5
'@swc/core-linux-arm64-musl': 1.6.5
'@swc/core-linux-x64-gnu': 1.6.5
'@swc/core-linux-x64-musl': 1.6.5
'@swc/core-win32-arm64-msvc': 1.6.5
'@swc/core-win32-ia32-msvc': 1.6.5
'@swc/core-win32-x64-msvc': 1.6.5
'@swc/counter@0.1.3': {}
'@swc/types@0.1.9':
dependencies:
'@swc/counter': 0.1.3
'@types/body-parser@1.19.5':
dependencies:
'@types/connect': 3.4.38
'@types/node': 22.9.0
'@types/connect@3.4.38':
dependencies:
'@types/node': 22.9.0
'@types/express-serve-static-core@4.19.6':
dependencies:
'@types/node': 22.9.0
'@types/qs': 6.9.17
'@types/range-parser': 1.2.7
'@types/send': 0.17.4
'@types/express@4.17.21':
dependencies:
'@types/body-parser': 1.19.5
'@types/express-serve-static-core': 4.19.6
'@types/qs': 6.9.17
'@types/serve-static': 1.15.7
'@types/http-errors@2.0.4': {}
'@types/jsonwebtoken@9.0.7':
dependencies:
'@types/node': 22.9.0
'@types/mime@1.3.5': {}
'@types/node@22.9.0':
dependencies:
undici-types: 6.19.8
'@types/qs@6.9.17': {}
'@types/range-parser@1.2.7': {}
'@types/send@0.17.4':
dependencies:
'@types/mime': 1.3.5
'@types/node': 22.9.0
'@types/serve-static@1.15.7':
dependencies:
'@types/http-errors': 2.0.4
'@types/node': 22.9.0
'@types/send': 0.17.4
'@whatwg-node/disposablestack@0.0.6':
dependencies:
'@whatwg-node/promise-helpers': 1.3.2
tslib: 2.8.1
'@whatwg-node/events@0.1.2':
dependencies:
tslib: 2.8.1
'@whatwg-node/fetch@0.10.11':
dependencies:
'@whatwg-node/node-fetch': 0.8.0
urlpattern-polyfill: 10.1.0
'@whatwg-node/node-fetch@0.8.0':
dependencies:
'@fastify/busboy': 3.2.0
'@whatwg-node/disposablestack': 0.0.6
'@whatwg-node/promise-helpers': 1.3.2
tslib: 2.8.1
'@whatwg-node/promise-helpers@1.3.2':
dependencies:
tslib: 2.8.1
'@whatwg-node/server@0.10.12':
dependencies:
'@envelop/instrumentation': 1.0.0
'@whatwg-node/disposablestack': 0.0.6
'@whatwg-node/fetch': 0.10.11
'@whatwg-node/promise-helpers': 1.3.2
tslib: 2.8.1
buffer-equal-constant-time@1.0.1: {}
cross-inspect@1.0.1:
dependencies:
tslib: 2.8.1
debug@4.3.7:
dependencies:
ms: 2.1.3
dset@3.1.4: {}
ecdsa-sig-formatter@1.0.11:
dependencies:
safe-buffer: 5.2.1
graphql-yoga@5.16.0(graphql@16.11.0):
dependencies:
'@envelop/core': 5.3.2
'@envelop/instrumentation': 1.0.0
'@graphql-tools/executor': 1.4.9(graphql@16.11.0)
'@graphql-tools/schema': 10.0.25(graphql@16.11.0)
'@graphql-tools/utils': 10.9.1(graphql@16.11.0)
'@graphql-yoga/logger': 2.0.1
'@graphql-yoga/subscription': 5.0.5
'@whatwg-node/fetch': 0.10.11
'@whatwg-node/promise-helpers': 1.3.2
'@whatwg-node/server': 0.10.12
dset: 3.1.4
graphql: 16.11.0
lru-cache: 10.4.3
tslib: 2.8.1
graphql@16.11.0: {}
jose@4.15.9: {}
jsonwebtoken@9.0.2:
dependencies:
jws: 3.2.2
lodash.includes: 4.3.0
lodash.isboolean: 3.0.3
lodash.isinteger: 4.0.4
lodash.isnumber: 3.0.3
lodash.isplainobject: 4.0.6
lodash.isstring: 4.0.1
lodash.once: 4.1.1
ms: 2.1.3
semver: 7.6.3
jwa@1.4.1:
dependencies:
buffer-equal-constant-time: 1.0.1
ecdsa-sig-formatter: 1.0.11
safe-buffer: 5.2.1
jwks-rsa@3.1.0:
dependencies:
'@types/express': 4.17.21
'@types/jsonwebtoken': 9.0.7
debug: 4.3.7
jose: 4.15.9
limiter: 1.1.5
lru-memoizer: 2.3.0
transitivePeerDependencies:
- supports-color
jws@3.2.2:
dependencies:
jwa: 1.4.1
safe-buffer: 5.2.1
limiter@1.1.5: {}
lodash.clonedeep@4.5.0: {}
lodash.includes@4.3.0: {}
lodash.isboolean@3.0.3: {}
lodash.isinteger@4.0.4: {}
lodash.isnumber@3.0.3: {}
lodash.isplainobject@4.0.6: {}
lodash.isstring@4.0.1: {}
lodash.once@4.1.1: {}
lru-cache@10.4.3: {}
lru-cache@6.0.0:
dependencies:
yallist: 4.0.0
lru-memoizer@2.3.0:
dependencies:
lodash.clonedeep: 4.5.0
lru-cache: 6.0.0
ms@2.1.3: {}
safe-buffer@5.2.1: {}
semver@7.6.3: {}
tslib@2.8.1: {}
undici-types@6.19.8: {}
urlpattern-polyfill@10.1.0: {}
yallist@4.0.0: {}

View File

@@ -18,3 +18,9 @@
timeout_seconds: 60
customization: {}
comment: Remote schema example
- name: stripe
definition:
url: '{{NHOST_FUNCTIONS_URL}}/graphql/stripe'
timeout_seconds: 60
customization: {}
comment: ""

View File

@@ -7,6 +7,10 @@ value = 'Sayonara'
name = 'NODE_ENV'
value = 'production'
[[global.environment]]
name = 'STRIPE_SECRET_KEY'
value = '{{ secrets.STRIPE_SECRET_KEY }}'
[hasura]
version = 'v2.46.0-ce'
adminSecret = '{{ secrets.HASURA_GRAPHQL_ADMIN_SECRET }}'

View File

@@ -1,7 +0,0 @@
{
"extends": "../../config/tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*"]
}

View File

@@ -119,7 +119,6 @@
gofumpt
golangci-lint
gqlgenc
oapi-codegen
# internal packages
self.packages.${system}.codegen

2
go.mod
View File

@@ -16,6 +16,7 @@ require (
github.com/davidbyttow/govips/v2 v2.16.0
github.com/gabriel-vasile/mimetype v1.4.8
github.com/getkin/kin-openapi v0.133.0
github.com/gin-contrib/cors v1.7.3
github.com/gin-gonic/gin v1.11.0
github.com/go-git/go-git/v5 v5.16.2
github.com/go-webauthn/webauthn v0.12.2
@@ -29,6 +30,7 @@ require (
github.com/lmittmann/tint v1.0.7
github.com/mark3labs/mcp-go v0.41.1
github.com/nhost/be v0.0.0-20251021065906-8abc7d8dfa48
github.com/oapi-codegen/gin-middleware v1.0.2
github.com/oapi-codegen/runtime v1.1.1
github.com/pb33f/libopenapi v0.21.12
github.com/pelletier/go-toml/v2 v2.2.4

4
go.sum
View File

@@ -162,6 +162,8 @@ github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3G
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ=
github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE=
github.com/gin-contrib/cors v1.7.3 h1:hV+a5xp8hwJoTw7OY+a70FsL8JkVVFTXw9EcfrYUdns=
github.com/gin-contrib/cors v1.7.3/go.mod h1:M3bcKZhxzsvI+rlRSkkxHyljJt1ESd93COUvemZ79j4=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
@@ -339,6 +341,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
github.com/nhost/be v0.0.0-20251021065906-8abc7d8dfa48 h1:+Oh4Rbr1psWlBaQTakoBYFNB8jBioiXuimNMaNPLTHk=
github.com/nhost/be v0.0.0-20251021065906-8abc7d8dfa48/go.mod h1:feVvqP3dft8hWbp9zNZExdGKbFEYv8aLYohfyAeINNQ=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oapi-codegen/gin-middleware v1.0.2 h1:/H99UzvHQAUxXK8pzdcGAZgjCVeXdFDAUUWaJT0k0eI=
github.com/oapi-codegen/gin-middleware v1.0.2/go.mod h1:2HJDQjH8jzK2/k/VKcWl+/T41H7ai2bKa6dN3AA2GpA=
github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=

View File

@@ -1,13 +0,0 @@
package oapi
import "fmt"
type AuthenticatorError struct {
Scheme string
Code string
Message string
}
func (e *AuthenticatorError) Error() string {
return fmt.Sprintf("security error [%s]: %s", e.Code, e.Message)
}

View File

@@ -1,10 +0,0 @@
//go:generate oapi-codegen -config server.cfg.yaml openapi.yaml
//go:generate oapi-codegen -config types.cfg.yaml openapi.yaml
package api
import (
_ "embed"
)
//go:embed openapi.yaml
var OpenAPISchema []byte

View File

@@ -1,200 +0,0 @@
openapi: "3.0.0"
paths:
/signin/email-password:
post:
summary: Sign in with email and password
description: Authenticate a user with their email and password. Returns a session object or MFA challenge if two-factor authentication is enabled.
operationId: signInEmailPassword
requestBody:
description: User credentials for email and password authentication
content:
application/json:
schema:
$ref: "#/components/schemas/SignInEmailPasswordRequest"
required: true
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/SignInEmailPasswordResponse"
description: "Authentication successful. If MFA is enabled, a challenge will be returned instead of a session."
default:
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
description: "An error occurred while processing the request"
/user/email/change:
post:
summary: Change user email
description: Request to change the authenticated user's email address. A verification email will be sent to the new address to confirm the change. Requires elevated permissions.
operationId: changeUserEmail
tags:
- user
security:
- BearerAuthElevated: []
requestBody:
description: New email address and optional redirect URL for email change
content:
application/json:
schema:
$ref: "#/components/schemas/UserEmailChangeRequest"
required: true
responses:
"200":
description: >-
Email change requested. An email with a verification link has been sent to the new address
content:
application/json:
schema:
$ref: "#/components/schemas/OKResponse"
default:
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
description: "An error occurred while processing the request"
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
description: "Bearer authentication with JWT access token. Used to authenticate requests to protected endpoints."
BearerAuthElevated:
type: http
scheme: bearer
description: "Bearer authentication that requires elevated permissions. Used for sensitive operations that may require additional security measures such as recent authentication. For details see https://docs.nhost.io/products/auth/elevated-permissions"
schemas:
SignInEmailPasswordRequest:
type: object
description: "Request to authenticate using email and password"
additionalProperties: false
properties:
email:
description: "User's email address"
example: "john.smith@nhost.io"
format: email
type: string
password:
description: "User's password"
example: "Str0ngPassw#ord-94|%"
minLength: 3
maxLength: 50
type: string
required:
- email
- password
SignInEmailPasswordResponse:
type: object
description: "Response for email-password authentication that may include a session or MFA challenge"
additionalProperties: false
properties:
session:
$ref: "#/components/schemas/Session"
Session:
type: object
description: "User authentication session containing tokens and user information"
additionalProperties: false
properties:
accessToken:
type: string
description: "JWT token for authenticating API requests"
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
accessTokenExpiresIn:
type: integer
format: int64
description: "Expiration time of the access token in seconds"
example: 900
refreshTokenId:
description: "Identifier for the refresh token"
example: "2c35b6f3-c4b9-48e3-978a-d4d0f1d42e24"
pattern: \b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b
type: string
refreshToken:
description: "Token used to refresh the access token"
example: "2c35b6f3-c4b9-48e3-978a-d4d0f1d42e24"
pattern: \b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b
type: string
required:
- accessToken
- accessTokenExpiresIn
- refreshToken
- refreshTokenId
UserEmailChangeRequest:
type: object
additionalProperties: false
properties:
newEmail:
description: A valid email
example: john.smith@nhost.io
format: email
type: string
required:
- newEmail
OKResponse:
type: string
additionalProperties: false
enum:
- OK
ErrorResponse:
type: object
description: "Standardized error response"
additionalProperties: false
properties:
status:
description: "HTTP status error code"
type: integer
example: 400
message:
description: "Human-friendly error message"
type: string
example: "Invalid email format"
error:
description: "Error code identifying the specific application error"
type: string
enum:
- default-role-must-be-in-allowed-roles
- disabled-endpoint
- disabled-user
- email-already-in-use
- email-already-verified
- forbidden-anonymous
- internal-server-error
- invalid-email-password
- invalid-request
- locale-not-allowed
- password-too-short
- password-in-hibp-database
- redirectTo-not-allowed
- role-not-allowed
- signup-disabled
- unverified-user
- user-not-anonymous
- invalid-pat
- invalid-refresh-token
- invalid-ticket
- disabled-mfa-totp
- no-totp-secret
- invalid-totp
- mfa-type-not-found
- totp-already-active
- invalid-state
- oauth-token-echange-failed
- oauth-profile-fetch-failed
- oauth-provider-error
- invalid-otp
- cannot-send-sms
required:
- status
- message
- error

View File

@@ -1,6 +0,0 @@
package: api
generate:
gin-server: true
embedded-spec: true
strict-server: true
output: server.gen.go

View File

@@ -1,351 +0,0 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.5.0 DO NOT EDIT.
package api
import (
"bytes"
"compress/gzip"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"net/url"
"path"
"strings"
"github.com/getkin/kin-openapi/openapi3"
"github.com/gin-gonic/gin"
strictgin "github.com/oapi-codegen/runtime/strictmiddleware/gin"
)
// ServerInterface represents all server handlers.
type ServerInterface interface {
// Sign in with email and password
// (POST /signin/email-password)
SignInEmailPassword(c *gin.Context)
// Change user email
// (POST /user/email/change)
ChangeUserEmail(c *gin.Context)
}
// ServerInterfaceWrapper converts contexts to parameters.
type ServerInterfaceWrapper struct {
Handler ServerInterface
HandlerMiddlewares []MiddlewareFunc
ErrorHandler func(*gin.Context, error, int)
}
type MiddlewareFunc func(c *gin.Context)
// SignInEmailPassword operation middleware
func (siw *ServerInterfaceWrapper) SignInEmailPassword(c *gin.Context) {
for _, middleware := range siw.HandlerMiddlewares {
middleware(c)
if c.IsAborted() {
return
}
}
siw.Handler.SignInEmailPassword(c)
}
// ChangeUserEmail operation middleware
func (siw *ServerInterfaceWrapper) ChangeUserEmail(c *gin.Context) {
c.Set(BearerAuthElevatedScopes, []string{})
for _, middleware := range siw.HandlerMiddlewares {
middleware(c)
if c.IsAborted() {
return
}
}
siw.Handler.ChangeUserEmail(c)
}
// GinServerOptions provides options for the Gin server.
type GinServerOptions struct {
BaseURL string
Middlewares []MiddlewareFunc
ErrorHandler func(*gin.Context, error, int)
}
// RegisterHandlers creates http.Handler with routing matching OpenAPI spec.
func RegisterHandlers(router gin.IRouter, si ServerInterface) {
RegisterHandlersWithOptions(router, si, GinServerOptions{})
}
// RegisterHandlersWithOptions creates http.Handler with additional options
func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options GinServerOptions) {
errorHandler := options.ErrorHandler
if errorHandler == nil {
errorHandler = func(c *gin.Context, err error, statusCode int) {
c.JSON(statusCode, gin.H{"msg": err.Error()})
}
}
wrapper := ServerInterfaceWrapper{
Handler: si,
HandlerMiddlewares: options.Middlewares,
ErrorHandler: errorHandler,
}
router.POST(options.BaseURL+"/signin/email-password", wrapper.SignInEmailPassword)
router.POST(options.BaseURL+"/user/email/change", wrapper.ChangeUserEmail)
}
type SignInEmailPasswordRequestObject struct {
Body *SignInEmailPasswordJSONRequestBody
}
type SignInEmailPasswordResponseObject interface {
VisitSignInEmailPasswordResponse(w http.ResponseWriter) error
}
type SignInEmailPassword200JSONResponse SignInEmailPasswordResponse
func (response SignInEmailPassword200JSONResponse) VisitSignInEmailPasswordResponse(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
return json.NewEncoder(w).Encode(response)
}
type SignInEmailPassworddefaultJSONResponse struct {
Body ErrorResponse
StatusCode int
}
func (response SignInEmailPassworddefaultJSONResponse) VisitSignInEmailPasswordResponse(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(response.StatusCode)
return json.NewEncoder(w).Encode(response.Body)
}
type ChangeUserEmailRequestObject struct {
Body *ChangeUserEmailJSONRequestBody
}
type ChangeUserEmailResponseObject interface {
VisitChangeUserEmailResponse(w http.ResponseWriter) error
}
type ChangeUserEmail200JSONResponse OKResponse
func (response ChangeUserEmail200JSONResponse) VisitChangeUserEmailResponse(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
return json.NewEncoder(w).Encode(response)
}
type ChangeUserEmaildefaultJSONResponse struct {
Body ErrorResponse
StatusCode int
}
func (response ChangeUserEmaildefaultJSONResponse) VisitChangeUserEmailResponse(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(response.StatusCode)
return json.NewEncoder(w).Encode(response.Body)
}
// StrictServerInterface represents all server handlers.
type StrictServerInterface interface {
// Sign in with email and password
// (POST /signin/email-password)
SignInEmailPassword(ctx context.Context, request SignInEmailPasswordRequestObject) (SignInEmailPasswordResponseObject, error)
// Change user email
// (POST /user/email/change)
ChangeUserEmail(ctx context.Context, request ChangeUserEmailRequestObject) (ChangeUserEmailResponseObject, error)
}
type StrictHandlerFunc = strictgin.StrictGinHandlerFunc
type StrictMiddlewareFunc = strictgin.StrictGinMiddlewareFunc
func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc) ServerInterface {
return &strictHandler{ssi: ssi, middlewares: middlewares}
}
type strictHandler struct {
ssi StrictServerInterface
middlewares []StrictMiddlewareFunc
}
// SignInEmailPassword operation middleware
func (sh *strictHandler) SignInEmailPassword(ctx *gin.Context) {
var request SignInEmailPasswordRequestObject
var body SignInEmailPasswordJSONRequestBody
if err := ctx.ShouldBindJSON(&body); err != nil {
ctx.Status(http.StatusBadRequest)
ctx.Error(err)
return
}
request.Body = &body
handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
return sh.ssi.SignInEmailPassword(ctx, request.(SignInEmailPasswordRequestObject))
}
for _, middleware := range sh.middlewares {
handler = middleware(handler, "SignInEmailPassword")
}
response, err := handler(ctx, request)
if err != nil {
ctx.Error(err)
ctx.Status(http.StatusInternalServerError)
} else if validResponse, ok := response.(SignInEmailPasswordResponseObject); ok {
if err := validResponse.VisitSignInEmailPasswordResponse(ctx.Writer); err != nil {
ctx.Error(err)
}
} else if response != nil {
ctx.Error(fmt.Errorf("unexpected response type: %T", response))
}
}
// ChangeUserEmail operation middleware
func (sh *strictHandler) ChangeUserEmail(ctx *gin.Context) {
var request ChangeUserEmailRequestObject
var body ChangeUserEmailJSONRequestBody
if err := ctx.ShouldBindJSON(&body); err != nil {
ctx.Status(http.StatusBadRequest)
ctx.Error(err)
return
}
request.Body = &body
handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
return sh.ssi.ChangeUserEmail(ctx, request.(ChangeUserEmailRequestObject))
}
for _, middleware := range sh.middlewares {
handler = middleware(handler, "ChangeUserEmail")
}
response, err := handler(ctx, request)
if err != nil {
ctx.Error(err)
ctx.Status(http.StatusInternalServerError)
} else if validResponse, ok := response.(ChangeUserEmailResponseObject); ok {
if err := validResponse.VisitChangeUserEmailResponse(ctx.Writer); err != nil {
ctx.Error(err)
}
} else if response != nil {
ctx.Error(fmt.Errorf("unexpected response type: %T", response))
}
}
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
"H4sIAAAAAAAC/9RYUXPbuBH+KxhcO30RJMVW0lhP9WV8rXLXS8Z22s7YfoCApYiYBHhY0IrO1X/vLEBK",
"pEQ1vs5dp32yTBCL3f2+b3fBZ65cWTkLNiCfP3NUOZQy/rzy3vlrwMpZBHogtTbBOCuLj95V4IMB5PNM",
"FggjrgGVNxWt8zm/CdJq6bX5GTQDMsR8a2nEq872Zx6X6UffRDyeKaeBGQ02mGxj7IqFHBhWoExmFJNV",
"VRglaUc6hY842Lrk8zuuIZN1EYR3BYiyxiCWIIwVsijcGnR8jnzEtUG5LEALsLpyxobusxoh2iylKYQs",
"PEi9ISN1jKP/+Am8yQxoPuKZ80ujNVghrbOb0tV0krEBvJWFQPBP4EXrsbFPsjBaJHOVRFw7rzsLHn6q",
"AcmxwilZgLAutHFQOpsdIjgnMHc+dB8aK3KzrISWQS5l9NuDNh5UuHUHlmKu+o/QrGxdiTYjfMRr20ba",
"pof+pG29aJPzlQy9UDIPmIvgHsF2ngejHqGX+jKTIrhQ8RG3Lv4SCMpD11qzHl/dVMn1zNWW3Iw7Wmyk",
"CuYJOjsxyED/O1mHxhsBKpd2BSKTJkWaFivvMlOAyCCofGDxyegBMJNnSlryCcFqgSXyhxEnR/mcY/DG",
"rvh2xEtAlCs4VsBf6lJakXkDVhebRkbt2yMOX2RZFWRrkc5kkUAsc76MOT86iYKuceCg29uPLC02p5Ds",
"ukfMptOdPaLxCjzfbolJP9XGgybBNdb3AY0aae+DdsvPoAK58uH7F1eWVtAfvh9M3w0gxjB+UYH6hOAZ",
"IUiVpakgmCwx5WyQxsZqQ8RAJq1mRHJmbMouGTmsY1IpQLyNxD5K8fu/3yZjBE/vYLtilx8XrNE49oCF",
"zft8+WdlPpj3i08/L179aBa4sNev1bvFm8Vj9Y+/vXt/MR6Ph7DueHP1pTIecDHgVlxK0QdTAnNZLLBp",
"c+OwocwoZ3XPtwtiREO1yIk3M35MEWJIFPyJtMTHlFrNgmPNu0cu9HJyps5fL99k50LNlhdi9hbOxcUf",
"30qhZ3qavdKzMzibxfoXqNryOb+/X95NxYUU2cPz2+39/VLs/p1tT/7u7np1RtuGstyNbqGP41ukzmXA",
"R9wpsF2Q/8uRHUi7S+0T1DpA+ig1Q0Xgxqzswl5R1frYtKvrptX9MjU3u4hDHWkBq5HklcoiabjTWw9m",
"EHrlGD6qEn/A1oDWHrAv0M8ut2MsTcj/ZHOHYWwc78gimR3gzc6RU0d2PN2fdhP81K5iqr6h1n4x++fv",
"qd7KLz+AXYWcz19PR7w0tv33/GvAtg7ujnsxTP/RWNhui2LojzuHxTjkMrBSbpixqqg1MLmrz86zv353",
"yVQuiwLs6niixH1L+J2HjM/5N5P9mDtpZtxJ2zkoKUdBEw4x5HdxKHgpL/uOWFhfDTPrknVa9q9AqQNc",
"dwcf40lzAKjam7C5oUQkT78F6cFf1sSaQ1/T2iFAaxNyRm2tW6nH7FNTy3s6bJsbLVTeBVCB7gXNwI3U",
"wCIo5OcynraPMA+hIkD2Hl4V8CQD6Jd6GqnUZAcZNLtZBb40kQHYuE2sRLBoaFhkBGQ0gHsyNlbYngOs",
"TSYrQWJNJ2CtciaReVBgw4E3Y/ad80xDkKZAhgCMAsT5ZKKdwnEL+aTyTtcq4IS2T1qnRcfpryeNsKaJ",
"hc9tXRQj7iqwsjJ8zs/H0/E09ZI84j+hOd/YycEdZP7MK5dof8DfLrwyDUeRESEH4wdK7phdQ6g9DVN7",
"IUdKHumZmYyFtROZVMEdoWmQgY1XBKLNDiTqvkOViidhAIZvnd5QIDTegU1S3t8fJ58xVYxUHb5aO063",
"rpj2gWlTeYjTgCxwX/96OToIlXc1HXwNUeSpgkbQzqbT3zagpsgPRHR5MDrXsQhkdTFmiyzCucdpxGQH",
"3LUpCrakmkB0AM2MxQBS0+y5o8aYxxPjDf5XC7H/QWMoqOYrAnNK1d6DZuvcFEAli6JrPz/4HdAjjnVZ",
"Sr9puEezclTBwMhBb09IJ0ljk3TZPK2wzkyTXk1jcUd36U5yOJ+M2SVLF/T2w0hcbdOOVJKCi8YsrNtd",
"8RhnM+PLuJSOJNH+u7J5JMDULHe98zcS34nePIDoj7DuZydi4qqmdrcfQtin6x86mmyg+W/Kr3MfHgjj",
"quNWSz/QY3a5RzfkTPZxL4x9ZLlEtgSwp3D/v9FZ02X5/O55cBS4e9g+dOWYqJEa025mkiuk6Sh+tnrY",
"brfbfwUAAP//3ciGL/8UAAA=",
}
// GetSwagger returns the content of the embedded swagger specification file
// or error if failed to decode
func decodeSpec() ([]byte, error) {
zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
if err != nil {
return nil, fmt.Errorf("error base64 decoding spec: %w", err)
}
zr, err := gzip.NewReader(bytes.NewReader(zipped))
if err != nil {
return nil, fmt.Errorf("error decompressing spec: %w", err)
}
var buf bytes.Buffer
_, err = buf.ReadFrom(zr)
if err != nil {
return nil, fmt.Errorf("error decompressing spec: %w", err)
}
return buf.Bytes(), nil
}
var rawSpec = decodeSpecCached()
// a naive cached of a decoded swagger spec
func decodeSpecCached() func() ([]byte, error) {
data, err := decodeSpec()
return func() ([]byte, error) {
return data, err
}
}
// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
res := make(map[string]func() ([]byte, error))
if len(pathToFile) > 0 {
res[pathToFile] = rawSpec
}
return res
}
// GetSwagger returns the Swagger specification corresponding to the generated code
// in this file. The external references of Swagger specification are resolved.
// The logic of resolving external references is tightly connected to "import-mapping" feature.
// Externally referenced files must be embedded in the corresponding golang packages.
// Urls can be supported but this task was out of the scope.
func GetSwagger() (swagger *openapi3.T, err error) {
resolvePath := PathToRawSpec("")
loader := openapi3.NewLoader()
loader.IsExternalRefsAllowed = true
loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
pathToFile := url.String()
pathToFile = path.Clean(pathToFile)
getSpec, ok := resolvePath[pathToFile]
if !ok {
err1 := fmt.Errorf("path not found: %s", pathToFile)
return nil, err1
}
return getSpec()
}
var specData []byte
specData, err = rawSpec()
if err != nil {
return
}
swagger, err = loader.LoadFromData(specData)
if err != nil {
return
}
return
}

View File

@@ -1,4 +0,0 @@
package: api
generate:
models: true
output: types.gen.go

View File

@@ -1,112 +0,0 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version 2.5.0 DO NOT EDIT.
package api
import (
openapi_types "github.com/oapi-codegen/runtime/types"
)
const (
BearerAuthElevatedScopes = "BearerAuthElevated.Scopes"
)
// Defines values for ErrorResponseError.
const (
CannotSendSms ErrorResponseError = "cannot-send-sms"
DefaultRoleMustBeInAllowedRoles ErrorResponseError = "default-role-must-be-in-allowed-roles"
DisabledEndpoint ErrorResponseError = "disabled-endpoint"
DisabledMfaTotp ErrorResponseError = "disabled-mfa-totp"
DisabledUser ErrorResponseError = "disabled-user"
EmailAlreadyInUse ErrorResponseError = "email-already-in-use"
EmailAlreadyVerified ErrorResponseError = "email-already-verified"
ForbiddenAnonymous ErrorResponseError = "forbidden-anonymous"
InternalServerError ErrorResponseError = "internal-server-error"
InvalidEmailPassword ErrorResponseError = "invalid-email-password"
InvalidOtp ErrorResponseError = "invalid-otp"
InvalidPat ErrorResponseError = "invalid-pat"
InvalidRefreshToken ErrorResponseError = "invalid-refresh-token"
InvalidRequest ErrorResponseError = "invalid-request"
InvalidState ErrorResponseError = "invalid-state"
InvalidTicket ErrorResponseError = "invalid-ticket"
InvalidTotp ErrorResponseError = "invalid-totp"
LocaleNotAllowed ErrorResponseError = "locale-not-allowed"
MfaTypeNotFound ErrorResponseError = "mfa-type-not-found"
NoTotpSecret ErrorResponseError = "no-totp-secret"
OauthProfileFetchFailed ErrorResponseError = "oauth-profile-fetch-failed"
OauthProviderError ErrorResponseError = "oauth-provider-error"
OauthTokenEchangeFailed ErrorResponseError = "oauth-token-echange-failed"
PasswordInHibpDatabase ErrorResponseError = "password-in-hibp-database"
PasswordTooShort ErrorResponseError = "password-too-short"
RedirectToNotAllowed ErrorResponseError = "redirectTo-not-allowed"
RoleNotAllowed ErrorResponseError = "role-not-allowed"
SignupDisabled ErrorResponseError = "signup-disabled"
TotpAlreadyActive ErrorResponseError = "totp-already-active"
UnverifiedUser ErrorResponseError = "unverified-user"
UserNotAnonymous ErrorResponseError = "user-not-anonymous"
)
// Defines values for OKResponse.
const (
OK OKResponse = "OK"
)
// ErrorResponse Standardized error response
type ErrorResponse struct {
// Error Error code identifying the specific application error
Error ErrorResponseError `json:"error"`
// Message Human-friendly error message
Message string `json:"message"`
// Status HTTP status error code
Status int `json:"status"`
}
// ErrorResponseError Error code identifying the specific application error
type ErrorResponseError string
// OKResponse defines model for OKResponse.
type OKResponse string
// Session User authentication session containing tokens and user information
type Session struct {
// AccessToken JWT token for authenticating API requests
AccessToken string `json:"accessToken"`
// AccessTokenExpiresIn Expiration time of the access token in seconds
AccessTokenExpiresIn int64 `json:"accessTokenExpiresIn"`
// RefreshToken Token used to refresh the access token
RefreshToken string `json:"refreshToken"`
// RefreshTokenId Identifier for the refresh token
RefreshTokenId string `json:"refreshTokenId"`
}
// SignInEmailPasswordRequest Request to authenticate using email and password
type SignInEmailPasswordRequest struct {
// Email User's email address
Email openapi_types.Email `json:"email"`
// Password User's password
Password string `json:"password"`
}
// SignInEmailPasswordResponse Response for email-password authentication that may include a session or MFA challenge
type SignInEmailPasswordResponse struct {
// Session User authentication session containing tokens and user information
Session *Session `json:"session,omitempty"`
}
// UserEmailChangeRequest defines model for UserEmailChangeRequest.
type UserEmailChangeRequest struct {
// NewEmail A valid email
NewEmail openapi_types.Email `json:"newEmail"`
}
// SignInEmailPasswordJSONRequestBody defines body for SignInEmailPassword for application/json ContentType.
type SignInEmailPasswordJSONRequestBody = SignInEmailPasswordRequest
// ChangeUserEmailJSONRequestBody defines body for ChangeUserEmail for application/json ContentType.
type ChangeUserEmailJSONRequestBody = UserEmailChangeRequest

View File

@@ -1,49 +0,0 @@
package controller
import (
"context"
"errors"
"net/http"
"github.com/nhost/nhost/internal/lib/oapi/example/api"
)
type Controller struct{}
func NewController() *Controller {
return &Controller{}
}
func (c *Controller) SignInEmailPassword( //nolint:ireturn
_ context.Context, req api.SignInEmailPasswordRequestObject,
) (api.SignInEmailPasswordResponseObject, error) {
switch req.Body.Email {
case "bad@email.com":
return api.SignInEmailPassworddefaultJSONResponse{
Body: api.ErrorResponse{
Error: api.DisabledUser,
Message: "The user account is disabled.",
Status: http.StatusConflict,
},
StatusCode: http.StatusConflict,
}, nil
case "crash@email.com":
return nil, errors.New("simulated server crash") //nolint:err113
}
return api.SignInEmailPassword200JSONResponse{
Session: &api.Session{
AccessToken: "access_token_example",
AccessTokenExpiresIn: 900, //nolint:mnd
RefreshToken: "refresh_token_example",
RefreshTokenId: "refresh_token_id_example",
},
}, nil
}
func (c *Controller) ChangeUserEmail( //nolint:ireturn
_ context.Context,
_ api.ChangeUserEmailRequestObject,
) (api.ChangeUserEmailResponseObject, error) {
return api.ChangeUserEmail200JSONResponse(api.OK), nil
}

View File

@@ -1,109 +0,0 @@
package main
import (
"context"
"fmt"
"log/slog"
"net/http"
"os"
"time"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/gin-gonic/gin"
"github.com/lmittmann/tint"
"github.com/nhost/nhost/internal/lib/oapi"
"github.com/nhost/nhost/internal/lib/oapi/example/api"
"github.com/nhost/nhost/internal/lib/oapi/example/controller"
"github.com/nhost/nhost/internal/lib/oapi/middleware"
)
const apiPrefix = "/"
func getLogger() *slog.Logger {
handler := tint.NewHandler(os.Stdout, &tint.Options{
AddSource: true,
Level: slog.LevelDebug,
TimeFormat: time.StampMilli,
NoColor: false,
ReplaceAttr: nil,
})
return slog.New(handler)
}
func authFn(
ctx context.Context,
input *openapi3filter.AuthenticationInput,
) error {
_, ok := ctx.Value(oapi.GinContextKey).(*gin.Context)
if !ok {
return &oapi.AuthenticatorError{
Scheme: input.SecuritySchemeName,
Code: "unauthorized",
Message: "unable to get context",
}
}
return &oapi.AuthenticatorError{
Scheme: input.SecuritySchemeName,
Code: "unauthorized",
Message: "your access token is invalid",
}
}
func setupRouter(logger *slog.Logger) (*gin.Engine, error) {
ctrl := controller.NewController()
handler := api.NewStrictHandler(ctrl, []api.StrictMiddlewareFunc{})
router, mw, err := oapi.NewRouter(
api.OpenAPISchema,
apiPrefix,
authFn,
middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"*"},
},
logger,
)
if err != nil {
return nil, fmt.Errorf("failed to create oapi router: %w", err)
}
api.RegisterHandlersWithOptions(
router,
handler,
api.GinServerOptions{
BaseURL: apiPrefix,
Middlewares: []api.MiddlewareFunc{mw},
ErrorHandler: nil,
},
)
return router, nil
}
func run(ctx context.Context) error {
logger := getLogger()
router, err := setupRouter(logger) //nolint:contextcheck
if err != nil {
return err
}
server := &http.Server{ //nolint:exhaustruct
Addr: ":8080",
Handler: router,
ReadHeaderTimeout: 5 * time.Second, //nolint:mnd
}
if err := server.ListenAndServe(); err != nil {
logger.ErrorContext(ctx, "server failed", slog.String("error", err.Error()))
}
return nil
}
func main() {
if err := run(context.Background()); err != nil {
panic(err)
}
}

View File

@@ -1,177 +0,0 @@
package main
import (
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/gin-gonic/gin"
"github.com/google/go-cmp/cmp"
)
func makeRequest(
router *gin.Engine,
method, path string,
headers map[string]string,
body io.Reader,
) *httptest.ResponseRecorder {
req := httptest.NewRequest(method, path, body)
for key, value := range headers {
req.Header.Set(key, value)
}
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
return w
}
func TestRequests(t *testing.T) {
t.Parallel()
logger := getLogger()
router, err := setupRouter(logger)
if err != nil {
t.Fatalf("Failed to set up router: %v", err)
}
cases := []struct {
name string
method string
path string
headers map[string]string
body io.Reader
expectedStatus int
expectedResponse string
}{
{
name: "success",
method: http.MethodPost,
path: "/signin/email-password",
headers: map[string]string{
"Content-Type": "application/json",
},
body: strings.NewReader(`{"email": "asd@asd.com", "password": "p4ssw0rd"}`),
expectedStatus: http.StatusOK,
expectedResponse: "{\"session\":{\"accessToken\":\"access_token_example\",\"accessTokenExpiresIn\":900,\"refreshToken\":\"refresh_token_example\",\"refreshTokenId\":\"refresh_token_id_example\"}}\n", //nolint:lll
},
{
name: "expected error",
method: http.MethodPost,
path: "/signin/email-password",
headers: map[string]string{
"Content-Type": "application/json",
},
body: strings.NewReader(
`{"email": "bad@email.com", "password": "p4ssw0rd"}`,
),
expectedStatus: http.StatusConflict,
expectedResponse: "{\"error\":\"disabled-user\",\"message\":\"The user account is disabled.\",\"status\":409}\n", //nolint:lll
},
{
name: "unexpected error",
method: http.MethodPost,
path: "/signin/email-password",
headers: map[string]string{
"Content-Type": "application/json",
},
body: strings.NewReader(
`{"email": "crash@email.com", "password": "p4ssw0rd"}`,
),
expectedStatus: http.StatusInternalServerError,
expectedResponse: `{"errors":"internal-server-error","message":"simulated server crash"}`,
},
{
name: "missing body",
method: http.MethodPost,
path: "/signin/email-password",
headers: map[string]string{
"Content-Type": "application/json",
},
body: nil,
expectedStatus: http.StatusBadRequest,
expectedResponse: `{"error":"request-validation-error","reason":"value is required but missing"}`,
},
{
name: "wrong param",
method: http.MethodPost,
path: "/signin/email-password",
headers: map[string]string{
"Content-Type": "application/json",
},
body: strings.NewReader(
`{"wrong":"asd", "email": "asd@asd.com", "password": "p4ssw0rd"}`,
),
expectedStatus: http.StatusBadRequest,
expectedResponse: `{"error":"schema-validation-error","reason":"property \"wrong\" is unsupported"}`,
},
{
name: "missing param",
method: http.MethodPost,
path: "/signin/email-password",
headers: map[string]string{
"Content-Type": "application/json",
},
body: strings.NewReader(`{"email": "asd@asd.com"}`),
expectedStatus: http.StatusBadRequest,
expectedResponse: `{"error":"schema-validation-error","reason":"property \"password\" is missing"}`,
},
{
name: "invalid param",
method: http.MethodPost,
path: "/signin/email-password",
headers: map[string]string{
"Content-Type": "application/json",
},
body: strings.NewReader(`{"email": "asdasd.com", "password": "p4ssw0rd"}`),
expectedStatus: http.StatusBadRequest,
expectedResponse: `{"errors":"bad-request","message":"email: failed to pass regex validation"}`,
},
{
name: "needs security",
method: http.MethodPost,
path: "/user/email/change",
headers: map[string]string{
"Content-Type": "application/json",
},
body: strings.NewReader(`{"newEmail": "new@asd.com"`),
expectedStatus: http.StatusUnauthorized,
expectedResponse: `{"error":"unauthorized","reason":"your access token is invalid","securityScheme":"BearerAuthElevated"}`, //nolint:lll
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
w := makeRequest(router, tc.method, tc.path, tc.headers, tc.body)
resp := w.Result()
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("Failed to read response body: %v", err)
}
if resp.StatusCode != tc.expectedStatus {
t.Errorf("Expected status %d, got %d", tc.expectedStatus, resp.StatusCode)
}
if diff := cmp.Diff(string(body), tc.expectedResponse); diff != "" {
t.Errorf("Response body mismatch (-want +got):\n%s", diff)
}
})
}
}

View File

@@ -1,140 +0,0 @@
package middleware
import (
"net/http"
"slices"
"strings"
"github.com/gin-gonic/gin"
)
// CORSOptions configures the CORS middleware behavior.
//
// The middleware supports three strategies for handling Access-Control-Allow-Headers:
// - nil (default): Reflects the Access-Control-Request-Headers from the client
// - empty slice: Denies all headers (no Access-Control-Allow-Headers header is set)
// - non-empty slice: Uses the specified headers
type CORSOptions struct {
// AllowedOrigins is a list of origins permitted to make cross-origin requests.
// Use "*" or nil slice to allow all origins.
AllowedOrigins []string
// AllowedMethods is a list of HTTP methods the client is permitted to use.
// Common values: GET, POST, PUT, DELETE, PATCH, OPTIONS.
AllowedMethods []string
// AllowedHeaders controls which headers clients can use in requests.
// - nil: reflects client's Access-Control-Request-Headers (permissive)
// - empty slice: denies all headers
// - non-empty: allows only specified headers
AllowedHeaders []string
// ExposedHeaders lists headers that browsers are allowed to access.
// By default, browsers only expose simple response headers.
ExposedHeaders []string
// AllowCredentials indicates whether the request can include credentials
// (cookies, authorization headers, or TLS client certificates).
AllowCredentials bool
// MaxAge indicates how long (in seconds) the results of a preflight request
// can be cached. Empty string means no caching directive is sent.
MaxAge string
}
// CORS returns a Gin middleware handler that implements Cross-Origin Resource Sharing (CORS).
//
// The middleware handles both preflight (OPTIONS) requests and actual requests, setting
// appropriate CORS headers based on the provided configuration. It automatically adds
// the "Vary: Origin, Access-Control-Request-Method" header for proper cache behavior.
//
// For preflight requests (OPTIONS), the middleware responds with 204 No Content and
// prevents further request processing. For actual requests, it sets CORS headers and
// continues the middleware chain.
//
// Example usage:
//
// router.Use(middleware.CORS(middleware.CORSOptions{
// AllowedOrigins: []string{"https://example.com", "https://app.example.com"},
// AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
// AllowedHeaders: nil, // reflects client headers
// AllowCredentials: true,
// MaxAge: "3600",
// }))
func CORS(opts CORSOptions) gin.HandlerFunc { //nolint:cyclop,funlen
allowedMethods := strings.Join(opts.AllowedMethods, ", ")
exposedHeaders := strings.Join(opts.ExposedHeaders, ", ")
allowCredentials := "false"
if opts.AllowCredentials {
allowCredentials = "true"
}
var (
headerStrategy string // "reflect", "specific", or "deny"
allowedHeaders string
)
switch {
case opts.AllowedHeaders == nil:
headerStrategy = "reflect"
case len(opts.AllowedHeaders) == 0:
headerStrategy = "deny"
default:
headerStrategy = "specific"
allowedHeaders = strings.Join(opts.AllowedHeaders, ", ")
}
f := func(c *gin.Context, origin string) {
if opts.AllowedOrigins != nil &&
!slices.Contains(opts.AllowedOrigins, origin) &&
!slices.Contains(opts.AllowedOrigins, "*") {
return
}
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Methods", allowedMethods)
// Handle allowed headers based on strategy
switch headerStrategy {
case "specific":
c.Header("Access-Control-Allow-Headers", allowedHeaders)
case "reflect":
headers := c.Request.Header.Get("Access-Control-Request-Headers")
if headers != "" {
c.Header("Access-Control-Allow-Headers", headers)
}
case "deny":
// Don't set the header at all
}
if exposedHeaders != "" {
c.Header("Access-Control-Expose-Headers", exposedHeaders)
}
c.Header("Access-Control-Allow-Credentials", allowCredentials)
if opts.MaxAge != "" {
c.Header("Access-Control-Max-Age", opts.MaxAge)
}
c.Writer.Header().Add("Vary", "Origin, Access-Control-Request-Method")
}
return func(c *gin.Context) {
origin := c.Request.Header.Get("Origin")
if c.Request.Method == http.MethodOptions {
f(c, origin)
c.Header("Content-Length", "0")
c.AbortWithStatus(http.StatusNoContent)
return
}
if origin != "" {
f(c, origin)
}
c.Next()
}
}

View File

@@ -1,323 +0,0 @@
package middleware_test
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/google/go-cmp/cmp"
"github.com/nhost/nhost/internal/lib/oapi/middleware"
)
func TestCORS(t *testing.T) { //nolint:maintidx
t.Parallel()
gin.SetMode(gin.TestMode)
cases := []struct {
name string
opts middleware.CORSOptions
requestMethod string
requestOrigin string
requestHeaders map[string]string
wantStatus int
wantHeaders http.Header
expectNext bool
}{
{
name: "OPTIONS request with allowed origin",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET", "POST"},
AllowedHeaders: []string{"Content-Type", "Authorization"},
},
requestMethod: "OPTIONS",
requestHeaders: map[string]string{},
requestOrigin: "https://example.com",
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{
"Access-Control-Allow-Origin": []string{"https://example.com"},
"Access-Control-Allow-Methods": []string{"GET, POST"},
"Access-Control-Allow-Headers": []string{"Content-Type, Authorization"},
"Access-Control-Allow-Credentials": []string{"false"},
"Vary": []string{
"Origin, Access-Control-Request-Method",
},
"Content-Length": []string{"0"},
},
expectNext: false,
},
{
name: "OPTIONS request with wildcard origin",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
},
requestMethod: "OPTIONS",
requestHeaders: map[string]string{},
requestOrigin: "https://any-origin.com",
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{
"Access-Control-Allow-Origin": []string{"https://any-origin.com"},
"Access-Control-Allow-Methods": []string{"GET, POST, PUT, DELETE"},
},
expectNext: false,
},
{
name: "OPTIONS request with disallowed origin",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET", "POST"},
},
requestMethod: "OPTIONS",
requestHeaders: map[string]string{},
requestOrigin: "https://malicious.com",
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{},
expectNext: false,
},
{
name: "OPTIONS request with reflected headers (nil)",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"POST"},
AllowedHeaders: nil,
},
requestMethod: "OPTIONS",
requestOrigin: "https://example.com",
requestHeaders: map[string]string{
"Access-Control-Request-Headers": "X-Custom-Header, X-Another-Header",
},
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{
"Access-Control-Allow-Headers": []string{"X-Custom-Header, X-Another-Header"},
},
expectNext: false,
},
{
name: "OPTIONS request with denied headers (empty slice)",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"POST"},
AllowedHeaders: []string{},
},
requestMethod: "OPTIONS",
requestOrigin: "https://example.com",
requestHeaders: map[string]string{
"Access-Control-Request-Headers": "X-Custom-Header, X-Another-Header",
},
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{},
expectNext: false,
},
{
name: "OPTIONS request with nil headers and no request headers",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET"},
AllowedHeaders: nil,
},
requestMethod: "OPTIONS",
requestOrigin: "https://example.com",
requestHeaders: map[string]string{},
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{},
expectNext: false,
},
{
name: "OPTIONS request with credentials enabled",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET"},
AllowCredentials: true,
},
requestMethod: "OPTIONS",
requestOrigin: "https://example.com",
requestHeaders: map[string]string{},
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{
"Access-Control-Allow-Credentials": []string{"true"},
},
expectNext: false,
},
{
name: "OPTIONS request with MaxAge",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET"},
MaxAge: "3600",
},
requestMethod: "OPTIONS",
requestOrigin: "https://example.com",
requestHeaders: map[string]string{},
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{
"Access-Control-Max-Age": []string{"3600"},
},
expectNext: false,
},
{
name: "OPTIONS request with exposed headers",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET"},
ExposedHeaders: []string{"X-Custom-Response", "X-Total-Count"},
},
requestMethod: "OPTIONS",
requestOrigin: "https://example.com",
requestHeaders: map[string]string{},
wantStatus: http.StatusNoContent,
wantHeaders: http.Header{
"Access-Control-Expose-Headers": []string{"X-Custom-Response, X-Total-Count"},
},
expectNext: false,
},
{
name: "GET request with allowed origin",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET", "POST"},
AllowedHeaders: []string{"Content-Type"},
},
requestMethod: "GET",
requestOrigin: "https://example.com",
requestHeaders: map[string]string{},
wantStatus: http.StatusOK,
wantHeaders: http.Header{
"Access-Control-Allow-Origin": []string{"https://example.com"},
"Access-Control-Allow-Methods": []string{"GET, POST"},
"Access-Control-Allow-Headers": []string{"Content-Type"},
},
expectNext: true,
},
{
name: "POST request with disallowed origin",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET", "POST"},
},
requestMethod: "POST",
requestOrigin: "https://malicious.com",
requestHeaders: map[string]string{},
wantStatus: http.StatusOK,
wantHeaders: http.Header{},
expectNext: true,
},
{
name: "GET request without origin header",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{"https://example.com"},
AllowedMethods: []string{"GET"},
},
requestMethod: "GET",
requestOrigin: "",
requestHeaders: map[string]string{},
wantStatus: http.StatusOK,
wantHeaders: http.Header{},
expectNext: true,
},
{
name: "GET request with empty allowed origins (denies all)",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{},
AllowedMethods: []string{"GET"},
},
requestMethod: "GET",
requestOrigin: "https://any-origin.com",
requestHeaders: map[string]string{},
wantStatus: http.StatusOK,
wantHeaders: http.Header{},
expectNext: true,
},
{
name: "GET request with nil allowed origins (allows all)",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: nil,
AllowedMethods: []string{"GET"},
},
requestMethod: "GET",
requestOrigin: "https://any-origin.com",
requestHeaders: map[string]string{},
wantStatus: http.StatusOK,
wantHeaders: http.Header{
"Access-Control-Allow-Origin": []string{"https://any-origin.com"},
},
expectNext: true,
},
{
name: "GET request with multiple allowed origins",
opts: middleware.CORSOptions{ //nolint:exhaustruct
AllowedOrigins: []string{
"https://example.com",
"https://another-example.com",
"https://third-example.com",
},
AllowedMethods: []string{"GET"},
},
requestMethod: "GET",
requestHeaders: map[string]string{},
requestOrigin: "https://another-example.com",
wantStatus: http.StatusOK,
wantHeaders: http.Header{
"Access-Control-Allow-Origin": []string{"https://another-example.com"},
},
expectNext: true,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
// Setup router with CORS middleware
router := gin.New()
nextCalled := false
router.Use(middleware.CORS(tc.opts))
router.Any("/test", func(c *gin.Context) {
nextCalled = true
c.Status(http.StatusOK)
})
// Create request
req := httptest.NewRequest(tc.requestMethod, "/test", nil)
if tc.requestOrigin != "" {
req.Header.Set("Origin", tc.requestOrigin)
}
// Add any additional request headers
for key, value := range tc.requestHeaders {
req.Header.Set(key, value)
}
// Record response
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
// Check status code
if w.Code != tc.wantStatus {
t.Errorf("expected status %d, got %d", tc.wantStatus, w.Code)
}
// Check expected headers using cmp.Diff
// Only compare headers that are expected
gotHeaders := make(http.Header)
for key := range tc.wantHeaders {
if values := w.Header().Values(key); len(values) > 0 {
gotHeaders[key] = values
}
}
if diff := cmp.Diff(tc.wantHeaders, gotHeaders); diff != "" {
t.Errorf("response headers mismatch (-want +got):\n%s", diff)
}
// Check if Next() was called
if nextCalled != tc.expectNext {
t.Errorf("expected Next() called to be %v, got %v", tc.expectNext, nextCalled)
}
})
}
}

View File

@@ -1,69 +0,0 @@
package oapi
import (
"fmt"
"log/slog"
"net/http"
"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/gin-gonic/gin"
"github.com/nhost/nhost/internal/lib/oapi/example/api"
"github.com/nhost/nhost/internal/lib/oapi/middleware"
)
func surfaceErrorsMiddleWare(c *gin.Context) {
// this captures two cases as far as I can see:
// 1. request validation errors where the strict generated code fails
// to bind the request to the struct (i.e. "invalid param" test)
// 2. when a handler returns an error instead of a response
c.Next()
if len(c.Errors) > 0 && !c.IsAborted() {
var errorCode string
switch c.Writer.Status() {
case http.StatusBadRequest:
errorCode = "bad-request"
default:
errorCode = "internal-server-error"
}
c.JSON(
c.Writer.Status(),
gin.H{"errors": errorCode, "message": c.Errors[0].Error()},
)
}
}
// NewRouter creates a Gin router with OpenAPI request validation middleware.
func NewRouter(
schema []byte,
apiPrefix string,
authenticationFunc openapi3filter.AuthenticationFunc,
corsOptions middleware.CORSOptions,
logger *slog.Logger,
) (*gin.Engine, func(c *gin.Context), error) {
router := gin.New()
loader := openapi3.NewLoader()
doc, err := loader.LoadFromData(schema)
if err != nil {
return nil, nil, fmt.Errorf("failed to load OpenAPI schema: %w", err)
}
doc.AddServer(&openapi3.Server{ //nolint:exhaustruct
URL: apiPrefix,
})
router.Use(
gin.Recovery(),
surfaceErrorsMiddleWare,
middleware.Logger(logger),
middleware.CORS(corsOptions),
)
mw := api.MiddlewareFunc(requestValidatorWithOptions(doc, authenticationFunc))
return router, mw, nil
}

View File

@@ -1,128 +0,0 @@
package oapi
import (
"context"
"errors"
"fmt"
"net/http"
"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/getkin/kin-openapi/routers"
"github.com/getkin/kin-openapi/routers/gorillamux"
"github.com/gin-gonic/gin"
)
type ContextKey string
const (
GinContextKey ContextKey = "nhost-oapi/gin-context"
)
func handleError(c *gin.Context, err error) {
var (
errReq *openapi3filter.RequestError
errSchema *openapi3.SchemaError
errAuth *AuthenticatorError
errSec *openapi3filter.SecurityRequirementsError
)
switch {
case errors.As(err, &errSchema):
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "schema-validation-error",
"reason": errSchema.Reason,
})
case errors.As(err, &errReq):
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "request-validation-error",
"reason": errReq.Err.Error(),
})
case errors.As(err, &errAuth):
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"error": errAuth.Code,
"reason": errAuth.Message,
"securityScheme": errAuth.Scheme,
})
case errors.As(err, &errSec):
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"error": "unauthorized",
"reason": errSec.Error(),
})
default:
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
}
func requestValidatorWithOptions(
swagger *openapi3.T,
authFn openapi3filter.AuthenticationFunc,
) gin.HandlerFunc {
router, err := gorillamux.NewRouter(swagger)
if err != nil {
panic(err)
}
return func(c *gin.Context) {
if err := validateRequestFromContext(c, router, authFn); err != nil {
handleError(c, err)
}
c.Next()
}
}
func validateRequestFromContext(
c *gin.Context,
router routers.Router,
authFn openapi3filter.AuthenticationFunc,
) error {
route, pathParams, err := router.FindRoute(c.Request)
if err != nil {
var e *routers.RouteError
switch {
case errors.As(err, &e):
return e
default:
return fmt.Errorf("error validating route: %w", err)
}
}
validationInput := &openapi3filter.RequestValidationInput{ //nolint:exhaustruct
Request: c.Request,
PathParams: pathParams,
Route: route,
Options: &openapi3filter.Options{
AuthenticationFunc: authFn,
ExcludeRequestBody: false,
ExcludeRequestQueryParams: false,
ExcludeResponseBody: false,
ExcludeReadOnlyValidations: false,
ExcludeWriteOnlyValidations: false,
IncludeResponseStatus: false,
MultiError: false,
RegexCompiler: nil,
SkipSettingDefaults: false,
},
}
requestContext := context.WithValue(c.Request.Context(), GinContextKey, c)
if err := openapi3filter.ValidateRequest(requestContext, validationInput); err != nil {
return err //nolint:wrapcheck
}
return nil
}
func GetGinContext(c context.Context) *gin.Context {
v := c.Value(GinContextKey)
if v == nil {
return nil
}
ginCtx, ok := v.(*gin.Context)
if !ok {
return nil
}
return ginCtx
}

View File

@@ -114,13 +114,13 @@ in
echo " Running golangci-lint"
golangci-lint run \
--timeout 600s \
./...
./${submodule}/...
echo " Running tests"
richgo test \
-tags="${pkgs.lib.strings.concatStringsSep " " tags}" \
-ldflags="${pkgs.lib.strings.concatStringsSep " " ldflags}" \
-v ${goTestFlags} ./...
-v ${goTestFlags} ./${submodule}/...
${extraCheck}

View File

@@ -1,24 +1,3 @@
## [@nhost/nhost-js@4.1.0] - 2025-11-04
### 🚀 Features
- *(nhost-js)* Added pushChainFunction to functions and graphql clients (#3610)
- *(nhost-js)* Added various middlewares to work with headers and customizable createNhostClient (#3612)
- *(auth)* Added endpoints to retrieve and refresh oauth2 providers' tokens (#3614)
### 🐛 Bug Fixes
- *(dashboard)* Run audit and lint in dashboard (#3578)
- *(nhost-js)* Improvements to Session guard to avoid conflict with ProviderSession (#3662)
### ⚙️ Miscellaneous Tasks
- *(nhost-js)* Generate code from local API definitions (#3583)
- *(docs)* Udpated README.md and CONTRIBUTING.md (#3587)
- *(nhost-js)* Regenerate types (#3648)
# Changelog
All notable changes to this project will be documented in this file.

View File

Before

Width:  |  Height:  |  Size: 559 KiB

After

Width:  |  Height:  |  Size: 559 KiB

View File

@@ -1,7 +1,7 @@
import { createServer } from 'http'
import { Context, createStripeGraphQLServer } from '../src/index'
import { type Context, createStripeGraphQLServer } from '../src/index'
const isAllowed = (stripeCustomerId: string, context: Context) => {
const isAllowed = (_stripeCustomerId: string, context: Context) => {
const { isAdmin } = context
if (isAdmin) {

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/stripe-graphql-js",
"version": "1.2.0",
"version": "1.3.0-beta.6",
"description": "Stripe GraphQL API",
"license": "MIT",
"keywords": [
@@ -17,8 +17,8 @@
"type": "git",
"url": "https://github.com/nhost/nhost.git"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
"source": "src/index.ts",
"files": [
"dist",
@@ -43,15 +43,16 @@
"@pothos/core": "^3.41.0",
"graphql": "16.8.1",
"graphql-scalars": "^1.23.0",
"graphql-yoga": "^3.9.1",
"graphql-yoga": "^5.16.0",
"jsonwebtoken": "^9.0.2",
"stripe": "^11.18.0"
},
"devDependencies": {
"@types/jsonwebtoken": "^9.0.6",
"@types/node": "^18.19.28",
"@types/node": "^20.14.8",
"dotenv": "^16.4.5",
"ts-node-dev": "^2.0.0",
"typescript": "^4.9.5"
"tslib": "^2.8.1",
"typescript": "^5.8.3"
}
}
}

1096
packages/stripe-graphql-js/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -18,11 +18,11 @@ const createStripeGraphQLServer = ({
// check if using correct `x-hasura-admin-secret` header
const adminSecretFromHeader = request.headers.get('x-hasura-admin-secret')
const adminSecret = process.env.NHOST_ADMIN_SECRET
const adminSecret = process.env['NHOST_ADMIN_SECRET']
// check if the request is from Hasura
const nhostWebhookSecretFromHeader = request.headers.get('x-nhost-webhook-secret')
const nhostWebhookSecret = process.env.NHOST_WEBHOOK_SECRET
const nhostWebhookSecret = process.env['NHOST_WEBHOOK_SECRET']
const role = request.headers.get('x-hasura-role')
// variables

View File

@@ -3,11 +3,11 @@ import Stripe from 'stripe'
import { UserHasuraClaims } from './types'
if (!process.env.STRIPE_SECRET_KEY) {
if (!process.env['STRIPE_SECRET_KEY']) {
throw new Error('STRIPE_SECRET_KEY env var is not set')
}
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
export const stripe = new Stripe(process.env['STRIPE_SECRET_KEY'], {
apiVersion: '2022-11-15'
})
@@ -21,11 +21,11 @@ export const getUserClaims = (req: Request): UserHasuraClaims | undefined => {
return undefined
}
if (!process.env.NHOST_JWT_SECRET) {
if (!process.env['NHOST_JWT_SECRET']) {
throw new Error('NHOST_JWT_SECRET env var is not set')
}
const jwtSecret = JSON.parse(process.env.NHOST_JWT_SECRET)
const jwtSecret = JSON.parse(process.env['NHOST_JWT_SECRET'])
const decodedToken = jwt.verify(accessToken, jwtSecret.key) as any
return decodedToken['https://hasura.io/jwt/claims'] as UserHasuraClaims

View File

@@ -0,0 +1,14 @@
{
"extends": "../../build/configs/tsconfig/library.json",
"compilerOptions": {
"verbatimModuleSyntax": false,
"outDir": "./dist"
},
"include": ["src/**/*"],
"ts-node": {
"compilerOptions": {
"module": "commonjs",
"verbatimModuleSyntax": false
}
}
}

View File

@@ -1,23 +1,3 @@
## [auth@0.43.0] - 2025-11-04
### 🚀 Features
- *(auth)* Encrypt TOTP secret (#3619)
- *(auth)* Added endpoints to retrieve and refresh oauth2 providers' tokens (#3614)
- *(auth)* If the callback state is wrong send back to the redirectTo as provider_state (#3649)
- *(internal/lib)* Common oapi middleware for go services (#3663)
### 🐛 Bug Fixes
- *(auth)* Dont mutate client URL (#3660)
### ⚙️ Miscellaneous Tasks
- *(docs)* Fix broken link in openapi spec and minor mistakes in postmark integration info (#3621)
- *(nixops)* Bump go to 1.25.3 and nixpkgs due to CVEs (#3652)
# Changelog
All notable changes to this project will be documented in this file.

View File

@@ -115,13 +115,13 @@ import (
"context"
"github.com/nhost/nhost/services/auth/go/api"
oapimw "github.com/nhost/nhost/internal/lib/oapi/middleware"
"github.com/nhost/nhost/services/auth/go/middleware"
)
func (ctrl *Controller) YourEndpoint( //nolint:ireturn
ctx context.Context, request api.YourEndpointRequestObject,
) (api.YourEndpointResponseObject, error) {
logger := oapimw.LoggerFromContext(ctx)
logger := middleware.LoggerFromContext(ctx)
// Validate inputs
if apiErr := ctrl.wf.ValidateInput(request.Body.Field, logger); apiErr != nil {

View File

@@ -0,0 +1,35 @@
package cmd
import (
"net/http"
"github.com/gin-gonic/gin"
)
func cors() gin.HandlerFunc {
f := func(c *gin.Context, origin string) {
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Methods", "POST, GET")
headers := c.Request.Header.Get("Access-Control-Request-Headers")
c.Header("Access-Control-Allow-Headers", headers)
c.Header("Access-Control-Allow-Credentials", "true")
c.Header("Access-Control-Max-Age", "86400")
c.Writer.Header().Add("Vary", "Origin, Access-Control-Request-Method")
}
return func(c *gin.Context) {
origin := c.Request.Header.Get("Origin")
if c.Request.Method == http.MethodOptions {
f(c, origin)
c.Header("Content-Length", "0")
c.AbortWithStatus(http.StatusNoContent)
}
if origin != "" {
f(c, origin)
}
c.Next()
}
}

Some files were not shown because too many files have changed in this diff Show More