Compare commits

..

140 Commits

Author SHA1 Message Date
Pilou
95f62bed07 Merge pull request #1644 from nhost/changeset-release/main
chore: update versions
2023-02-22 08:50:38 +01:00
Pierre-Louis Mercereau
0e4d8ff118 chore: manually bump @nhost/react-apollo 2023-02-21 18:20:41 +01:00
github-actions[bot]
baec5bada7 chore: update versions 2023-02-21 17:03:03 +00:00
Pilou
4e56cfc628 Merge pull request #1348 from nhost/sdk-next-major
Sdk next major version
2023-02-21 18:01:13 +01:00
Pierre-Louis Mercereau
54bc91923f docs: update changeset 2023-02-21 12:40:52 +01:00
Szilárd Dóró
77b12feb95 Merge pull request #1639 from nhost/renovate/testing-library-react-14.x
chore(deps): update dependency @testing-library/react to v14
2023-02-20 16:30:11 +01:00
Pierre-Louis Mercereau
32d4670bbb Merge branch 'main' into sdk-next-major 2023-02-20 16:05:23 +01:00
Pilou
1dc09942d2 Merge pull request #1587 from nhost/next-client
Next GraphQL client
2023-02-20 16:01:49 +01:00
Szilárd Dóró
3343a36358 chore(deps): bump @testing-library 2023-02-20 15:52:18 +01:00
Pierre-Louis Mercereau
48866d0ee1 chore: fail on runtime when passing an invalid field 2023-02-20 12:45:52 +01:00
renovate[bot]
5b3b76bd41 chore(deps): update dependency @testing-library/react to v14 2023-02-20 10:08:36 +00:00
Pierre-Louis Mercereau
284ef7e7f2 test: multiple where 2023-02-17 08:57:02 +01:00
Pierre-Louis Mercereau
6d5c202da9 changes 2023-02-17 08:44:48 +01:00
Pierre-Louis Mercereau
9342937440 readme 2023-02-15 13:39:24 +01:00
Pierre-Louis Mercereau
e89cd4e262 simple mutation example 2023-02-15 13:30:16 +01:00
Pierre-Louis Mercereau
a05438352b inline documentation 2023-02-15 13:28:04 +01:00
Pierre-Louis Mercereau
78437959bb dew 2023-02-15 13:08:20 +01:00
Pierre-Louis Mercereau
e1a7433adb docs: static doc for nhost.functions 2023-02-15 12:41:54 +01:00
Pierre-Louis Mercereau
e23cf74975 fix tests 2023-02-10 22:11:53 +01:00
Pierre-Louis Mercereau
a3d01c4fad fix lint config 2023-02-10 21:33:26 +01:00
Pierre-Louis Mercereau
4cdcef9ef5 fix broken links 2023-02-10 19:12:29 +01:00
Pierre-Louis Mercereau
df894ef7e2 upgrade typescript version 2023-02-10 15:51:59 +01:00
Pierre-Louis Mercereau
f7dd6a9fc6 deactivate functions doc 2023-02-10 14:42:56 +01:00
Pierre-Louis Mercereau
2949ff0f62 fix docgen 2023-02-10 14:33:56 +01:00
Pierre-Louis Mercereau
1527b0a455 remove type-fest dependency 2023-02-06 14:18:13 +01:00
Pierre-Louis Mercereau
375e53a3f0 update ts 2023-02-06 13:35:33 +01:00
Pierre-Louis Mercereau
96e3ca5a32 basic readme 2023-02-06 12:53:11 +01:00
Pierre-Louis Mercereau
0e570df9c5 missing dependency 2023-02-06 12:11:02 +01:00
Pierre-Louis Mercereau
1f4c67283e lockfile 2023-02-06 10:49:47 +01:00
Pierre-Louis Mercereau
fc1c4861a3 cleanup 2023-02-06 10:49:02 +01:00
Pierre-Louis Mercereau
74feaf6add unions 2023-02-02 11:47:29 +01:00
Pierre-Louis Mercereau
8cd97206cc Merge branch 'next-client' of https://github.com/nhost/nhost into next-client 2023-01-31 21:06:17 +01:00
Pierre-Louis Mercereau
02197639f2 dew 2023-01-31 20:59:14 +01:00
Pilou
38b594aef9 Update README.md 2023-01-31 19:40:31 +01:00
Pierre-Louis Mercereau
f3a8886cd0 dew 2023-01-31 19:08:19 +01:00
Pierre-Louis Mercereau
8d76cf8d40 simplify 2023-01-31 17:37:44 +01:00
Pierre-Louis Mercereau
3e1fb974e4 dew 2023-01-31 16:37:40 +01:00
Pierre-Louis Mercereau
f74871d872 dew 2023-01-31 15:01:54 +01:00
Pierre-Louis Mercereau
3f26056688 Merge branch 'main' into sdk-next-major 2023-01-30 11:11:51 +01:00
Pierre-Louis Mercereau
6a7801be93 chore: update changeset 2023-01-10 09:10:33 +01:00
Pierre-Louis Mercereau
7bc5bb857c chore: add the deprecated useAxios option 2023-01-10 09:02:45 +01:00
Pierre-Louis Mercereau
c957039d75 chore: update lock file 2023-01-09 20:17:12 +01:00
Pierre-Louis Mercereau
96c4032424 Merge branch 'main' into sdk-next-major 2023-01-09 20:13:13 +01:00
Pierre-Louis Mercereau
ec70126b56 fix: iso 8859-1 2023-01-09 19:25:02 +01:00
Pierre-Louis Mercereau
86b9f9040c Merge branch 'main' into sdk-next-major 2023-01-09 16:31:04 +01:00
Pierre-Louis Mercereau
222f03725b fix(dashboard): use fetch instead of axios 2023-01-06 16:42:40 +01:00
Pierre-Louis Mercereau
10b786e5c6 chore: fix lockfile 2023-01-06 16:30:22 +01:00
Pierre-Louis Mercereau
aa8ae88d12 Merge branch 'main' into sdk-next-major 2023-01-06 16:25:12 +01:00
Pilou
0f2c86b41a Merge pull request #1351 from nhost/refactor/cross-fetch
refactor: replace axios by cross-fetch
2023-01-06 16:17:03 +01:00
Pilou
a4c76892dd Update packages/hasura-storage-js/src/hasura-storage-api.ts
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2023-01-03 10:36:33 +01:00
Pierre-Louis Mercereau
00d278b2cc refactor: adjustments from review 2023-01-02 17:32:34 +01:00
Pilou
cb6b5faeb9 Update packages/hasura-storage-js/src/hasura-storage-client.ts
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2023-01-02 17:29:21 +01:00
Pierre-Louis Mercereau
7c4c847b91 Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-26 12:54:40 +01:00
Pierre-Louis Mercereau
908887d8c5 Merge branch 'main' into sdk-next-major 2022-12-26 12:54:19 +01:00
Pierre-Louis Mercereau
a2d67bc2db fix(dashboard): js error from error payload 2022-12-26 12:45:33 +01:00
Pierre-Louis Mercereau
1a6cd78254 Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-21 16:42:58 +01:00
Pierre-Louis Mercereau
6500629c4b Merge branch 'main' into sdk-next-major 2022-12-21 16:22:28 +01:00
Pierre-Louis Mercereau
add3c2c10e Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-21 14:29:00 +01:00
Pierre-Louis Mercereau
dd29b06260 Merge branch 'main' into sdk-next-major 2022-12-21 14:27:48 +01:00
Pierre-Louis Mercereau
490cb25a0f Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-20 10:13:18 +01:00
Pierre-Louis Mercereau
0df0dd741e Merge branch 'main' into sdk-next-major 2022-12-20 10:12:56 +01:00
Pierre-Louis Mercereau
2172946879 Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-20 09:17:50 +01:00
Pierre-Louis Mercereau
40e50f0e75 Merge branch 'main' into sdk-next-major 2022-12-20 09:15:30 +01:00
Pierre-Louis Mercereau
65cf0888b5 chore: extract patch changes 2022-12-16 12:14:38 +01:00
Pierre-Louis Mercereau
21833019ca chore: correct error from several mergers 2022-12-14 21:14:48 +01:00
Pierre-Louis Mercereau
b3171ba3e9 chore: remove lockfile 2022-12-14 20:40:16 +01:00
Pierre-Louis Mercereau
6f01f19d02 refactor: remove docgen 2022-12-14 20:33:03 +01:00
Pierre-Louis Mercereau
ce92b01eac Merge branch 'main' into sdk-next-major 2022-12-14 19:25:15 +01:00
Pierre-Louis Mercereau
e24a177434 Merge branch 'main' into sdk-next-major 2022-12-14 19:06:50 +01:00
Pierre-Louis Mercereau
56a52b6d48 chore: remove duplicate changesets 2022-12-12 16:45:42 +01:00
Pierre-Louis Mercereau
92bfa8c723 chore: phrasing 2022-12-12 16:03:07 +01:00
Pierre-Louis Mercereau
2a52aaa4a6 Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-12 14:46:39 +01:00
Pierre-Louis Mercereau
8280a3e9d8 chore: use explicit changeset links 2022-12-12 14:30:38 +01:00
Pierre-Louis Mercereau
523f60bf68 Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-12 14:20:28 +01:00
Pierre-Louis Mercereau
19b11d4084 chore: details on removed deprecations 2022-12-12 14:15:08 +01:00
Pierre-Louis Mercereau
805bae1507 chore: bump nextjs as major as React removed deprecated methods are reexported 2022-12-12 13:36:25 +01:00
Pierre-Louis Mercereau
f6c014c06f chore: correct changeset 2022-12-12 13:34:19 +01:00
Pierre-Louis Mercereau
c5794f4596 chore: improve changesets 2022-12-12 13:32:09 +01:00
Pierre-Louis Mercereau
fc28817380 chore: explain xhr in changeset 2022-12-12 10:06:56 +01:00
Pierre-Louis Mercereau
80bbd3a165 chore: changesets 2022-12-12 10:02:21 +01:00
Pierre-Louis Mercereau
7a10617a72 test: simplify email verification test 2022-12-12 09:26:02 +01:00
Pierre-Louis Mercereau
f0b6dca1a5 Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-08 14:28:03 +01:00
Szilárd Dóró
5db20adc34 fix(react): eliminate error when testing the project 2022-12-08 12:01:05 +01:00
Pierre-Louis Mercereau
12dc41a517 test: TypedDocumentNode 2022-12-08 09:07:46 +01:00
Pierre-Louis Mercereau
768fd56891 feat: graphql-typed-document-node 2022-12-07 21:53:21 +01:00
Pierre-Louis Mercereau
8a508cb1cc chore: run CI on evey pull request, not only the ones to main 2022-12-07 20:47:26 +01:00
Pierre-Louis Mercereau
34f6a8eef4 refactor: upload progress with XHR 2022-12-07 19:48:34 +01:00
Pierre-Louis Mercereau
c9d2d31a9b feat: nhost.graphql.httpUrl and nhost.graphql.wsUrl 2022-12-07 18:53:58 +01:00
Pierre-Louis Mercereau
68fb23a361 refactor: remove last pieces of axios 2022-12-07 17:16:42 +01:00
Pierre-Louis Mercereau
476139e528 refactor: remove axios from hasura-storage-js, with breaking change 2022-12-07 13:27:34 +01:00
Pierre-Louis Mercereau
6a850818a0 Merge branch 'sdk-next-major' into refactor/cross-fetch 2022-12-07 11:41:55 +01:00
Pilou
3970dbba0d Merge pull request #1342 from nhost/chore/improve-internal-dependencies
chore: improve internal dependencies
2022-12-07 11:40:02 +01:00
Pierre-Louis Mercereau
8ee2166f0d fix: correct nhost clients 2022-12-07 11:08:54 +01:00
Szilárd Dóró
e13500a185 fix(docgen): correct class references when used as interface members 2022-12-07 10:47:04 +01:00
Pierre-Louis Mercereau
411f574a51 refactor: re-export @nhost/react in @nhost/nextjs 2022-12-07 09:47:45 +01:00
Szilárd Dóró
7fc91b992e chore: cleanup dependencies, fix references 2022-12-07 08:59:06 +01:00
Pierre-Louis Mercereau
b840012be0 fix: correct fetch errors 2022-12-07 08:56:11 +01:00
Pierre-Louis Mercereau
645c51a9dc refactor: 💡 replace axios by cross-fetch, step 1
Changes not done yet in `nhost.auth.graphql` (will soon use
graphql-request instead) and the upload machines (depends on prrogress)
2022-12-06 22:08:46 +01:00
Pierre-Louis Mercereau
0ce6f05539 Merge branch 'sdk-next-major' into chore/improve-internal-dependencies 2022-12-06 14:10:19 +01:00
Pierre-Louis Mercereau
8b1188af53 Merge branch 'main' into sdk-next-major 2022-12-06 14:08:55 +01:00
Pilou
12b01f8dee Merge pull request #1298 from nhost/fix/react-strict-mode
fix: react strict mode
2022-12-06 14:06:07 +01:00
Pierre-Louis Mercereau
60f4faf409 chore: remove @nhost/core from changeset 2022-12-06 13:05:45 +01:00
Pierre-Louis Mercereau
528dff3f1b Merge branch 'sdk-next-major' into fix/react-strict-mode 2022-12-06 12:52:33 +01:00
Pierre-Louis Mercereau
d429fb4a3e Merge branch 'sdk-next-major' into chore/improve-internal-dependencies 2022-12-06 12:41:25 +01:00
Pilou
816c916709 Merge pull request #1233 from nhost/docs/hide-old-deprecations
chore: remove deprecated methods
2022-12-06 12:40:42 +01:00
Pierre-Louis Mercereau
b7a2b8b537 docs: update installation instructions 2022-12-06 10:50:40 +01:00
Pierre-Louis Mercereau
261d8cf434 merge 2022-12-06 10:10:13 +01:00
Pierre-Louis Mercereau
41f49bde76 Merge branch 'sdk-next-major' into chore/improve-internal-dependencies 2022-12-06 10:06:25 +01:00
Pilou
65f685bdb2 Update packages/core/src/client.ts
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2022-12-06 09:57:29 +01:00
Pilou
f52a7f4aac Update packages/core/src/machines/index.ts
Co-authored-by: Szilárd Dóró <doroszilard@icloud.com>
2022-12-06 09:57:01 +01:00
Pierre-Louis Mercereau
e71b9903d9 Merge branch 'sdk-next-major' into docs/hide-old-deprecations 2022-12-06 09:50:40 +01:00
Pilou
325fd08aef Merge pull request #1246 from nhost/refactor/merge-core
refactor: decommission `@nhost/core`
2022-12-06 09:46:50 +01:00
Pierre-Louis Mercereau
3888704464 chore: remove comment 2022-12-06 09:23:31 +01:00
Pierre-Louis Mercereau
38e8a10a29 chore: 🤖 remove lockfile 2022-12-06 09:19:02 +01:00
Pierre-Louis Mercereau
d8545eae12 chore: 🤖 add changeset 2022-12-06 09:18:16 +01:00
Pierre-Louis Mercereau
3d5bfd87d2 refactor: simplify 2022-12-06 08:59:11 +01:00
Pierre-Louis Mercereau
e66c5626bd fix: don't fetch session when present in initial state 2022-12-05 23:14:17 +01:00
Pierre-Louis Mercereau
a227c6561e refactor: work with nextjs 2022-12-05 23:09:26 +01:00
Pierre-Louis Mercereau
e885c159df refactor: simplify onStart 2022-12-05 14:53:10 +01:00
Pierre-Louis Mercereau
09fcb74bef refactor: use Johan's function name 2022-12-05 14:31:03 +01:00
Pierre-Louis Mercereau
a089197197 Merge branch 'main' into fix/react-strict-mode 2022-12-05 14:29:27 +01:00
Pierre-Louis Mercereau
34f843875b Merge branch 'main' into fix/react-strict-mode 2022-12-05 12:15:01 +01:00
Pierre-Louis Mercereau
ca278a8c39 Merge branch 'main' into fix/react-strict-mode 2022-12-05 11:54:01 +01:00
Pierre-Louis Mercereau
75603786e0 refactor: 💡 Remove unused immer dependency 2022-12-05 11:43:47 +01:00
Pierre-Louis Mercereau
4e4e699b94 refactor: adapt to nextjs 2022-12-05 11:39:36 +01:00
Pierre-Louis Mercereau
da31fa9fba ci: explicit pnpm run 2022-12-02 20:46:25 +01:00
Pierre-Louis Mercereau
95e2afaf47 Merge branch 'main' into fix/react-strict-mode 2022-12-02 15:46:13 +01:00
Pierre-Louis Mercereau
958a56dde9 fix: adapt to nextjs 2022-12-02 15:11:08 +01:00
Pierre-Louis Mercereau
74cb15930e Merge branch 'main' into fix/react-strict-mode 2022-12-02 13:35:53 +01:00
Pierre-Louis Mercereau
aa37a98424 Merge branch 'main' into fix/react-strict-mode 2022-12-02 13:27:37 +01:00
Pierre-Louis Mercereau
11cbdda3a5 Merge branch 'main' into fix/react-strict-mode 2022-12-02 13:20:55 +01:00
Pierre-Louis Mercereau
6d1f4adf10 chore: update changeset 2022-12-02 13:16:31 +01:00
Pierre-Louis Mercereau
ddbc50c15e refactor: avoid ambiguous interpreter getter/setter 2022-12-02 13:15:04 +01:00
Pierre-Louis Mercereau
b2cbf570a3 fix: 🐛 don't throw error when re-setting the interpreter 2022-12-02 12:08:52 +01:00
Pierre-Louis Mercereau
22b8e65031 fix: 🐛 onstart only when interpreter is initialised 2022-12-02 11:26:14 +01:00
Pierre-Louis Mercereau
63c94d2036 chore: fine-tune (peer) dependencies 2022-11-30 12:56:46 +01:00
Pierre-Louis Mercereau
010df48c1e chore: remove deprecations 2022-11-28 20:44:24 +01:00
Pierre-Louis Mercereau
fdc11db93d Merge branch 'main' into docs/hide-old-deprecations 2022-11-28 20:18:26 +01:00
Pierre-Louis Mercereau
cb4749f168 chore: fix lint 2022-11-28 15:53:54 +01:00
Pierre-Louis Mercereau
46a8fcf471 docs: hide > 6m.o. deprecations in the generated documentation 2022-11-28 15:34:09 +01:00
222 changed files with 17839 additions and 1441 deletions

View File

@@ -40,14 +40,14 @@ runs:
- shell: bash
name: Build packages
if: ${{ inputs.BUILD == 'all' }}
run: pnpm build:all
run: pnpm run build:all
env:
TURBO_TOKEN: ${{ inputs.TURBO_TOKEN }}
TURBO_TEAM: ${{ inputs.TURBO_TEAM }}
- shell: bash
name: Build everything in the monorepo
if: ${{ inputs.BUILD == 'default' }}
run: pnpm build
run: pnpm run build
env:
TURBO_TOKEN: ${{ inputs.TURBO_TOKEN }}
TURBO_TEAM: ${{ inputs.TURBO_TEAM }}

View File

@@ -8,7 +8,6 @@ on:
- '**.md'
- 'LICENSE'
pull_request:
branches: [main]
types: [opened, synchronize]
paths-ignore:
- 'assets/**'
@@ -56,7 +55,7 @@ jobs:
| xargs -I@ realpath --relative-to=$PWD @ \
| xargs -I@ jq "if (.scripts.e2e | length) != 0 then {name: .name, path: \"@\"} else null end" @/package.json \
| awk "!/null/" \
| jq -c --slurp)
| jq -c --slurp 'map(select(length > 0))')
echo "matrix=$PACKAGES" >> $GITHUB_OUTPUT
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}

View File

@@ -45,6 +45,9 @@
"@nhost/docgen": [
"../packages/docgen/src/index.ts"
],
"@nhost/graphql-js": [
"../packages/graphql-js/src/index.ts"
],
"@nhost/hasura-auth-js": [
"../packages/hasura-auth-js/src/index.ts"
],

View File

@@ -1,7 +1,6 @@
import replace from '@rollup/plugin-replace'
import fs from 'fs'
import path from 'path'
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import tsconfigPaths from 'vite-tsconfig-paths'
@@ -61,7 +60,6 @@ export default defineConfig({
'@apollo/client/utilities': '@apollo/client/utilities',
'graphql-ws': 'graphql-ws',
xstate: 'xstate',
axios: 'axios',
'js-cookie': 'Cookies',
react: 'React',
'react-dom': 'ReactDOM',

View File

@@ -1,5 +1,13 @@
# @nhost/dashboard
## 0.11.13
### Patch Changes
- 3343a363: chore(dashboard): bump `@testing-library/react` to v14 and `@testing-library/dom` to v9
- @nhost/react-apollo@5.0.1
- @nhost/nextjs@1.13.6
## 0.11.12
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/dashboard",
"version": "0.11.12",
"version": "0.11.13",
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",
@@ -44,7 +44,6 @@
"@tanstack/react-table": "^8.5.30",
"@tanstack/react-virtual": "^3.0.0-beta.23",
"analytics-node": "^6.2.0",
"axios": "^0.27.2",
"bcryptjs": "^2.4.3",
"clsx": "^1.2.1",
"cross-fetch": "^3.1.5",
@@ -98,9 +97,9 @@
"@storybook/manager-webpack5": "^6.5.14",
"@storybook/react": "^6.5.14",
"@storybook/testing-library": "^0.0.13",
"@testing-library/dom": "^8.19.0",
"@testing-library/dom": "^9.0.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/lodash.debounce": "^4.0.7",
"@types/node": "^16.11.7",

View File

@@ -277,7 +277,7 @@ export default function FilesDataGrid(props: FilesDataGridProps) {
}
if (fileError) {
throw fileError;
throw new Error(fileError.message);
}
triggerToast(`File has been uploaded successfully (${fileMetadata?.id})`);

View File

@@ -67,7 +67,7 @@ export function InviteAnnounce() {
triggerToast('An error occurred when trying to accept the invitation.');
return setSubmitState({
error: res.error,
error: new Error(res.error.message),
loading: false,
});
}

View File

@@ -107,7 +107,7 @@ export default function SystemEnvironmentVariableSettings() {
),
},
{ key: 'NHOST_AUTH_URL', value: appClient.auth.url },
{ key: 'NHOST_GRAPHQL_URL', value: appClient.graphql.url },
{ key: 'NHOST_GRAPHQL_URL', value: appClient.graphql.httpUrl },
{ key: 'NHOST_STORAGE_URL', value: appClient.storage.url },
{ key: 'NHOST_FUNCTIONS_URL', value: appClient.functions.url },
];

View File

@@ -6,7 +6,7 @@ import Input from '@/ui/v2/Input';
import generateAppServiceUrl from '@/utils/common/generateAppServiceUrl';
import { getToastStyleProps } from '@/utils/settings/settingsConstants';
import { yupResolver } from '@hookform/resolvers/yup';
import axios from 'axios';
import fetch from 'cross-fetch';
import { useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { toast } from 'react-hot-toast';
@@ -79,10 +79,10 @@ export default function CreateUserForm({
try {
await toast.promise(
axios.post(signUpUrl, {
email,
password,
}),
fetch(signUpUrl, {
method: 'POST',
body: JSON.stringify({ email, password }),
}).then((res) => res.json()),
{
loading: 'Creating user...',
success: 'User created successfully.',

View File

@@ -28,7 +28,7 @@ The GraphQL API is available at `https://[subdomain].graphql.[region].nhost.run/
## GraphQL Clients for JavaScript
The [Nhost JavaScript client](/reference/javascript) comes with a simple [GraphQL client](/reference/javascript/nhost-js/graphql) that works well for the backend or simple applications.
The [Nhost JavaScript client](/reference/javascript) comes with a simple [GraphQL client](/reference/javascript/graphql) that works well for the backend or simple applications.
When building more complex frontend applications, we recommend using a more advanced GraphQL client such as:

View File

@@ -10,8 +10,8 @@ In this section:
- [Overview](/reference/javascript)
- [Authentication](/reference/javascript/auth)
- [Storage](/reference/javascript/storage)
- [Functions](/reference/javascript/nhost-js/functions)
- [GraphQL](/reference/javascript/nhost-js/graphql)
- [Functions](/reference/javascript/functions)
- [GraphQL](/reference/javascript/graphql)
### React

View File

@@ -0,0 +1,60 @@
---
title: call()
sidebar_label: call()
slug: /reference/javascript/functions/call
description: Use `nhost.functions.call` to call (sending a POST request to) a serverless function.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/nhost-js/src/clients/functions/index.ts#L55
---
# `call()`
## Overload 1 of 2
Use `nhost.functions.call` to call (sending a POST request to) a serverless function.
:::caution Deprecated
Axios will be replaced by cross-fetch in the near future. Only the headers configuration will be kept.
:::
### Parameters
---
**<span className="parameter-name">url</span>** <span className="optional-status">required</span> <code>string</code>
---
**<span className="parameter-name">data</span>** <span className="optional-status">optional</span> <code>D</code>
---
**<span className="parameter-name">config</span>** <span className="optional-status">optional</span> <code>AxiosRequestConfig&lt;any&gt; &amp; { useAxios: "true" } &amp; [`NhostFunctionCallConfig`](/reference/javascript/functions/types/nhost-function-call-config) &amp; { useAxios: "true" }</code>
---
## Overload 2 of 2
Use `nhost.functions.call` to call (sending a POST request to) a serverless function.
```ts
await nhost.functions.call('send-welcome-email', {
email: 'joe@example.com',
name: 'Joe Doe'
})
```
### Parameters
---
**<span className="parameter-name">url</span>** <span className="optional-status">required</span> <code>string</code>
---
**<span className="parameter-name">data</span>** <span className="optional-status">required</span> <code>D</code>
---
**<span className="parameter-name">config</span>** <span className="optional-status">optional</span> <code>[`NhostFunctionCallConfig`](/reference/javascript/functions/types/nhost-function-call-config) &amp; { useAxios: "false" }</code>
---

View File

@@ -0,0 +1,23 @@
---
title: setAccessToken()
sidebar_label: setAccessToken()
slug: /reference/javascript/functions/set-access-token
description: Use `nhost.functions.setAccessToken` to a set an access token to be used in subsequent functions requests. Note that if you're signin in users with `nhost.auth.signIn()` the access token will be set automatically.
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/nhost-js/src/clients/functions/index.ts#L155
---
# `setAccessToken()`
Use `nhost.functions.setAccessToken` to a set an access token to be used in subsequent functions requests. Note that if you're signin in users with `nhost.auth.signIn()` the access token will be set automatically.
```ts
nhost.functions.setAccessToken('some-access-token')
```
## Parameters
---
**<span className="parameter-name">accessToken</span>** <span className="optional-status">required</span> <code>undefined &#124; string</code>
---

View File

@@ -0,0 +1,22 @@
---
title: NhostFunctionsClient
sidebar_label: Functions
description: No description provided.
slug: /reference/javascript/functions
custom_edit_url: https://github.com/nhost/nhost/edit/main/docs/docs/reference/javascript/functions/index.mdx
---
# `NhostFunctionsClient`
## Parameters
---
**<span className="parameter-name">params</span>** <span className="optional-status">required</span> [`NhostFunctionsConstructorParams`](/reference/javascript/functions/types/nhost-functions-constructor-params)
| Property | Type | Required | Notes |
| :--------------------------------------------------------------------------------------------- | :------------------ | :------: | :---------------------------------------------------------------------------------------- |
| <span className="parameter-name"><span className="light-grey">params.</span>url</span> | <code>string</code> | ✔️ | Serverless Functions endpoint. |
| <span className="parameter-name"><span className="light-grey">params.</span>adminSecret</span> | <code>string</code> | | Admin secret. When set, it is sent as an `x-hasura-admin-secret` header for all requests. |
---

View File

@@ -0,0 +1,19 @@
---
title: NhostFunctionCallConfig
sidebar_label: NhostFunctionCallConfig
description: Subset of RequestInit parameters that are supported by the functions client
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/nhost-js/src/clients/functions/types.ts#L41
---
# `NhostFunctionCallConfig`
Subset of RequestInit parameters that are supported by the functions client
## Parameters
---
**<span className="parameter-name">headers</span>** <span className="optional-status">optional</span> <code>Record&lt;string, string&gt;</code>
---

View File

@@ -0,0 +1,15 @@
---
title: NhostFunctionCallResponse
sidebar_label: NhostFunctionCallResponse
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/nhost-js/src/clients/functions/types.ts#L15
---
# `NhostFunctionCallResponse`
```ts
type NhostFunctionCallResponse =
| { res: { data: T; status: number; statusText: string }; error: null }
| { res: null; error: ErrorPayload }
```

View File

@@ -0,0 +1,25 @@
---
title: NhostFunctionsConstructorParams
sidebar_label: NhostFunctionsConstructorParams
description: No description provided.
displayed_sidebar: referenceSidebar
custom_edit_url: https://github.com/nhost/nhost/edit/main/packages/nhost-js/src/clients/functions/types.ts#L4
---
# `NhostFunctionsConstructorParams`
## Parameters
---
**<span className="parameter-name">url</span>** <span className="optional-status">required</span> <code>string</code>
Serverless Functions endpoint.
---
**<span className="parameter-name">adminSecret</span>** <span className="optional-status">optional</span> <code>string</code>
Admin secret. When set, it is sent as an `x-hasura-admin-secret` header for all requests.
---

View File

@@ -10,12 +10,12 @@ The Nhost JavaScript client is the primary way of interacting with your Nhost pr
- [Authentication](/reference/javascript/auth)
- [Storage](/reference/javascript/storage)
- [Functions](/reference/javascript/nhost-js/functions)
- [GraphQL](/reference/javascript/nhost-js/graphql)
- [Functions](/reference/javascript/functions)
- [GraphQL](/reference/javascript/graphql)
## Installation
Install the the Nhost client together with GraphQL:
Install the Nhost client together with GraphQL:
<Tabs groupId="package-manager">
<TabItem value="npm" label="npm" default>

View File

@@ -111,12 +111,12 @@ const sidebars = {
label: 'Functions',
link: {
type: 'doc',
id: 'reference/docgen/javascript/nhost-js/content/nhost-functions-client/index'
id: 'reference/javascript/functions/index'
},
items: [
{
type: 'autogenerated',
dirName: 'reference/docgen/javascript/nhost-js/content/nhost-functions-client/content'
dirName: 'reference/javascript/functions/content'
}
]
},
@@ -125,12 +125,12 @@ const sidebars = {
label: 'GraphQL',
link: {
type: 'doc',
id: 'reference/docgen/javascript/nhost-js/content/nhost-graphql-client/index'
id: 'reference/docgen/javascript/graphql/content/nhost-graphql-client/index'
},
items: [
{
type: 'autogenerated',
dirName: 'reference/docgen/javascript/nhost-js/content/nhost-graphql-client/content'
dirName: 'reference/docgen/javascript/graphql/content/nhost-graphql-client/content'
}
]
}

View File

@@ -18,6 +18,7 @@ export function authProtected(Comp) {
if (isLoading) {
return <div>Loading...</div>
}
return <Comp {...props} />
}
}

View File

@@ -35,8 +35,8 @@
"@types/react": "18.0.25",
"@xstate/inspect": "^0.6.2",
"eslint-config-next": "12.0.10",
"typescript": "4.5.5",
"typescript": "^4.8.2",
"ws": "^8.8.1",
"xstate": "^4.33.5"
}
}
}

View File

@@ -4,7 +4,7 @@
"version": "0.0.5",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"build": "vite build",
"preview": "vite preview",
"prettier": "prettier --check src/",
"prettier:fix": "prettier --write src/",
@@ -34,7 +34,7 @@
"@vitejs/plugin-vue": "^4.0.0",
"@xstate/inspect": "^0.6.2",
"sass": "1.32.0",
"typescript": "^4.8.4",
"typescript": "4.9.4",
"vite": "^4.0.2",
"vue-tsc": "^0.38.9"
},

View File

@@ -1,5 +1,15 @@
# @nhost/apollo
## 5.0.0
### Patch Changes
- Updated dependencies [c9d2d31a]
- Updated dependencies [80bbd3a1]
- Updated dependencies [80bbd3a1]
- Updated dependencies [2949ff0f]
- @nhost/nhost-js@2.0.0
## 4.13.4
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/apollo",
"version": "4.13.4",
"version": "5.0.0",
"description": "Nhost Apollo Client library",
"license": "MIT",
"keywords": [

View File

@@ -1,5 +1,14 @@
# @nhost/react-apollo
## 5.0.1
### Patch Changes
- Updated dependencies [19b11d40]
- Updated dependencies [19b11d40]
- @nhost/react@2.0.0
- @nhost/apollo@5.0.0
## 4.13.5
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/react-apollo",
"version": "4.13.5",
"version": "5.0.1",
"description": "Nhost React Apollo client",
"license": "MIT",
"keywords": [

View File

@@ -1,5 +1,13 @@
# @nhost/react-urql
## 2.0.0
### Patch Changes
- Updated dependencies [19b11d40]
- Updated dependencies [19b11d40]
- @nhost/react@2.0.0
## 1.0.5
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/react-urql",
"version": "1.0.5",
"version": "2.0.0",
"description": "Nhost React URQL client",
"license": "MIT",
"keywords": [

View File

@@ -0,0 +1,9 @@
const base = require('../../config/.eslintrc.js')
module.exports = {
...base,
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname
},
ignorePatterns: [...base.ignorePatterns, 'functions/**/*.ts']
}

View File

@@ -0,0 +1,140 @@
<h1 align="center">@nhost/graphql-js</h1>
<h2 align="center">Nhost GraphQL client</h2>
<p align="center">
<img alt="npm" src="https://img.shields.io/npm/v/@nhost/graphql-js">
<img alt="npm" src="https://img.shields.io/npm/dm/@nhost/graphql-js">
<a href="LICENSE">
<img src="https://img.shields.io/badge/license-MIT-yellow.svg" alt="license: MIT" />
</a>
</p>
Nhost GraphQL client.
## Install
First, install `graphql-codegen` and the Nhost Typescript plugin:
```sh
npm install @nhost/graphql-js
npm install -D @graphql-codegen/cli @graphql-codegen/typescript-nhost
```
## Configure the code generator
Configure the code generator by adding a `graphql.config.yaml` file:
```yaml filename="graphql.config.yaml"
schema:
- http://localhost:1337/v1/graphql:
headers:
x-hasura-admin-secret: nhost-admin-secret
generates:
./src/schema.ts:
plugins:
- typescript-nhost
```
Generate the schema:
```sh
yarn graphql-codegen
```
## Usage
```ts filename="./src/main.ts"
import { NhostGraphqlClient } from '@nhost/graphql-js'
import schema from './schema.ts'
const client = new NhostGraphqlClient({ url: 'http://localhost:1337/v1/graphql', schema })
```
### Basic GraphQL requests
### Queries
```ts
const todos = await client.query.todos({
select: { createdAt: true, contents: true, user: { select: { displayName: true } } }
})
todos.map(({ createdAt, contents, user: { displayName } }) => {
console.log(`${displayName} created the following todo at ${createdAt}: ${contents}`)
})
```
Select all scalar fields:
```ts
const todos = await client.query.todos()
todos.map(({ createdAt, contents }) => {
console.log(`Todo created at ${createdAt}: ${contents}`)
})
```
Pass on parameters:
```ts
const todos = await client.query.todos({
variables: { where: { contents: { _eq: 'document the sdk' } } },
select: { createdAt: true, contents: true, user: { select: { displayName: true } } }
})
todos.map(({ createdAt, contents }) => {
console.log(`${displayName} created the following todo at ${createdAt}: ${contents}`)
})
```
### Mutations
```ts
const { id } = await client.mutation.insertTodo({
select: { id: true },
variables: { contents: 'document the sdk', userId: 'xxx-yyy-zzz' }
})
```
### Enums
```ts
const todos = await client.query.todos({
variables: {
where: {
category: { _eq: 'essay' } // the client detects 'essay' is a GraphQL enum value
}
},
contents: true,
category: true
})
```
### Unions
```ts
const giraffes = await client.query
.giraffeFacts({
_on: {
GiraffeNumericFact: { value: true },
GiraffeStringFact: { fact: true }
}
})
.run()
giraffes.forEach((giraffe) => {
if (giraffe.__typename === 'GiraffeNumericFact') {
// * We are in the GiraffeNumericFact fragment: only `value` is available
console.log('Value:', giraffe.value)
} else {
// * We are in the GiraffeStringFact fragment: only `fact` is available
console.log('Fact:', giraffe.fact)
}
})
```
### Interfaces
## Documentation
[https://docs.nhost.io/reference/javascript/auth](https://docs.nhost.io/reference/javascript/graphql)

View File

@@ -0,0 +1,131 @@
import SchemaBuilder from '@pothos/core'
import { createYoga } from 'graphql-yoga'
class Human {
public pets: Pet[] = []
constructor(public phoneNumber: string, public firstName: string) {}
}
class Pet {
name: string
diet: Diet
owner: Human
constructor(name: string, diet: Diet, owner: Human) {
this.name = name
this.diet = diet
this.owner = owner
}
// constructor(public name: string, public diet: Diet, public owner: Human) {}
}
enum Diet {
HERBIVOROUS,
CARNIVOROUS,
OMNIVORIOUS
}
export class Dog extends Pet {
constructor(name: string, owner: Human, public barks: boolean) {
super(name, Diet.CARNIVOROUS, owner)
}
}
export class Hamster extends Pet {
constructor(name: string, owner: Human, public squeaks: boolean) {
super(name, Diet.HERBIVOROUS, owner)
}
}
const human1 = new Human('123-456-7890', 'John')
const dog1 = new Dog('Fido', human1, false)
const dog2 = new Dog('Rover', human1, true)
const hamster1 = new Hamster('Hammy', human1, true)
human1.pets = [dog1, dog2, hamster1]
const builder = new SchemaBuilder<{
Objects: {
Pet: Pet
Human: Human
Dog: Dog
}
}>({})
const HumanObject = builder.objectType('Human', {
fields: (t) => ({
phoneNumber: t.exposeString('phoneNumber', {}),
firstName: t.exposeString('firstName', {}),
pets: t.field({
type: [Pet],
resolve: (h) => h.pets
})
})
})
const PetObject = builder.interfaceType(Pet, {
name: 'Pet',
fields: (t) => ({
name: t.exposeString('name', {}),
owner: t.field({ type: HumanObject, resolve: (p) => p.owner }),
diet: t.expose('diet', {
type: Diet
})
})
})
const DogObject = builder.objectType('Dog', {
interfaces: [Pet],
isTypeOf: (value) => value instanceof Dog,
fields: (t) => ({
barks: t.exposeBoolean('barks', {})
})
})
const HamsterObject = builder.objectType(Hamster, {
name: 'Hamster',
interfaces: [Pet],
isTypeOf: (value) => value instanceof Hamster,
fields: (t) => ({
squeaks: t.exposeBoolean('squeaks', {})
})
})
builder.enumType(Diet, {
name: 'Diet'
})
const Anyone = builder.unionType('Anyone', {
types: [DogObject, HamsterObject, HumanObject],
resolveType: (fact) => {
if (fact instanceof Human) {
return HumanObject
}
if (fact instanceof Dog) {
return DogObject
}
if (fact instanceof Hamster) {
return HamsterObject
}
}
})
builder.queryField('everyone', (t) =>
t.field({
type: [Anyone],
resolve: () => {
return [human1, dog1, dog2, hamster1]
}
})
)
builder.queryField('pets', (t) =>
t.field({ type: [PetObject], resolve: () => [dog1, dog2, hamster1] })
)
builder.queryField('dogs', (t) => t.field({ type: [DogObject], resolve: () => [dog1, dog2] }))
builder.queryField('hamsters', (t) => t.field({ type: [HamsterObject], resolve: () => [hamster1] }))
builder.queryType({})
export default createYoga({
schema: builder.toSchema(),
graphqlEndpoint: '/'
})

View File

@@ -0,0 +1,16 @@
{
"name": "functions",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@pothos/core": "^3.24.0",
"@types/node": "^18.11.18",
"graphql-yoga": "^3.3.0",
"graphql": "^16.6.0"
}
}

View File

@@ -0,0 +1,24 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"strict": true,
"isolatedModules": true,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"moduleResolution": "node",
"target": "ES6",
"module": "CommonJS",
"types": [
"node"
],
"esModuleInterop": true,
"sourceMap": true
},
"exclude": [
"node_modules",
"dist"
]
}

View File

@@ -0,0 +1,366 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@envelop/core@3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@envelop/core/-/core-3.0.4.tgz#6801049bed24487599b4ffa0f836f70cb62714fc"
integrity sha512-AybIZxQsDlFQTWHy6YtX/MSQPVuw+eOFtTW90JsHn6EbmcQnD6N3edQfSiTGjggPRHLoC0+0cuYXp2Ly2r3vrQ==
dependencies:
"@envelop/types" "3.0.1"
tslib "2.4.0"
"@envelop/parser-cache@^5.0.4":
version "5.0.4"
resolved "https://registry.yarnpkg.com/@envelop/parser-cache/-/parser-cache-5.0.4.tgz#4ff19c16c601c6137a6774fc5660f2e18768c05c"
integrity sha512-+kp6nzCVLYI2WQExQcE3FSy6n9ZGB5GYi+ntyjYdxaXU41U1f8RVwiLdyh0Ewn5D/s/zaLin09xkFKITVSAKDw==
dependencies:
lru-cache "^6.0.0"
tslib "^2.4.0"
"@envelop/types@3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@envelop/types/-/types-3.0.1.tgz#0afec3b3f1ab282bc828e6c42c5e26d76ffe363c"
integrity sha512-Ok62K1K+rlS+wQw77k8Pis8+1/h7+/9Wk5Fgcc2U6M5haEWsLFAHcHsk8rYlnJdEUl2Y3yJcCSOYbt1dyTaU5w==
dependencies:
tslib "^2.4.0"
"@envelop/validation-cache@^5.0.5":
version "5.0.5"
resolved "https://registry.yarnpkg.com/@envelop/validation-cache/-/validation-cache-5.0.5.tgz#9be1c1ba178460dcaf6d277136a381833cc4f931"
integrity sha512-69sq5H7hvxE+7VV60i0bgnOiV1PX9GEJHKrBrVvyEZAXqYojKO3DP9jnLGryiPgVaBjN5yw12ge0l0s2gXbolQ==
dependencies:
lru-cache "^6.0.0"
tslib "^2.4.0"
"@graphql-tools/executor@0.0.12":
version "0.0.12"
resolved "https://registry.yarnpkg.com/@graphql-tools/executor/-/executor-0.0.12.tgz#d885c7fa98a8aaeaa771163b71fb98ce9f52f9bd"
integrity sha512-bWpZcYRo81jDoTVONTnxS9dDHhEkNVjxzvFCH4CRpuyzD3uL+5w3MhtxIh24QyWm4LvQ4f+Bz3eMV2xU2I5+FA==
dependencies:
"@graphql-tools/utils" "9.1.4"
"@graphql-typed-document-node/core" "3.1.1"
"@repeaterjs/repeater" "3.0.4"
tslib "^2.4.0"
value-or-promise "1.0.12"
"@graphql-tools/merge@8.3.16":
version "8.3.16"
resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.3.16.tgz#fede610687b148e34ff861e8b038dcd71e20039b"
integrity sha512-In0kcOZcPIpYOKaqdrJ3thdLPE7TutFnL9tbrHUy2zCinR2O/blpRC48jPckcs0HHrUQ0pGT4HqvzMkZUeEBAw==
dependencies:
"@graphql-tools/utils" "9.1.4"
tslib "^2.4.0"
"@graphql-tools/schema@^9.0.0":
version "9.0.14"
resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-9.0.14.tgz#9a658ab82d5a7d4db73f68a44900d4c88a98f0bc"
integrity sha512-U6k+HY3Git+dsOEhq+dtWQwYg2CAgue8qBvnBXoKu5eEeH284wymMUoNm0e4IycOgMCJANVhClGEBIkLRu3FQQ==
dependencies:
"@graphql-tools/merge" "8.3.16"
"@graphql-tools/utils" "9.1.4"
tslib "^2.4.0"
value-or-promise "1.0.12"
"@graphql-tools/utils@9.1.4", "@graphql-tools/utils@^9.0.1":
version "9.1.4"
resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-9.1.4.tgz#2c9e0aefc9655dd73247667befe3c850ec014f3f"
integrity sha512-hgIeLt95h9nQgQuzbbdhuZmh+8WV7RZ/6GbTj6t3IU4Zd2zs9yYJ2jgW/krO587GMOY8zCwrjNOMzD40u3l7Vg==
dependencies:
tslib "^2.4.0"
"@graphql-typed-document-node/core@3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052"
integrity sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==
"@graphql-yoga/subscription@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@graphql-yoga/subscription/-/subscription-3.1.0.tgz#4a0bb0b9db2602d02c68f9828603e1e40329140b"
integrity sha512-Vc9lh8KzIHyS3n4jBlCbz7zCjcbtQnOBpsymcRvHhFr2cuH+knmRn0EmzimMQ58jQ8kxoRXXC3KJS3RIxSdPIg==
dependencies:
"@graphql-yoga/typed-event-target" "^1.0.0"
"@repeaterjs/repeater" "^3.0.4"
"@whatwg-node/events" "0.0.2"
tslib "^2.3.1"
"@graphql-yoga/typed-event-target@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@graphql-yoga/typed-event-target/-/typed-event-target-1.0.0.tgz#dae3c0146f08a4dc30b5b890f8bab706c2b62199"
integrity sha512-Mqni6AEvl3VbpMtKw+TIjc9qS9a8hKhiAjFtqX488yq5oJtj9TkNlFTIacAVS3vnPiswNsmDiQqvwUOcJgi1DA==
dependencies:
"@repeaterjs/repeater" "^3.0.4"
tslib "^2.3.1"
"@peculiar/asn1-schema@^2.1.6", "@peculiar/asn1-schema@^2.3.0":
version "2.3.3"
resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.3.tgz#21418e1f3819e0b353ceff0c2dad8ccb61acd777"
integrity sha512-6GptMYDMyWBHTUKndHaDsRZUO/XMSgIns2krxcm2L7SEExRHwawFvSwNBhqNPR9HJwv3MruAiF1bhN0we6j6GQ==
dependencies:
asn1js "^3.0.5"
pvtsutils "^1.3.2"
tslib "^2.4.0"
"@peculiar/json-schema@^1.1.12":
version "1.1.12"
resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339"
integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==
dependencies:
tslib "^2.0.0"
"@peculiar/webcrypto@^1.4.0":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.4.1.tgz#821493bd5ad0f05939bd5f53b28536f68158360a"
integrity sha512-eK4C6WTNYxoI7JOabMoZICiyqRRtJB220bh0Mbj5RwRycleZf9BPyZoxsTvpP0FpmVS2aS13NKOuh5/tN3sIRw==
dependencies:
"@peculiar/asn1-schema" "^2.3.0"
"@peculiar/json-schema" "^1.1.12"
pvtsutils "^1.3.2"
tslib "^2.4.1"
webcrypto-core "^1.7.4"
"@pothos/core@^3.24.0":
version "3.24.0"
resolved "https://registry.yarnpkg.com/@pothos/core/-/core-3.24.0.tgz#1a555c501c9fc09c588196f83e6b0075571a59c5"
integrity sha512-LfWzUrmjhg9WQNUntQMJWOfMLb51AMunqBOC66zWEIi2GR4IcAQCPwzy77713Zd/awtIInIuHv4x5/1whAWeeA==
"@repeaterjs/repeater@3.0.4", "@repeaterjs/repeater@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca"
integrity sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==
"@types/node@^18.11.18":
version "18.11.18"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f"
integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==
"@whatwg-node/events@0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.2.tgz#7b7107268d2982fc7b7aff5ee6803c64018f84dd"
integrity sha512-WKj/lI4QjnLuPrim0cfO7i+HsDSXHxNv1y0CrJhdntuO3hxWZmnXCwNDnwOvry11OjRin6cgWNF+j/9Pn8TN4w==
"@whatwg-node/fetch@0.6.2":
version "0.6.2"
resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.6.2.tgz#fe4837505f6fc91bcfd6e12cdcec66f4aecfeecc"
integrity sha512-fCUycF1W+bI6XzwJFnbdDuxIldfKM3w8+AzVCLGlucm0D+AQ8ZMm2j84hdcIhfV6ZdE4Y1HFVrHosAxdDZ+nPw==
dependencies:
"@peculiar/webcrypto" "^1.4.0"
abort-controller "^3.0.0"
busboy "^1.6.0"
form-data-encoder "^1.7.1"
formdata-node "^4.3.1"
node-fetch "^2.6.7"
undici "^5.12.0"
urlpattern-polyfill "^6.0.2"
web-streams-polyfill "^3.2.0"
"@whatwg-node/server@0.5.8":
version "0.5.8"
resolved "https://registry.yarnpkg.com/@whatwg-node/server/-/server-0.5.8.tgz#e47aa4535431b6703652809dc4f7e5ebac6bffdb"
integrity sha512-29f2Ijk663Hr6hF5GU5a8ELGQVbNMMDBWF1lTdpIKGyLrLJTKixarp6COEyEN5H9tGzIRUQar9Z76A+Jb9DyzQ==
dependencies:
"@whatwg-node/fetch" "0.6.2"
tslib "^2.3.1"
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
dependencies:
event-target-shim "^5.0.0"
asn1js@^3.0.1, asn1js@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38"
integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==
dependencies:
pvtsutils "^1.3.2"
pvutils "^1.1.3"
tslib "^2.4.0"
braces@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
busboy@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
dependencies:
streamsearch "^1.1.0"
dset@^3.1.1:
version "3.1.2"
resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a"
integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==
event-target-shim@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
to-regex-range "^5.0.1"
form-data-encoder@^1.7.1:
version "1.7.2"
resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040"
integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==
formdata-node@^4.3.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2"
integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==
dependencies:
node-domexception "1.0.0"
web-streams-polyfill "4.0.0-beta.3"
graphql-yoga@^3.3.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/graphql-yoga/-/graphql-yoga-3.4.0.tgz#9ab03552edb1f9ec0d877566ee7f0ecb23726dd7"
integrity sha512-Cjx60mmpoK1qL/sLdM285VdAOQyJBKLuC6oMZrfO8QleneNtu0nDOM6Efv5m0IrRYSONEMtIYA7eNr0u/cCBfg==
dependencies:
"@envelop/core" "3.0.4"
"@envelop/parser-cache" "^5.0.4"
"@envelop/validation-cache" "^5.0.5"
"@graphql-tools/executor" "0.0.12"
"@graphql-tools/schema" "^9.0.0"
"@graphql-tools/utils" "^9.0.1"
"@graphql-yoga/subscription" "^3.1.0"
"@whatwg-node/fetch" "0.6.2"
"@whatwg-node/server" "0.5.8"
dset "^3.1.1"
tslib "^2.3.1"
graphql@^16.6.0:
version "16.6.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb"
integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
yallist "^4.0.0"
node-domexception@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
node-fetch@^2.6.7:
version "2.6.8"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.8.tgz#a68d30b162bc1d8fd71a367e81b997e1f4d4937e"
integrity sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==
dependencies:
whatwg-url "^5.0.0"
pvtsutils@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.2.tgz#9f8570d132cdd3c27ab7d51a2799239bf8d8d5de"
integrity sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==
dependencies:
tslib "^2.4.0"
pvutils@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3"
integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==
streamsearch@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
tslib@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
tslib@^2.0.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
undici@^5.12.0:
version "5.16.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.16.0.tgz#6b64f9b890de85489ac6332bd45ca67e4f7d9943"
integrity sha512-KWBOXNv6VX+oJQhchXieUznEmnJMqgXMbs0xxH2t8q/FUAWSJvOSr/rMaZKnX5RIVq7JDn0JbP4BOnKG2SGXLQ==
dependencies:
busboy "^1.6.0"
urlpattern-polyfill@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-6.0.2.tgz#a193fe773459865a2a5c93b246bb794b13d07256"
integrity sha512-5vZjFlH9ofROmuWmXM9yj2wljYKgWstGwe8YTyiqM7hVum/g9LyCizPZtb3UqsuppVwety9QJmfc42VggLpTgg==
dependencies:
braces "^3.0.2"
value-or-promise@1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c"
integrity sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==
web-streams-polyfill@4.0.0-beta.3:
version "4.0.0-beta.3"
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38"
integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==
web-streams-polyfill@^3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
webcrypto-core@^1.7.4:
version "1.7.5"
resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.5.tgz#c02104c953ca7107557f9c165d194c6316587ca4"
integrity sha512-gaExY2/3EHQlRNNNVSrbG2Cg94Rutl7fAaKILS1w8ZDhGxdFOaw6EbCfHIxPy9vt/xwp5o0VQAx9aySPF6hU1A==
dependencies:
"@peculiar/asn1-schema" "^2.1.6"
"@peculiar/json-schema" "^1.1.12"
asn1js "^3.0.1"
pvtsutils "^1.3.2"
tslib "^2.4.0"
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==

View File

@@ -0,0 +1,10 @@
{
"title": "GraphQL",
"path": "./.docgen/graphql.json",
"output": "../../docs/docs/reference/docgen/javascript/graphql",
"root": "reference/docgen/javascript/graphql",
"slug": "/reference/javascript/graphql",
"sidebarConfig": "referenceSidebar",
"baseEditUrl": "https://github.com/nhost/nhost/edit/main/packages",
"cleanup": true
}

View File

@@ -7,8 +7,8 @@
"sort": [
"source-order"
],
"json": "./.docgen/nhost-js.json",
"name": "Nhost JS",
"json": "./.docgen/graphql.json",
"name": "GraphQL",
"readme": "none",
"githubPages": false,
"cleanOutputDir": false,
@@ -26,6 +26,9 @@
"@nhost/hasura-storage-js": [
"../hasura-storage-js/src/index.ts"
],
"@nhost/graphql-js": [
"../graphql-js/src/index.ts"
],
"@nhost/nextjs": [
"../nextjs/src/index.ts"
],

View File

@@ -0,0 +1,132 @@
metadata_directory: metadata
services:
hasura:
image: hasura/graphql-engine:v2.15.2
environment:
hasura_graphql_enable_remote_schema_permissions: false
auth:
image: nhost/hasura-auth:0.16.2
storage:
image: nhost/hasura-storage:0.3.0
auth:
access_control:
email:
allowed_email_domains: ''
allowed_emails: ''
blocked_email_domains: ''
blocked_emails: ''
allowed_redirect_urls: ''
anonymous_users_enabled: true
client_url: http://localhost:3000
disable_new_users: false
email:
signin_email_verified_required: false
passwordless:
enabled: true
template_fetch_url: ''
gravatar:
default: ''
enabled: true
rating: ''
locale:
allowed: en
default: en
password:
hibp_enabled: false
min_length: 3
provider:
apple:
client_id: ''
enabled: false
key_id: ''
private_key: ''
scope: name,email
team_id: ''
bitbucket:
client_id: ''
client_secret: ''
enabled: false
facebook:
client_id: ''
client_secret: ''
enabled: false
scope: email,photos,displayName
github:
enabled: false
client_id: ''
client_secret: ''
scope: user:email
token_url: ''
user_profile_url: ''
gitlab:
base_url: ''
client_id: ''
client_secret: ''
enabled: false
scope: read_user
google:
client_id: ''
client_secret: ''
enabled: false
scope: email,profile
linkedin:
client_id: ''
client_secret: ''
enabled: false
scope: r_emailaddress,r_liteprofile
spotify:
client_id: ''
client_secret: ''
enabled: false
scope: user-read-email,user-read-private
strava:
client_id: ''
client_secret: ''
enabled: false
twilio:
account_sid: ''
auth_token: ''
enabled: false
messaging_service_id: ''
twitter:
consumer_key: ''
consumer_secret: ''
enabled: false
windows_live:
client_id: ''
client_secret: ''
enabled: false
scope: wl.basic,wl.emails,wl.contacts_emails
sms:
enabled: false
passwordless:
enabled: false
provider:
twilio:
account_sid: ''
auth_token: ''
from: ''
messaging_service_id: ''
smtp:
host: mailhog
method: ''
pass: password
port: 1025
secure: false
sender: hasura-auth@example.com
user: user
token:
access:
expires_in: 900
refresh:
expires_in: 43200
user:
allowed_roles: user,me
default_allowed_roles: user,me
default_role: user
mfa:
enabled: true
issuer: nhost
storage:
force_download_for_content_types: text/html,application/javascript
version: 3

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>Confirm Email Change</h2>
<p>Use this link to confirm changing email:</p>
<p>
<a href="${link}"> Change email </a>
</p>
</body>
</html>

View File

@@ -0,0 +1 @@
Change your email address

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>Verify Email</h2>
<p>Use this link to verify your email:</p>
<p>
<a href="${link}"> Verify Email </a>
</p>
</body>
</html>

View File

@@ -0,0 +1 @@
Verify your email

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>Reset Password</h2>
<p>Use this link to reset your password:</p>
<p>
<a href="${link}"> Reset password </a>
</p>
</body>
</html>

View File

@@ -0,0 +1 @@
Reset your password

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>Magic Link</h2>
<p>Use this link to securely sign in:</p>
<p>
<a href="${link}"> Sign In </a>
</p>
</body>
</html>

View File

@@ -0,0 +1 @@
Secure sign-in link

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>Confirmer changement de courriel</h2>
<p>Utilisez ce lien pour confirmer le changement de courriel:</p>
<p>
<a href="${link}"> Changer courriel </a>
</p>
</body>
</html>

View File

@@ -0,0 +1 @@
Changez votre adresse courriel

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>V&eacute;rifiez votre courriel</h2>
<p>Utilisez ce lien pour v&eacute;rifier votre courriel:</p>
<p>
<a href="${link}"> V&eacute;rifier courriel </a>
</p>
</body>
</html>

View File

@@ -0,0 +1 @@
Vérifier votre courriel

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>R&eacute;initializer votre mot de passe</h2>
<p>Utilisez ce lien pour r&eacute;initializer votre mot de passe:</p>
<p>
<a href="${link}"> R&eacute;initializer mot de passe </a>
</p>
</body>
</html>

View File

@@ -0,0 +1 @@
Réinitialiser votre mot de passe

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>Lien magique</h2>
<p>Utilisez ce lien pour vous connecter de fa&ccedil;on s&eacute;curitaire:</p>
<p>
<a href="${link}"> Connexion </a>
</p>
</body>
</html>

View File

@@ -0,0 +1 @@
Lien de connexion sécurisé

View File

@@ -0,0 +1,6 @@
actions: []
custom_types:
enums: []
input_objects: []
objects: []
scalars: []

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,14 @@
- name: default
kind: postgres
configuration:
connection_info:
database_url:
from_env: HASURA_GRAPHQL_DATABASE_URL
isolation_level: read-committed
pool_settings:
connection_lifetime: 600
idle_timeout: 180
max_connections: 50
retries: 20
use_prepared_statements: true
tables: "!include default/tables/tables.yaml"

View File

@@ -0,0 +1,23 @@
table:
name: provider_requests
schema: auth
configuration:
column_config:
id:
custom_name: id
options:
custom_name: options
custom_column_names:
id: id
options: options
custom_name: authProviderRequests
custom_root_fields:
delete: deleteAuthProviderRequests
delete_by_pk: deleteAuthProviderRequest
insert: insertAuthProviderRequests
insert_one: insertAuthProviderRequest
select: authProviderRequests
select_aggregate: authProviderRequestsAggregate
select_by_pk: authProviderRequest
update: updateAuthProviderRequests
update_by_pk: updateAuthProviderRequest

View File

@@ -0,0 +1,28 @@
table:
name: providers
schema: auth
configuration:
column_config:
id:
custom_name: id
custom_column_names:
id: id
custom_name: authProviders
custom_root_fields:
delete: deleteAuthProviders
delete_by_pk: deleteAuthProvider
insert: insertAuthProviders
insert_one: insertAuthProvider
select: authProviders
select_aggregate: authProvidersAggregate
select_by_pk: authProvider
update: updateAuthProviders
update_by_pk: updateAuthProvider
array_relationships:
- name: userProviders
using:
foreign_key_constraint_on:
column: provider_id
table:
name: user_providers
schema: auth

View File

@@ -0,0 +1,33 @@
table:
name: refresh_tokens
schema: auth
configuration:
column_config:
created_at:
custom_name: createdAt
expires_at:
custom_name: expiresAt
refresh_token:
custom_name: refreshToken
user_id:
custom_name: userId
custom_column_names:
created_at: createdAt
expires_at: expiresAt
refresh_token: refreshToken
user_id: userId
custom_name: authRefreshTokens
custom_root_fields:
delete: deleteAuthRefreshTokens
delete_by_pk: deleteAuthRefreshToken
insert: insertAuthRefreshTokens
insert_one: insertAuthRefreshToken
select: authRefreshTokens
select_aggregate: authRefreshTokensAggregate
select_by_pk: authRefreshToken
update: updateAuthRefreshTokens
update_by_pk: updateAuthRefreshToken
object_relationships:
- name: user
using:
foreign_key_constraint_on: user_id

View File

@@ -0,0 +1,46 @@
table:
name: roles
schema: auth
configuration:
column_config:
role:
custom_name: role
custom_column_names:
role: role
custom_name: authRoles
custom_root_fields:
delete: deleteAuthRoles
delete_by_pk: deleteAuthRole
insert: insertAuthRoles
insert_one: insertAuthRole
select: authRoles
select_aggregate: authRolesAggregate
select_by_pk: authRole
update: updateAuthRoles
update_by_pk: updateAuthRole
array_relationships:
- name: userRoles
using:
foreign_key_constraint_on:
column: role
table:
name: user_roles
schema: auth
- name: usersByDefaultRole
using:
foreign_key_constraint_on:
column: default_role
table:
name: users
schema: auth
select_permissions:
- role: anonymous
permission:
columns:
- role
filter: {}
- role: user
permission:
columns:
- role
filter: {}

View File

@@ -0,0 +1,48 @@
table:
name: user_providers
schema: auth
configuration:
column_config:
access_token:
custom_name: accessToken
created_at:
custom_name: createdAt
id:
custom_name: id
provider_id:
custom_name: providerId
provider_user_id:
custom_name: providerUserId
refresh_token:
custom_name: refreshToken
updated_at:
custom_name: updatedAt
user_id:
custom_name: userId
custom_column_names:
access_token: accessToken
created_at: createdAt
id: id
provider_id: providerId
provider_user_id: providerUserId
refresh_token: refreshToken
updated_at: updatedAt
user_id: userId
custom_name: authUserProviders
custom_root_fields:
delete: deleteAuthUserProviders
delete_by_pk: deleteAuthUserProvider
insert: insertAuthUserProviders
insert_one: insertAuthUserProvider
select: authUserProviders
select_aggregate: authUserProvidersAggregate
select_by_pk: authUserProvider
update: updateAuthUserProviders
update_by_pk: updateAuthUserProvider
object_relationships:
- name: provider
using:
foreign_key_constraint_on: provider_id
- name: user
using:
foreign_key_constraint_on: user_id

View File

@@ -0,0 +1,52 @@
table:
name: user_roles
schema: auth
configuration:
column_config:
created_at:
custom_name: createdAt
id:
custom_name: id
role:
custom_name: role
user_id:
custom_name: userId
custom_column_names:
created_at: createdAt
id: id
role: role
user_id: userId
custom_name: authUserRoles
custom_root_fields:
delete: deleteAuthUserRoles
delete_by_pk: deleteAuthUserRole
insert: insertAuthUserRoles
insert_one: insertAuthUserRole
select: authUserRoles
select_aggregate: authUserRolesAggregate
select_by_pk: authUserRole
update: updateAuthUserRoles
update_by_pk: updateAuthUserRole
object_relationships:
- name: roleByRole
using:
foreign_key_constraint_on: role
- name: user
using:
foreign_key_constraint_on: user_id
select_permissions:
- role: public
permission:
columns:
- role
- created_at
- id
- user_id
filter: {}
- role: user
permission:
columns:
- id
- role
- user_id
filter: {}

View File

@@ -0,0 +1,33 @@
table:
name: user_security_keys
schema: auth
configuration:
column_config:
credential_id:
custom_name: credentialId
credential_public_key:
custom_name: credentialPublicKey
id:
custom_name: id
user_id:
custom_name: userId
custom_column_names:
credential_id: credentialId
credential_public_key: credentialPublicKey
id: id
user_id: userId
custom_name: authUserSecurityKeys
custom_root_fields:
delete: deleteAuthUserSecurityKeys
delete_by_pk: deleteAuthUserSecurityKey
insert: insertAuthUserSecurityKeys
insert_one: insertAuthUserSecurityKey
select: authUserSecurityKeys
select_aggregate: authUserSecurityKeysAggregate
select_by_pk: authUserSecurityKey
update: updateAuthUserSecurityKeys
update_by_pk: updateAuthUserSecurityKey
object_relationships:
- name: user
using:
foreign_key_constraint_on: user_id

View File

@@ -0,0 +1,156 @@
table:
name: users
schema: auth
configuration:
column_config:
active_mfa_type:
custom_name: activeMfaType
avatar_url:
custom_name: avatarUrl
created_at:
custom_name: createdAt
default_role:
custom_name: defaultRole
disabled:
custom_name: disabled
display_name:
custom_name: displayName
email:
custom_name: email
email_verified:
custom_name: emailVerified
id:
custom_name: id
is_anonymous:
custom_name: isAnonymous
last_seen:
custom_name: lastSeen
locale:
custom_name: locale
new_email:
custom_name: newEmail
otp_hash:
custom_name: otpHash
otp_hash_expires_at:
custom_name: otpHashExpiresAt
otp_method_last_used:
custom_name: otpMethodLastUsed
password_hash:
custom_name: passwordHash
phone_number:
custom_name: phoneNumber
phone_number_verified:
custom_name: phoneNumberVerified
ticket:
custom_name: ticket
ticket_expires_at:
custom_name: ticketExpiresAt
totp_secret:
custom_name: totpSecret
updated_at:
custom_name: updatedAt
webauthn_current_challenge:
custom_name: currentChallenge
custom_column_names:
active_mfa_type: activeMfaType
avatar_url: avatarUrl
created_at: createdAt
default_role: defaultRole
disabled: disabled
display_name: displayName
email: email
email_verified: emailVerified
id: id
is_anonymous: isAnonymous
last_seen: lastSeen
locale: locale
new_email: newEmail
otp_hash: otpHash
otp_hash_expires_at: otpHashExpiresAt
otp_method_last_used: otpMethodLastUsed
password_hash: passwordHash
phone_number: phoneNumber
phone_number_verified: phoneNumberVerified
ticket: ticket
ticket_expires_at: ticketExpiresAt
totp_secret: totpSecret
updated_at: updatedAt
webauthn_current_challenge: currentChallenge
custom_name: users
custom_root_fields:
delete: deleteUsers
delete_by_pk: deleteUser
insert: insertUsers
insert_one: insertUser
select: users
select_aggregate: usersAggregate
select_by_pk: user
update: updateUsers
update_by_pk: updateUser
object_relationships:
- name: defaultRoleByRole
using:
foreign_key_constraint_on: default_role
array_relationships:
- name: refreshTokens
using:
foreign_key_constraint_on:
column: user_id
table:
name: refresh_tokens
schema: auth
- name: roles
using:
foreign_key_constraint_on:
column: user_id
table:
name: user_roles
schema: auth
- name: securityKeys
using:
foreign_key_constraint_on:
column: user_id
table:
name: user_security_keys
schema: auth
- name: userProviders
using:
foreign_key_constraint_on:
column: user_id
table:
name: user_providers
schema: auth
insert_permissions:
- role: public
permission:
check: {}
columns:
- avatar_url
- default_role
- display_name
- email
- locale
- metadata
select_permissions:
- role: public
permission:
columns:
- avatar_url
- created_at
- default_role
- display_name
- email
- id
- is_anonymous
- last_seen
- locale
- updated_at
filter: {}
allow_aggregations: true
- role: user
permission:
columns:
- display_name
- email
- id
filter: {}

View File

@@ -0,0 +1,10 @@
table:
name: books
schema: public
select_permissions:
- permission:
columns:
- id
- title
filter: {}
role: user

View File

@@ -0,0 +1,17 @@
table:
name: categories
schema: public
is_enum: true
select_permissions:
- role: public
permission:
columns:
- comment
- value
filter: {}
- role: user
permission:
columns:
- comment
- value
filter: {}

View File

@@ -0,0 +1,89 @@
table:
name: todos
schema: public
configuration:
column_config:
created_at:
custom_name: createdAt
updated_at:
custom_name: updatedAt
user_id:
custom_name: userId
custom_column_names:
created_at: createdAt
updated_at: updatedAt
user_id: userId
custom_root_fields:
delete: deleteTodos
delete_by_pk: deleteTodo
insert: insertTodos
insert_one: insertTodo
select_aggregate: todosAggregate
select_by_pk: todo
update: updateTodos
update_by_pk: updateTodo
object_relationships:
- name: user
using:
foreign_key_constraint_on: user_id
insert_permissions:
- role: public
permission:
check: {}
columns:
- category
- contents
- created_at
- updated_at
- id
- user_id
- role: user
permission:
check: {}
set:
user_id: x-hasura-user-id
columns:
- category
- contents
- created_at
- updated_at
- id
- user_id
select_permissions:
- role: public
permission:
columns:
- category
- contents
- created_at
- updated_at
- id
- user_id
filter: {}
allow_aggregations: true
- role: user
permission:
columns:
- category
- contents
- created_at
- updated_at
- id
- user_id
filter: {}
update_permissions:
- role: public
permission:
columns:
- category
- contents
- created_at
- updated_at
- id
- user_id
filter: {}
check: {}
delete_permissions:
- role: public
permission:
filter: {}

View File

@@ -0,0 +1,49 @@
table:
name: buckets
schema: storage
configuration:
column_config:
cache_control:
custom_name: cacheControl
created_at:
custom_name: createdAt
download_expiration:
custom_name: downloadExpiration
id:
custom_name: id
max_upload_file_size:
custom_name: maxUploadFileSize
min_upload_file_size:
custom_name: minUploadFileSize
presigned_urls_enabled:
custom_name: presignedUrlsEnabled
updated_at:
custom_name: updatedAt
custom_column_names:
cache_control: cacheControl
created_at: createdAt
download_expiration: downloadExpiration
id: id
max_upload_file_size: maxUploadFileSize
min_upload_file_size: minUploadFileSize
presigned_urls_enabled: presignedUrlsEnabled
updated_at: updatedAt
custom_name: buckets
custom_root_fields:
delete: deleteBuckets
delete_by_pk: deleteBucket
insert: insertBuckets
insert_one: insertBucket
select: buckets
select_aggregate: bucketsAggregate
select_by_pk: bucket
update: updateBuckets
update_by_pk: updateBucket
array_relationships:
- name: files
using:
foreign_key_constraint_on:
column: bucket_id
table:
name: files
schema: storage

View File

@@ -0,0 +1,103 @@
table:
name: files
schema: storage
configuration:
column_config:
bucket_id:
custom_name: bucketId
created_at:
custom_name: createdAt
etag:
custom_name: etag
id:
custom_name: id
is_uploaded:
custom_name: isUploaded
mime_type:
custom_name: mimeType
name:
custom_name: name
size:
custom_name: size
updated_at:
custom_name: updatedAt
uploaded_by_user_id:
custom_name: uploadedByUserId
custom_column_names:
bucket_id: bucketId
created_at: createdAt
etag: etag
id: id
is_uploaded: isUploaded
mime_type: mimeType
name: name
size: size
updated_at: updatedAt
uploaded_by_user_id: uploadedByUserId
custom_name: files
custom_root_fields:
delete: deleteFiles
delete_by_pk: deleteFile
insert: insertFiles
insert_one: insertFile
select: files
select_aggregate: filesAggregate
select_by_pk: file
update: updateFiles
update_by_pk: updateFile
object_relationships:
- name: bucket
using:
foreign_key_constraint_on: bucket_id
insert_permissions:
- role: anonymous
permission:
check:
size:
_lt: 1024000
columns:
- is_uploaded
- size
- bucket_id
- etag
- mime_type
- name
- created_at
- updated_at
- id
- uploaded_by_user_id
select_permissions:
- role: anonymous
permission:
columns:
- is_uploaded
- size
- bucket_id
- etag
- mime_type
- name
- created_at
- updated_at
- id
- uploaded_by_user_id
filter: {}
update_permissions:
- role: anonymous
permission:
columns:
- is_uploaded
- size
- bucket_id
- etag
- mime_type
- name
- created_at
- updated_at
- id
- uploaded_by_user_id
filter: {}
check: {}
delete_permissions:
- role: anonymous
permission:
filter: {}

View File

@@ -0,0 +1,12 @@
- "!include auth_provider_requests.yaml"
- "!include auth_providers.yaml"
- "!include auth_refresh_tokens.yaml"
- "!include auth_roles.yaml"
- "!include auth_user_providers.yaml"
- "!include auth_user_roles.yaml"
- "!include auth_user_security_keys.yaml"
- "!include auth_users.yaml"
- "!include public_categories.yaml"
- "!include public_todos.yaml"
- "!include storage_buckets.yaml"
- "!include storage_files.yaml"

View File

@@ -0,0 +1 @@
disabled_for_roles: []

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,5 @@
- name: functions
definition:
url_from_env: NHOST_FUNCTIONS_URL
timeout_seconds: 60
customization: {}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1 @@
version: 3

View File

@@ -0,0 +1 @@
DROP TABLE "public"."books";

View File

@@ -0,0 +1,2 @@
CREATE TABLE "public"."books" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "title" text NOT NULL, PRIMARY KEY ("id") );
CREATE EXTENSION IF NOT EXISTS pgcrypto;

View File

@@ -0,0 +1,2 @@
DROP INDEX IF EXISTS "public"."user_id";
DROP TABLE "public"."todos_user_id";

View File

@@ -0,0 +1,20 @@
CREATE TABLE "public"."todos" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "user_id" uuid NOT NULL, "contents" text NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON UPDATE cascade ON DELETE cascade);
CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"()
RETURNS TRIGGER AS $$
DECLARE
_new record;
BEGIN
_new := NEW;
_new."updated_at" = NOW();
RETURN _new;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER "set_public_todos_updated_at"
BEFORE UPDATE ON "public"."todos"
FOR EACH ROW
EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"();
COMMENT ON TRIGGER "set_public_todos_updated_at" ON "public"."todos"
IS 'trigger to set value of column "updated_at" to current timestamp on row update';
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE INDEX "todos_user_id" on
"public"."todos" using btree ("user_id");

View File

@@ -0,0 +1,2 @@
CREATE TABLE "public"."books" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "title" text NOT NULL, PRIMARY KEY ("id") );
CREATE EXTENSION IF NOT EXISTS pgcrypto;

View File

@@ -0,0 +1 @@
DROP table "public"."books";

View File

@@ -0,0 +1,10 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- CREATE TABLE categories (
-- value text PRIMARY KEY,
-- comment text
-- );
--
-- INSERT INTO categories (value, comment) VALUES
-- ('novel', 'Novels'),
-- ('essay', 'whatev');

View File

@@ -0,0 +1,8 @@
CREATE TABLE categories (
value text PRIMARY KEY,
comment text
);
INSERT INTO categories (value, comment) VALUES
('novel', 'Novels'),
('essay', 'whatev');

View File

@@ -0,0 +1,4 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."todos" add column "category" text
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."todos" add column "category" text
null;

View File

@@ -0,0 +1 @@
alter table "public"."todos" drop constraint "todos_category_fkey";

View File

@@ -0,0 +1,5 @@
alter table "public"."todos"
add constraint "todos_category_fkey"
foreign key ("category")
references "public"."categories"
("value") on update restrict on delete restrict;

View File

@@ -0,0 +1,79 @@
{
"name": "@nhost/graphql-js",
"version": "0.0.1",
"description": "Nhost GraphQL client",
"license": "MIT",
"keywords": [
"nhost",
"hasura",
"graphql"
],
"author": "Nhost",
"homepage": "https://nhost.io",
"bugs": "https://github.com/nhost/nhost/issues",
"repository": {
"type": "git",
"url": "https://github.com/nhost/nhost.git"
},
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"types": "dist/index.d.ts",
"source": "src/index.ts",
"files": [
"dist",
"umd",
"README.md"
],
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"node": "./dist/index.cjs.js",
"default": "./dist/index.esm.js"
},
"require": "./dist/index.cjs.js"
}
},
"publishConfig": {
"access": "public"
},
"scripts": {
"dev": "vite build",
"build": "run-p build:lib build:umd",
"build:lib": "vite build",
"build:umd": "vite build --config ../../config/vite.lib.umd.config.js",
"test": "run-p test:types test:unit",
"test:codegen": "graphql-codegen --config tests/codegen.yaml",
"test:unit": "vitest run --config vite.config.unit.js",
"test:types": "tsc -p tsconfig.test.json --noEmit",
"test:watch": "vitest --config vite.config.unit.js",
"e2e": "start-test e2e:backend http-get://localhost:9695 e2e:test",
"e2e:test": "vitest run --config vite.config.e2e.js",
"e2e:backend": "nhost dev --no-browser",
"prettier": "prettier --check src/",
"prettier:fix": "prettier --write src/",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix",
"verify": "run-p prettier lint",
"verify:fix": "run-p prettier:fix lint:fix",
"typedoc": "typedoc --options ./graphql.typedoc.json --tsconfig ./typedoc.tsconfig.json",
"docgen": "pnpm typedoc && docgen --config ./graphql.docgen.json"
},
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
"cross-fetch": "^3.1.5",
"json-to-graphql-query": "^2.2.4"
},
"peerDependencies": {
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
},
"devDependencies": {
"@faker-js/faker": "^7.6.0",
"@nhost/docgen": "workspace:*",
"@nhost/hasura-auth-js": "workspace:*",
"graphql": "16.6.0",
"graphql-tag": "^2.12.6",
"npm-run-all": "^4.1.5",
"start-server-and-test": "^1.14.0"
}
}

View File

@@ -0,0 +1,268 @@
import { TypedDocumentNode } from '@graphql-typed-document-node/core'
import fetch from 'cross-fetch'
import { toRawGraphQL } from './graphql-object/query-builder'
import { GenericSchema, getRootOperationNames } from './graphql-object/schema'
import { OperationFactory } from './graphql-object/types'
import { parseRequestArgs } from './parse-args'
import { resolveRequestDocument } from './resolve-request-document'
import {
NhostGraphqlConstructorParams,
NhostGraphqlRequestConfig,
NhostGraphqlRequestResponse,
RemoveIndex,
RequestDocument,
RequestOptions,
Variables
} from './types'
/**
* @alias GraphQL
*/
export class NhostGraphqlClient<Schema extends GenericSchema | undefined> {
readonly _url: string
private accessToken: string | null
private adminSecret?: string
/**
* Use `nhost.graphql.query` to run a GraphQL query from object parameters and the schema genetated with `@graphql-codegen/typescript-nhost`.
*
* @example
* ```ts
* import schema from './generated-schema'
* const nhost = new NhostClient({ subdomain: 'xxx', region: 'yyy', schema })
*
* const { id, name } = await nhost.graphql.query.customer({ select: { id: true, name: true }, variables: {id: 'customer-id' } })
* ```
*
* @docs https://docs.nhost.io/reference/javascript/graphql/query
*/
public query: OperationFactory<Schema, 'Query'>
/**
* Use `nhost.graphql.mutation` to run a GraphQL mutation from object parameters and the schema genetated with `@graphql-codegen/typescript-nhost`.
*
* @example
* ```ts
* import schema from './generated-schema'
* const nhost = new NhostClient({ subdomain: 'xxx', region: 'yyy', schema })
*
* const { id } = await nhost.graphql.mutation.insertCustomer({ select: { id: true }, variables: { name: 'Bob' } })
* ```
*
* @docs https://docs.nhost.io/reference/javascript/graphql/mutation
*/
public mutation: OperationFactory<Schema, 'Mutation'>
constructor(params: NhostGraphqlConstructorParams<Schema>) {
const { url, adminSecret, schema } = params
this._url = url
this.accessToken = null
this.adminSecret = adminSecret
this.query = getRootOperationNames(schema, 'Query').reduce((acc, property) => {
acc[property] = async (input?: unknown) => {
const { query, variables } = toRawGraphQL(schema, 'Query', property, input)
const { data, error } = await this.request(query, variables)
if (error) {
if ('message' in error) {
throw new Error(error.message)
}
throw new Error(error[0].message)
}
return data[property]
}
return acc
}, {} as any)
this.mutation = getRootOperationNames(schema, 'Mutation').reduce((acc, property) => {
acc[property] = async (input?: unknown) => {
const { query, variables } = toRawGraphQL(schema, 'Mutation', property, input)
const { data, error } = await this.request(query, variables)
if (error) {
if ('message' in error) {
throw new Error(error.message)
}
throw new Error(error[0].message)
}
return data[property]
}
return acc
}, {} as any)
}
/**
* Use `nhost.graphql.request` to send a GraphQL request. For more serious GraphQL usage we recommend using a GraphQL client such as Apollo Client (https://www.apollographql.com/docs/react).
*
* @example
* ```ts
* const CUSTOMERS = gql`
* query {
* customers {
* id
* name
* }
* }
* `
* const { data, error } = await nhost.graphql.request(CUSTOMERS)
* ```
*
* @docs https://docs.nhost.io/reference/javascript/graphql/request
*/
request<T = any, V = Variables>(
document: RequestDocument | TypedDocumentNode<T, V>,
...variablesAndRequestHeaders: V extends Record<any, never>
? [variables?: V, config?: NhostGraphqlRequestConfig]
: keyof RemoveIndex<V> extends never
? [variables?: V, config?: NhostGraphqlRequestConfig]
: [variables: V, config?: NhostGraphqlRequestConfig]
): Promise<NhostGraphqlRequestResponse<T>>
async request<T = any, V extends Variables = Variables>(
options: RequestOptions<V, T>
): Promise<NhostGraphqlRequestResponse<T>>
async request<T = any, V extends Variables = Variables>(
documentOrOptions: RequestDocument | TypedDocumentNode<T, V> | RequestOptions<V>,
...variablesAndRequestHeaders: V extends Record<any, never>
? [variables?: V, config?: NhostGraphqlRequestConfig]
: keyof RemoveIndex<V> extends never
? [variables?: V, config?: NhostGraphqlRequestConfig]
: [variables: V, config?: NhostGraphqlRequestConfig]
): Promise<NhostGraphqlRequestResponse<T>> {
const [variables, config] = variablesAndRequestHeaders
const requestOptions = parseRequestArgs(documentOrOptions, variables, config)
const { headers, ...otherOptions } = config || {}
const { query, operationName } = resolveRequestDocument(requestOptions.document)
try {
const response = await fetch(this.httpUrl, {
method: 'POST',
body: JSON.stringify({
operationName,
query,
variables
}),
headers: {
'Content-Type': 'application/json',
...this.generateAccessTokenHeaders(),
...headers
},
...otherOptions
})
if (!response.ok) {
return {
data: null,
error: {
error: response.statusText,
message: response.statusText,
status: response.status
}
}
}
const { data, errors } = await response.json()
if (errors) {
return {
data: null,
error: errors
}
}
if (typeof data !== 'object' || Array.isArray(data) || data === null) {
return {
data: null,
error: {
error: 'invalid-response',
message: 'incorrect response data from GraphQL server',
status: 0
}
}
}
return { data, error: null }
} catch (e) {
const error = e as Error
return {
data: null,
error: {
message: error.message,
status: error.name === 'AbortError' ? 0 : 500,
error: error.name === 'AbortError' ? 'abort-error' : 'unknown'
}
}
}
}
/**
* Use `nhost.graphql.httpUrl` to get the GraphQL HTTP URL.
* @example
* ```ts
* const url = nhost.graphql.httpUrl;
* ```
*
* @docs https://docs.nhost.io/reference/javascript/graphql/get-http-url
*/
get httpUrl(): string {
return this._url
}
/**
* Use `nhost.graphql.wsUrl` to get the GraphQL WebSocket URL.
* @example
* ```ts
* const url = nhost.graphql.wsUrl;
* ```
*
* @docs https://docs.nhost.io/reference/javascript/graphql/get-ws-url
*/
get wsUrl(): string {
return this._url.replace(/^(http)(s?):\/\//, 'ws$2://')
}
/**
* Use `nhost.graphql.url` to get the GraphQL URL.
* @deprecated Use `nhost.graphql.httpUrl` and `nhost.graphql.wsUrl` instead.
*/
get url(): string {
return this._url
}
/**
* Use `nhost.graphql.getUrl()` to get the GraphQL URL.
* @deprecated Use `nhost.graphql.httpUrl` and `nhost.graphql.wsUrl` instead.
*/
getUrl(): string {
return this._url
}
/**
* Use `nhost.graphql.setAccessToken` to a set an access token to be used in subsequent graphql requests. Note that if you're signin in users with `nhost.auth.signIn()` the access token will be set automatically.
*
* @example
* ```ts
* nhost.graphql.setAccessToken('some-access-token')
* ```
*
* @docs https://docs.nhost.io/reference/javascript/graphql/set-access-token
*/
setAccessToken(accessToken: string | undefined) {
if (!accessToken) {
this.accessToken = null
return
}
this.accessToken = accessToken
}
private generateAccessTokenHeaders(): NhostGraphqlRequestConfig['headers'] {
if (this.adminSecret) {
return {
'x-hasura-admin-secret': this.adminSecret
}
}
if (this.accessToken) {
return {
Authorization: `Bearer ${this.accessToken}`
}
}
return {}
}
}

View File

@@ -0,0 +1,132 @@
import { parse } from 'graphql'
import { jsonToGraphQLQuery, VariableType } from 'json-to-graphql-query'
import {
FieldDefinition,
GenericSchema,
getArgumentType,
getConcreteType,
getFieldType,
getGraphQLType,
getRootOperationNode,
getTypeFromRef,
OperationTypes,
TypeRef
} from '../graphql-object/schema'
const toJson = (
schema: GenericSchema,
parameters: Record<string, any> | true = true,
definition: TypeRef | FieldDefinition,
variables: Record<string, any> = {},
variablesValues: Record<string, any> = {},
variablesPrefix: string = ''
) => {
const select: Record<string, any> = {}
const values = (parameters !== true && parameters.select) || {}
const inputArguments = (parameters !== true && parameters.variables) || {}
const args: Record<string, any> = {}
const onValues = parameters !== true && parameters.on
if (onValues) {
select['__typename'] = true
select['__on'] = Object.keys(onValues).map((fragmentName) => {
const childVariablePrefix = variablesPrefix
? `${variablesPrefix}_on_${fragmentName}`
: `on_${fragmentName}`
const {
query,
variables: newVariables,
variablesValues: newVariablesValues
} = toJson(
schema,
onValues[fragmentName],
getTypeFromRef(schema, { kind: 'OBJECT', name: fragmentName }),
variables,
variablesValues,
childVariablePrefix
)
variables = { ...variables, ...newVariables }
variablesValues = { ...variablesValues, ...newVariablesValues }
return {
__typeName: fragmentName,
...query
}
})
}
if ('type' in definition) {
Object.keys(inputArguments).forEach((key) => {
// ? camel case the variable names?
const uniqueVariableName = variablesPrefix ? `${variablesPrefix}_${key}` : key
variables[uniqueVariableName] = getGraphQLType(schema, getArgumentType(key, definition))
args[key] = new VariableType(uniqueVariableName)
variablesValues[key] = inputArguments[key]
})
}
if (Object.keys(values).length === 0) {
const fieldType = getConcreteType(schema, definition)
if (fieldType.kind === 'OBJECT') {
fieldType.fields?.forEach((field) => {
const concreteType = getConcreteType(schema, field.type)
if (concreteType.kind === 'SCALAR' || concreteType.kind === 'ENUM') {
select[field.name] = true
}
})
}
} else {
Object.entries(values).forEach(([key, value]: [string, any]) => {
const childVariablePrefix = variablesPrefix ? `${variablesPrefix}_${key}` : key
const fieldType = getFieldType(schema, key, definition)
if (!fieldType) {
throw new Error(`Field ${key} is not defined`)
}
const {
query,
variables: newVariables,
variablesValues: newVariablesValues
} = toJson(schema, value, fieldType, variables, variablesValues, childVariablePrefix)
select[key] = query
variables = { ...variables, ...newVariables }
variablesValues = { ...variablesValues, ...newVariablesValues }
})
}
return {
query: { ...select, __args: args },
variables,
variablesValues
}
}
export const toRawGraphQL = (
schema: GenericSchema | undefined,
opType: OperationTypes,
rootOperation: string,
params: any = {}
) => {
if (!schema) throw new Error('Schema is not defined')
const { query, variables, variablesValues } = toJson(
schema,
params,
getRootOperationNode(schema, opType, rootOperation)
)
return {
query: jsonToGraphQLQuery(
{
[opType.toLowerCase()]: {
__variables: variables,
[rootOperation]: query
}
},
{ pretty: true }
),
variables: variablesValues
}
}
export const toGraphQLDocument = (
schema: GenericSchema | undefined,
opType: OperationTypes,
rootOperation: string,
params: any
) => parse(toRawGraphQL(schema, opType, rootOperation, params).query)

View File

@@ -0,0 +1,303 @@
import { CapitalizeSnakeCase, PickFirstTupleItemThatExtends } from './type-helpers'
export type GenericSchema = Record<string, any> & {
introspection: Introspection
types: Record<string, any>
}
export type OperationTypes = 'Query' | 'Mutation' | 'Subscription'
type RootOperationName<
Schema extends GenericSchema | undefined,
OperationType extends OperationTypes,
capitalize extends boolean = true,
IntrospectionSchema = Schema extends GenericSchema ? Schema['introspection']['__schema'] : never,
IntrospectionProperty = `${Uncapitalize<OperationType>}Type`
> = Schema extends GenericSchema
? IntrospectionProperty extends keyof IntrospectionSchema
? IntrospectionSchema[IntrospectionProperty] extends { name: string }
? capitalize extends true
? CapitalizeSnakeCase<IntrospectionSchema[IntrospectionProperty]['name']>
: IntrospectionSchema[IntrospectionProperty]['name']
: never
: never
: never
export type RootOperation<
Schema extends GenericSchema | undefined,
OperationType extends OperationTypes,
OperationName = RootOperationName<Schema, OperationType>
> = Schema extends GenericSchema
? OperationName extends string
? Schema['types'][OperationName] extends object
? Schema['types'][OperationName]
: never
: never
: never
export type OperationsOf<
Schema extends GenericSchema | undefined,
OperationType extends OperationTypes
> = Omit<RootOperation<Schema | undefined, OperationType>, '__typename' | number | symbol>
export type FieldArgs<
Schema extends GenericSchema,
OperationType extends OperationTypes,
FieldName extends string,
Suffix extends string = `_${Capitalize<FieldName>}Args`
> = Schema['types'][`${RootOperationName<Schema, OperationType>}${Suffix}`]
export type OperationRootTypeOf<
Schema extends GenericSchema,
OperationType extends OperationTypes
> = SelectSingleType<
Schema,
{ kind: 'OBJECT'; name: RootOperationName<Schema, OperationType, false> }
>
export type SelectSingleType<
S extends GenericSchema,
Type extends TypeRef
> = PickFirstTupleItemThatExtends<
S['introspection']['__schema']['types'],
Type extends { name: string }
? { name: Type['name']; kind: Type['kind'] }
: { kind: Type['kind'] }
>
type MAX_RECURSION = 10 // maximum recursion depth
type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N
? Acc
: Enumerate<N, [...Acc, Acc['length']]>
type Pred = [never, ...Enumerate<MAX_RECURSION>]
// TODO remove the recursion as we know the possible type depth
export type ConcreteTypeOf<
S extends GenericSchema,
T extends TypeRef,
D extends number = MAX_RECURSION
> = [D] extends [0]
? any
: T extends TypeRef
? T extends NonNullType
? ConcreteTypeOf<S, T['ofType'], Pred[D]>
: T extends ListType
? ConcreteTypeOf<S, T['ofType'], Pred[D]>
: T extends ObjectType | InterfaceType | UnionType
? SelectSingleType<S, T>
: T
: never
export type Introspection = {
__schema: {
queryType: { name: string } | null
mutationType: { name: string } | null
subscriptionType: { name: string } | null
types: Readonly<Array<TypeRef>>
directives: Readonly<[]>
}
}
export type InputObjectType = {
kind: 'INPUT_OBJECT'
name: string
ofType?: null
readonly inputFields?: Readonly<Array<FieldDefinition>>
}
export type ListType = {
kind: 'LIST'
ofType: TypeRef
}
export type NonNullType = {
kind: 'NON_NULL'
ofType: TypeRef
}
export type ObjectType<Name extends string = string> = {
kind: 'OBJECT'
name: Name
interfaces?: Readonly<Array<unknown>>
ofType?: null
fields?: Readonly<Array<FieldDefinition>>
}
export type ScalarType = {
kind: 'SCALAR'
name: string
}
export type UnionType = {
kind: 'UNION'
name: string
ofType?: null
possibleTypes?: Readonly<Array<ObjectType | UnionType | InterfaceType>>
}
export type EnumType = {
kind: 'ENUM'
name: string
ofType?: null
enumValues?: Readonly<Array<{ name: string }>>
}
export type InterfaceType = {
kind: 'INTERFACE'
name: string
ofType?: null
fields?: Readonly<Array<FieldDefinition>>
possibleTypes?: Readonly<Array<ObjectType | UnionType | InterfaceType>>
}
export type TypeRef =
| InputObjectType
| ListType
| NonNullType
| ObjectType
| ScalarType
| UnionType
| EnumType
| InterfaceType
export type FieldDefinition = {
readonly name: string
readonly args?: ReadonlyArray<{ name: string; type: TypeRef }>
readonly type: TypeRef
}
export const getIntrospectionType = <S extends GenericSchema, Type extends Partial<TypeRef>>(
schema: S,
type: Type
) =>
schema.introspection.__schema.types.find((t) =>
Object.entries(type).every(([key, value]) => t[key as keyof TypeRef] === value)
)
const getRootOperationNodeType = <S extends GenericSchema, OperationType extends OperationTypes>(
schema: S,
operationType: OperationType
): ObjectType<OperationType> | null => {
const name =
schema.introspection.__schema[
`${operationType.toLowerCase()}Type` as 'queryType' | 'mutationType' | 'subscriptionType'
]?.name
if (!name) {
return null
}
const type = getIntrospectionType(schema, { kind: 'OBJECT', name }) as ObjectType<OperationType>
if (!type) {
throw new Error(`Could not find the root operation type for ${operationType}`)
}
return type
}
export const getRootOperationNames = <
S extends GenericSchema | undefined,
OperationType extends OperationTypes,
Operations = OperationsOf<S, OperationType>
>(
schema: S,
operationType: OperationType
): Array<keyof Operations> => {
if (!schema) {
return []
}
const type = getRootOperationNodeType(schema, operationType)
return (type?.fields?.map((field) => field.name) as Array<keyof Operations>) ?? []
}
export const getTypeFromRef = (schema: GenericSchema, typeRef?: TypeRef) => {
const type = schema.introspection.__schema.types.find(
(t) => 'name' in t && typeRef && 'name' in typeRef && t.name === typeRef.name
)
if (!type) {
throw new Error(`Could not find type`)
}
return type
}
export const getArgumentType = (name: String, definition: FieldDefinition) => {
const type = definition?.args?.find((f) => f.name === name)?.type
if (!type) {
throw new Error(`Could not determine the type of the argument ${name}`)
}
return type
}
export const getFieldType = (
schema: GenericSchema,
fieldName: String,
definition: TypeRef | FieldDefinition
) => {
const type = 'type' in definition ? definition.type : definition
const objectType = getTypeFromRef(schema, getConcreteType(schema, type))
if (objectType.kind === 'OBJECT' || objectType.kind === 'INTERFACE') {
const type = objectType.fields?.find((f) => f.name === fieldName)
if (!type) {
return null
}
return type
}
if (objectType.kind === 'INPUT_OBJECT') {
const type = objectType?.inputFields?.find((f) => f.name === fieldName)
if (!type) {
return null
}
return type
}
return null
}
export const getRootOperationNode = (
schema: GenericSchema,
opType: OperationTypes,
rootOperation: string
) => {
const rootNode = getRootOperationNodeType(schema, opType)
const node = rootNode?.fields?.find((field) => field.name === rootOperation)
if (!node) {
throw new Error(`Could not find root operation ${rootOperation}`)
}
return node
}
export const getConcreteType = (
schema: GenericSchema,
definition: TypeRef | FieldDefinition
): TypeRef => {
if ('type' in definition) {
return getConcreteType(schema, definition.type)
}
if (definition.kind === 'NON_NULL' || definition.kind === 'LIST') {
return getConcreteType(schema, definition.ofType)
}
const type = schema.introspection.__schema.types?.find(
(f) => 'name' in f && f.name === definition.name
)
if (!type) {
throw new Error('not found')
}
return type
}
export const getGraphQLType = (schema: GenericSchema, type: TypeRef): string => {
if (type.kind === 'NON_NULL') {
return `${getGraphQLType(schema, type.ofType)}!`
}
if (type.kind === 'LIST') {
return `[${getGraphQLType(schema, type.ofType)}]`
}
const typeDesc = schema.introspection.__schema.types?.find(
(f) => 'name' in f && f.name === type.name
)
if (!typeDesc) {
throw new Error(`Could not find type ${type.name}`)
}
if (!('name' in typeDesc)) {
throw new Error(`Could not determine GraphQL type name for ${type.name}`)
}
return typeDesc.name
}

View File

@@ -0,0 +1,68 @@
import { EmptyObject, Join, Split } from './type-fest'
export type { RequireAtLeastOne, SetRequired } from './type-fest'
export type StripImpossibleProperties<T> = Pick<
T,
{ [Key in keyof T]-?: T[Key] extends never ? never : Key }[keyof T]
>
export type UnwrapNullableArray<T> = NonNullable<T extends (infer E)[] ? E : T>
export type UnwrapArray<T> = T extends (infer E)[] ? E : NonNullable<T>
export type WrapArray<T, U> = NonNullable<T> extends any[] ? U[] : U
/** Omit all the optional fields of the type */
type OmitOptionalFields<T> = {
[K in keyof T as T[K] extends Required<T>[K] ? K : never]: T[K]
}
export type MakeOptional<T> = {
[K in keyof T as undefined extends T[K] ? K : never]?: T[K]
} & {
[K in keyof T as undefined extends T[K] ? never : K]: T[K]
}
/** Select only the properties of the object that matches the second generic argument */
export type Select<T, K extends keyof any> = Pick<T, Extract<keyof T, K>>
/** Gets the main GraphQL type from a GraphQL argument type e.g. `[string!]!` returns `string` */
export type GraphQLPredicate<GQLType extends string> = GQLType extends `${infer S}!`
? GraphQLPredicate<S>
: GQLType extends `[${infer S}]`
? GraphQLPredicate<S>
: GQLType
export type ToUnion<T> = T[keyof T]
type CapitalizeEach<T> = T extends [infer I, ...infer R]
? I extends string
? [Capitalize<I>, ...CapitalizeEach<R>]
: []
: []
/** Transform `a_string_type` to `A_String_Type` */
export type CapitalizeSnakeCase<T extends string> = Join<CapitalizeEach<Split<T, '_'>>, '_'>
type RequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K }[keyof T]
type OptionalKeys<T> = { [K in keyof T]: {} extends Pick<T, K> ? never : K }[keyof T]
export type RequiredWhenChildrenAreRequired<key extends string, T> = RequiredKeys<T> extends never
? OptionalKeys<T> extends never
? EmptyObject
: { [k in key]?: T }
: { [k in key]: T }
export type PickFirstTupleItemThatExtends<T, U> = Readonly<T> extends Readonly<
[infer I, ...infer Rest]
>
? I extends U
? I
: PickFirstTupleItemThatExtends<Rest, U>
: never
export type IsTrueOrHasOnlyOptionals<T> = T extends true
? true
: keyof OmitOptionalFields<T> extends never
? true
: false

View File

@@ -0,0 +1,54 @@
// Gracefully poached from https://github.com/sindresorhus/type-fest
export type Split<
S extends string,
Delimiter extends string
> = S extends `${infer Head}${Delimiter}${infer Tail}`
? [Head, ...Split<Tail, Delimiter>]
: S extends Delimiter
? []
: [S]
export type Join<
Strings extends Readonly<Array<string | number>>,
Delimiter extends string
> = Strings extends []
? ''
: Strings extends [string | number]
? `${Strings[0]}`
: Strings extends readonly [string | number, ...infer Rest extends Array<string | number>]
? `${Strings[0]}${Delimiter}${Join<Rest, Delimiter>}`
: string
declare const emptyObjectSymbol: unique symbol
export type EmptyObject = { [emptyObjectSymbol]?: never }
type IsEqual<A, B> = (<G>() => G extends A ? 1 : 2) extends <G>() => G extends B ? 1 : 2
? true
: false
type Simplify<T> = { [KeyType in keyof T]: T[KeyType] }
type Filter<KeyType, ExcludeType> = IsEqual<KeyType, ExcludeType> extends true
? never
: KeyType extends ExcludeType
? never
: KeyType
type Except<ObjectType, KeysType extends keyof ObjectType> = {
[KeyType in keyof ObjectType as Filter<KeyType, KeysType>]: ObjectType[KeyType]
}
export type RequireAtLeastOne<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> = {
// For each `Key` in `KeysType` make a mapped type:
[Key in KeysType]-?: Required<Pick<ObjectType, Key>> & // 1. Make `Key`'s type required
// 2. Make all other keys in `KeysType` optional
Partial<Pick<ObjectType, Exclude<KeysType, Key>>>
}[KeysType] &
// 3. Add the remaining keys not in `KeysType`
Except<ObjectType, KeysType>
export type SetRequired<BaseType, Keys extends keyof BaseType> = Simplify<
// Pick just the keys that are optional from the base type.
Except<BaseType, Keys> &
// Pick the keys that should be required from the base type and make them required.
Required<Pick<BaseType, Keys>>
>

View File

@@ -0,0 +1,172 @@
import {
ConcreteTypeOf,
FieldArgs,
FieldDefinition,
GenericSchema,
InterfaceType,
ObjectType,
OperationRootTypeOf,
OperationsOf,
OperationTypes,
UnionType
} from './schema'
import {
IsTrueOrHasOnlyOptionals,
PickFirstTupleItemThatExtends,
RequireAtLeastOne,
RequiredWhenChildrenAreRequired,
SetRequired,
StripImpossibleProperties,
ToUnion,
UnwrapArray,
UnwrapNullableArray,
WrapArray
} from './type-helpers'
type ParametersOf<
Schema extends GenericSchema,
OperationType extends OperationTypes,
Element extends Record<string, any>,
Definition,
FieldName extends string | undefined,
FieldTypeRef extends FieldDefinition = Definition extends { fields: readonly any[] }
? PickFirstTupleItemThatExtends<Definition['fields'], { name: FieldName }>
: Definition extends FieldDefinition
? Definition
: never,
FieldType extends ObjectType | InterfaceType | UnionType = ConcreteTypeOf<
Schema,
FieldTypeRef['type']
>,
HasArgs = FieldTypeRef extends { args: readonly any[] }
? FieldTypeRef['args']['length'] extends 0
? false
: true
: false,
Args = HasArgs extends true
? unknown extends FieldArgs<Schema, OperationType, FieldTypeRef['name']>
? FieldArgs<Schema, OperationType, FieldType['name']>
: FieldArgs<Schema, OperationType, FieldTypeRef['name']>
: never,
Fields = {
// TODO use rather "key in FieldType['fields'][number]" instead of "key in keyof Element"
[key in keyof Element]?: UnwrapNullableArray<Element[key]> extends object
? // * Accept either a list of fields or `true` to select all the fields
| ParametersOf<
Schema,
OperationType,
UnwrapNullableArray<Element[key]>,
FieldType,
string & key
>
| true
: // * If the element key is not an object/array of objects, it's a scalar field
true
},
Select = {
// * The `select` property is optional, as when absent, all the fields are selected
select?: Fields
},
// * The `variables` property is required when at least one of the children is required
// * If there is no possible variables, the `variables` property is not available
Variables = RequiredWhenChildrenAreRequired<'variables', Args>,
OnFields = FieldType extends SetRequired<UnionType | InterfaceType, 'possibleTypes'>
? {
[key in FieldType['possibleTypes'][number] as key['name']]?:
| ParametersOf<
Schema,
OperationType,
Schema['types'][key['name']],
{ name: key['name']; type: ConcreteTypeOf<Schema, key> },
undefined
>
| true
}
: never,
On = FieldType extends SetRequired<UnionType, 'possibleTypes'>
? // * In an union type, the `on` property is required, and at least one union type must be selected
{ on: RequireAtLeastOne<OnFields> }
: FieldType extends SetRequired<InterfaceType, 'possibleTypes'>
? // * In an interface type, the `on` property is optional.
{ on?: OnFields }
: {}
> = Select & Variables & On
type QueryFields<
Params extends { select?: any },
Element,
UnwrappedParams extends { select?: any } = UnwrapArray<Params>
> = UnwrappedParams extends undefined
? Element
: WrapArray<
NonNullable<Element>,
IsTrueOrHasOnlyOptionals<UnwrappedParams['select']> extends true
? // * Return all the non-object (scalar) fields
StripImpossibleProperties<{
[k in keyof NonNullable<Element>]: k extends keyof UnwrapArray<Element>
? UnwrapArray<NonNullable<Element>>[k] extends object
? never
: UnwrapArray<Element>[k]
: never
}>
: // * The parameter is a list of fields and the element in an object: pick the selected fields
StripImpossibleProperties<{
[k in keyof UnwrappedParams['select']]: k extends keyof UnwrapArray<Element>
? UnwrapArray<NonNullable<Element>>[k] extends object
? QueryFields<UnwrappedParams['select'][k], UnwrapArray<Element>[k]>
: UnwrapArray<Element>[k]
: never
}>
>
type UnionFields<
Schema extends GenericSchema,
Params extends { on: any[] },
Fragments = NonNullable<NonNullable<Params>['on']>
> = ToUnion<{
[fragmentName in keyof Fragments]: {
__typename: NonNullable<Schema['types'][string & fragmentName]['__typename']>
} & QueryFields<NonNullable<Fragments[fragmentName]>, Schema['types'][string & fragmentName]>
}>
// * See: https://stackoverflow.com/a/59230299
type Exactly<T, U> = T & Record<Exclude<keyof U, keyof T>, never>
export type OperationFactory<
Schema extends GenericSchema | undefined,
OperationType extends OperationTypes,
Operations = Schema extends GenericSchema ? OperationsOf<Schema, OperationType> : {}
> = Schema extends GenericSchema
? Required<{
[name in keyof Operations]: <
Operation extends Operations[name],
Element extends UnwrapArray<Operation>,
Params extends ParametersOf<
Schema,
OperationType,
NonNullable<Element>,
OperationRootTypeOf<Schema, OperationType>,
string & name
>,
// * See: https://stackoverflow.com/a/59230299
ExactParams extends Exactly<Params, ExactParams>,
Result extends WrapArray<
Operation,
ExactParams extends { on: any }
?
| (UnionFields<Schema, ExactParams> & QueryFields<ExactParams, Element>)
| ({
// * We add `__typename` as an union discrimimator.
// * Interfaces have no `__typename` property, so we set it to `null` if not present.
__typename: Element extends { __typename: any } ? Element['__typename'] : null
} & QueryFields<ExactParams, Element>)
: QueryFields<ExactParams, Element>
>
>(
// * Parameters are required when variables are required
...parameters: ExactParams extends { variables: any } | { on: any }
? [ExactParams]
: [ExactParams?]
) => Promise<Result>
}>
: {}

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