From b464630df0bb5c6278df266d0399c140168be5ab Mon Sep 17 00:00:00 2001 From: Dennis Falling Date: Mon, 10 Aug 2026 12:50:58 +0100 Subject: [PATCH] Show the booking details behind an imported element MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API now parses structured details out of an imported booking — flight numbers, reservation codes, seats, where transport leaves from and arrives — and exposes them as element_metadata. The app fetched none of it, so a flight imported from a confirmation email looked like any other pin. Renders them as a Booking section on the element detail screen, ordered and titled the same way the web app does so one booking reads the same in both places: the kind of transport titles the number rather than taking a row of its own, a flight number links out to its status, and the raw address only appears when geocoding failed (otherwise it's already the element's location). Fetching metadata on the import and update mutations too, so an element lands in the cache with its booking details already attached. Fix GraphQL codegen while here, since adding a field required running it. It couldn't run at all: typescript-react-apollo peers at graphql <=16 and crashed on the installed 17, and its Apollo v3-shaped hooks needed ~15 @ts-ignores hand-applied after every regen. Dropped it, along with the typescript plugin whose schema types typescript-operations 6.x now emits itself (running both defined every input twice). Codegen emits a TypedDocumentNode per operation instead, passed to Apollo's own hooks, which infer results and variables from it — so `bun run codegen` is now a clean, idempotent, no-touch-ups command. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 22 +- __tests__/metadataRows.test.ts | 105 ++ bun.lock | 151 ++- codegen.ts | 48 +- package.json | 7 +- src/auth/LoginScreen.tsx | 5 +- src/auth/authClient.ts | 5 +- src/graphql/__generated__/types.ts | 1071 +++------------------ src/graphql/queries/elementDetail.graphql | 10 + src/graphql/queries/importShare.graphql | 10 + src/graphql/queries/updateElement.graphql | 10 + src/map/ElementDetailScreen.tsx | 62 +- src/map/ElementEditScreen.tsx | 21 +- src/map/ElementPreviewCard.tsx | 7 +- src/map/MapScreen.tsx | 11 +- src/map/SearchOverlay.tsx | 8 +- src/map/metadataRows.ts | 95 ++ src/photos/photoUpload.ts | 19 +- src/share/ImportShareScreen.tsx | 5 +- 19 files changed, 571 insertions(+), 1101 deletions(-) create mode 100644 __tests__/metadataRows.test.ts create mode 100644 src/map/metadataRows.ts diff --git a/README.md b/README.md index b389579..d319674 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,15 @@ Android-only React Native app, distributed via GitHub Releases for installation [Obtainium](https://github.com/ImranR98/Obtainium). Targets GrapheneOS and stock Android; intentionally avoids Google Play Services, Firebase, and Play Integrity. -Connects to an Elixir/Phoenix GraphQL API. Types and hooks are code-generated from the -schema with [`graphql-codegen`](https://the-guild.dev/graphql/codegen) + Apollo Client. +Connects to an Elixir/Phoenix GraphQL API. Operation types and typed documents are +code-generated from the schema with [`graphql-codegen`](https://the-guild.dev/graphql/codegen) +and used with Apollo Client's own hooks. ## Stack - React Native 0.85 (bare, TypeScript, no Expo) -- Apollo Client 3 + `@apollo/client` -- `@graphql-codegen/cli` with `typescript`, `typescript-operations`, `typescript-react-apollo` +- Apollo Client 4 (`@apollo/client`) +- `@graphql-codegen/cli` with `typescript-operations` + `typed-document-node` - Package manager: **bun** (lockfile: `bun.lock`). Node is still required at runtime — Metro and Gradle's react.gradle plugin invoke `node` directly. - Linter + formatter: **biome** (`biome.json`) — single tool, replaces eslint + prettier - Toolchain pinned via [mise](https://mise.jdx.dev) (`mise.toml`): Node 22, Bun 1.2, JDK 17 (Zulu) @@ -159,18 +160,25 @@ Output: `src/graphql/__generated__/types.ts` — committed to the repo. CI doesn't run codegen (no schema in CI), so remember to regenerate and commit after editing a `.graphql` file. -Example of using a generated hook: +Codegen emits a `TypedDocumentNode` per operation (plus its result/variable +types) — not hooks. Pass the document to Apollo's own hook and both the result +and the variables are inferred from it: ```tsx -import { usePingQuery } from './src/graphql/__generated__/types'; +import { useQuery } from '@apollo/client/react'; +import { PingDocument } from './src/graphql/__generated__/types'; function Ping() { - const { data, loading } = usePingQuery(); + const { data, loading } = useQuery(PingDocument); if (loading) return ; return {data?.ping}; } ``` +`useMutation(SomeDocument)` and `useLazyQuery(SomeDocument)` work the same way. +Deliberately no `typescript-react-apollo`: its generated hooks are Apollo v3-shaped +and it pins `graphql` to <=16. + ## Releasing (signed APK to GitHub Releases) The `Release APK` workflow (`.github/workflows/release.yml`) builds a signed APK on diff --git a/__tests__/metadataRows.test.ts b/__tests__/metadataRows.test.ts new file mode 100644 index 0000000..6d24ee2 --- /dev/null +++ b/__tests__/metadataRows.test.ts @@ -0,0 +1,105 @@ +/** + * @format + */ + +import {metadataRows} from '../src/map/metadataRows'; + +const titles = (rows: ReturnType) => + rows.map(row => `${row.title}: ${row.value}`); + +test('an element with no metadata has no rows', () => { + expect(metadataRows(null)).toEqual([]); + expect(metadataRows(undefined)).toEqual([]); + expect(metadataRows({})).toEqual([]); +}); + +test('rows read in booking order, not the order the fields arrived', () => { + expect( + titles( + metadataRows({ + seat: '14C', + arrivalLocation: 'Barcelona', + number: 'IB3216', + departureLocation: 'Madrid', + reservation: 'XY7ZQ2', + }), + ), + ).toEqual([ + 'Number: IB3216', + 'From: Madrid', + 'To: Barcelona', + 'Reservation: XY7ZQ2', + 'Seat: 14C', + ]); +}); + +test('the kind of transportation titles the number', () => { + expect(titles(metadataRows({type: 'flight', number: 'IB3216'}))).toEqual([ + 'Flight: IB3216', + ]); + expect(titles(metadataRows({type: 'train', number: 'AVE 3092'}))).toEqual([ + 'Train: AVE 3092', + ]); + expect(titles(metadataRows({type: 'ferry', number: '7'}))).toEqual([ + 'Ferry: 7', + ]); +}); + +test('a kind with no name of its own keeps the generic title', () => { + expect(titles(metadataRows({type: 'car', number: 'ABC123'}))).toEqual([ + 'Number: ABC123', + ]); + expect(titles(metadataRows({number: 'ABC123'}))).toEqual(['Number: ABC123']); +}); + +test('type alone is never a row of its own', () => { + expect(metadataRows({type: 'flight'})).toEqual([]); +}); + +test('a flight number links to its status, other numbers do not', () => { + const [flight] = metadataRows({type: 'flight', number: 'American 291'}); + expect(flight.link).toBe( + 'https://www.google.com/search?q=American%20291%20flight%20status', + ); + + const [train] = metadataRows({type: 'train', number: 'AVE 3092'}); + expect(train.link).toBeNull(); +}); + +test('the raw address only shows when there is no geocoded location', () => { + const metadata = {address: '12 Gran Via, Madrid'}; + expect(titles(metadataRows(metadata, {hasLocation: false}))).toEqual([ + 'Address: 12 Gran Via, Madrid', + ]); + expect(metadataRows(metadata, {hasLocation: true})).toEqual([]); +}); + +test('a location does not suppress the other rows', () => { + expect( + titles( + metadataRows( + {reservation: 'XY7ZQ2', address: '12 Gran Via, Madrid'}, + {hasLocation: true}, + ), + ), + ).toEqual(['Reservation: XY7ZQ2']); +}); + +test('blank and whitespace-only values are skipped, and values are trimmed', () => { + expect( + titles( + metadataRows({ + number: ' IB3216 ', + seat: '', + reservation: ' ', + paymentDetails: null, + }), + ), + ).toEqual(['Number: IB3216']); +}); + +test('payment notes are titled Payment', () => { + expect(titles(metadataRows({paymentDetails: 'Paid €100'}))).toEqual([ + 'Payment: Paid €100', + ]); +}); diff --git a/bun.lock b/bun.lock index 267fba2..eb60a56 100644 --- a/bun.lock +++ b/bun.lock @@ -26,11 +26,10 @@ "@babel/preset-env": "^7.25.3", "@babel/runtime": "^7.25.0", "@biomejs/biome": "^2.4.15", - "@graphql-codegen/cli": "^7.0.0", + "@graphql-codegen/cli": "^7.2.0", "@graphql-codegen/introspection": "^6.0.0", - "@graphql-codegen/typescript": "^6.0.0", - "@graphql-codegen/typescript-operations": "^6.0.0", - "@graphql-codegen/typescript-react-apollo": "^4.0.0", + "@graphql-codegen/typed-document-node": "^7.1.0", + "@graphql-codegen/typescript-operations": "^6.1.5", "@react-native-community/cli": "20.2.0", "@react-native-community/cli-platform-android": "20.2.0", "@react-native/babel-preset": "0.86.0", @@ -317,29 +316,27 @@ "@fastify/busboy": ["@fastify/busboy@3.2.0", "", {}, "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA=="], - "@graphql-codegen/add": ["@graphql-codegen/add@7.0.1", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-kWw6RMu9ysBw1wcgcgf9mOnswc5M3ekOApDTiaJC/UZNTEYins01srZHYTP7z3P/WlGGC844BRtjwh3U2kNd/A=="], + "@graphql-codegen/add": ["@graphql-codegen/add@7.1.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-bytJg1kel5zfgK3JSYbGwtpbNe6F9OPZSR6DiMDe9RVxblAgl6w4zEEPd/mM3rhNJ1VmGYLbNnf5e1eUfXQEbg=="], - "@graphql-codegen/cli": ["@graphql-codegen/cli@7.1.2", "", { "dependencies": { "@babel/generator": "^7.18.13", "@babel/template": "^7.18.10", "@babel/types": "^7.18.13", "@graphql-codegen/client-preset": "^6.0.1", "@graphql-codegen/core": "^6.1.0", "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-tools/apollo-engine-loader": "^8.0.28", "@graphql-tools/code-file-loader": "^8.1.28", "@graphql-tools/git-loader": "^8.0.32", "@graphql-tools/github-loader": "^9.0.6", "@graphql-tools/graphql-file-loader": "^8.1.11", "@graphql-tools/json-file-loader": "^8.0.26", "@graphql-tools/load": "^8.1.8", "@graphql-tools/merge": "^9.0.6", "@graphql-tools/url-loader": "^9.0.6", "@graphql-tools/utils": "^11.0.0", "@inquirer/prompts": "^8.3.2", "@whatwg-node/fetch": "^0.10.0", "chalk": "^5.6.0", "cosmiconfig": "^9.0.0", "debounce": "^3.0.0", "detect-indent": "^7.0.0", "graphql-config": "^5.1.6", "is-glob": "^4.0.1", "jiti": "^2.3.0", "json-to-pretty-yaml": "^1.2.2", "listr2": "^10.2.1", "log-symbols": "^7.0.0", "micromatch": "^4.0.5", "shell-quote": "^1.7.3", "string-env-interpolation": "^1.0.1", "ts-log": "^3.0.0", "tslib": "^2.4.0", "yaml": "^2.3.1", "yargs": "^18.0.0" }, "peerDependencies": { "@parcel/watcher": "^2.1.0", "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" }, "optionalPeers": ["@parcel/watcher"], "bin": { "gql-gen": "esm/bin.js", "graphql-codegen": "esm/bin.js", "graphql-codegen-cjs": "cjs/bin.js", "graphql-codegen-esm": "esm/bin.js", "graphql-code-generator": "esm/bin.js" } }, "sha512-RiXedOZhanodp8fCBlpciyic17kSv0hSMboDaE9/ZWXC6f4g1aQBTZmQJOsT9Dtxy0SxqmMY674NoTlJgELNeA=="], + "@graphql-codegen/cli": ["@graphql-codegen/cli@7.2.0", "", { "dependencies": { "@babel/generator": "^7.18.13", "@babel/template": "^7.18.10", "@babel/types": "^7.18.13", "@graphql-codegen/client-preset": "^6.1.0", "@graphql-codegen/core": "^6.2.0", "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-tools/apollo-engine-loader": "^8.0.28", "@graphql-tools/code-file-loader": "^8.1.28", "@graphql-tools/git-loader": "^8.0.32", "@graphql-tools/github-loader": "^9.0.6", "@graphql-tools/graphql-file-loader": "^8.1.11", "@graphql-tools/json-file-loader": "^8.0.26", "@graphql-tools/load": "^8.1.8", "@graphql-tools/merge": "^9.0.6", "@graphql-tools/url-loader": "^9.0.6", "@graphql-tools/utils": "^11.2.0", "@inquirer/prompts": "^8.3.2", "@whatwg-node/fetch": "^0.10.0", "chalk": "^5.6.0", "cosmiconfig": "^9.0.0", "debounce": "^3.0.0", "detect-indent": "^7.0.0", "graphql-config": "^5.1.6", "is-glob": "^4.0.1", "jiti": "^2.3.0", "json-to-pretty-yaml": "^1.2.2", "listr2": "^10.2.1", "log-symbols": "^7.0.0", "micromatch": "^4.0.5", "shell-quote": "^1.7.3", "string-env-interpolation": "^1.0.1", "ts-log": "^3.0.0", "tslib": "^2.4.0", "yaml": "^2.3.1", "yargs": "^18.0.0" }, "peerDependencies": { "@parcel/watcher": "^2.1.0", "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" }, "optionalPeers": ["@parcel/watcher"], "bin": { "gql-gen": "esm/bin.js", "graphql-codegen": "esm/bin.js", "graphql-code-generator": "esm/bin.js", "graphql-codegen-esm": "esm/bin.js", "graphql-codegen-cjs": "cjs/bin.js" } }, "sha512-JPJw2vquEIpO3b8XJyxFVTrYi6WRn/OKu/SlzQA+IwAVT7GZPeG+AHmfRXAvpVMj31899nTpQYEQGUxx3ZqubQ=="], - "@graphql-codegen/client-preset": ["@graphql-codegen/client-preset@6.0.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.20.2", "@babel/template": "^7.20.7", "@graphql-codegen/add": "^7.0.1", "@graphql-codegen/gql-tag-operations": "^6.0.1", "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-codegen/typed-document-node": "^7.0.1", "@graphql-codegen/typescript": "^6.0.2", "@graphql-codegen/typescript-operations": "^6.0.3", "@graphql-codegen/visitor-plugin-common": "^7.0.3", "@graphql-tools/documents": "^1.0.0", "@graphql-tools/utils": "^11.0.0", "@graphql-typed-document-node/core": "3.2.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", "graphql-sock": "^1.0.0" }, "optionalPeers": ["graphql-sock"] }, "sha512-6wh0ZHG9WzBD6bE4AVOO6VCCMXK2orxHuXxaNKj+sj1w0qZ3Y3WIjZnqZLg6JZrHCIs/e+gy3T15Dc2pH8IbHA=="], + "@graphql-codegen/client-preset": ["@graphql-codegen/client-preset@6.1.2", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.20.2", "@babel/template": "^7.20.7", "@graphql-codegen/add": "^7.1.0", "@graphql-codegen/gql-tag-operations": "^6.1.0", "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-codegen/typed-document-node": "^7.1.0", "@graphql-codegen/typescript": "^6.1.0", "@graphql-codegen/typescript-operations": "^6.1.5", "@graphql-codegen/visitor-plugin-common": "^7.2.4", "@graphql-tools/documents": "^1.0.0", "@graphql-tools/utils": "^11.2.0", "@graphql-typed-document-node/core": "3.2.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "graphql-sock": "^1.0.0" }, "optionalPeers": ["graphql-sock"] }, "sha512-1ZxyQXoTyK2Q0i46PBAa7meQ+Ds/tJxBHhTkqDbPhNdNeeabcvznPksIek2pHx4wSwc8jvIT87CktrWj5n5Cqg=="], - "@graphql-codegen/core": ["@graphql-codegen/core@6.1.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-tools/schema": "^10.0.0", "@graphql-tools/utils": "^11.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-jReAzuCYlrSBJHW2bfBpDl/vMRCw0yQEoTvGi9K+3OTsazDXEQGOpCVfj8p/xO2h7ynu5Yrvzo0sUylVv0CnwA=="], + "@graphql-codegen/core": ["@graphql-codegen/core@6.2.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-tools/schema": "^10.0.0", "@graphql-tools/utils": "^11.2.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-RZadhhwYhuy2ZdIGK40vYVBMzXEFGkCC+58MUC/F2af/gKznEYNzHgmNBUBCk/BTklyUsNu0mIXmyGE4tTA0PA=="], - "@graphql-codegen/gql-tag-operations": ["@graphql-codegen/gql-tag-operations@6.0.1", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-codegen/visitor-plugin-common": "^7.0.3", "@graphql-tools/utils": "^11.0.0", "auto-bind": "^5.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-eHYUIchZLG6G+kafeKnUByL2Nkmb8Uj2vg33UVLFj8XJ2coC4b1iRDWxCdTXbupZrN0FaM0QRRBLs3zBEAzcJg=="], + "@graphql-codegen/gql-tag-operations": ["@graphql-codegen/gql-tag-operations@6.1.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-codegen/visitor-plugin-common": "^7.2.0", "@graphql-tools/utils": "^11.2.0", "auto-bind": "^5.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-AmMcZFwonufvWJnQm7I0lBxKpAm+35BcCrOOvUlBoviohiR17aPoTGAOaNAEtpcpI86lnZ9m9AXUdiKMdm8nnQ=="], "@graphql-codegen/introspection": ["@graphql-codegen/introspection@6.0.1", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-codegen/visitor-plugin-common": "^7.0.3", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-X8LdqTjWf6G1k1cqM1WpBMEarFWDRLxJxo5CfigoU1Aw3GHn8ToVoPvHd4wrQyS8WA+2ijsd6+jjzo5mXg9xuQ=="], - "@graphql-codegen/plugin-helpers": ["@graphql-codegen/plugin-helpers@7.0.1", "", { "dependencies": { "@graphql-tools/utils": "^11.0.0", "change-case-all": "^2.1.0", "common-tags": "1.8.2", "import-from": "4.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-S2X0YT3XQbP2haqhIeku8GOXo2j8QuBu7BrLsOEHz4UeMu78y3rja1Q4ri3oJ0jq4dMgaQlazoVHI/A+FAKMGw=="], + "@graphql-codegen/plugin-helpers": ["@graphql-codegen/plugin-helpers@7.1.0", "", { "dependencies": { "@graphql-tools/utils": "^11.2.0", "change-case-all": "^2.1.0", "common-tags": "1.8.2", "import-from": "4.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-ieJH7kZ5oSZKBPJs7CvHMrFY/CLYLklqv74ir93qMwRna6geZsbIMoJzTDBXohxcQTITiProiYSGrEtZjIpYGg=="], - "@graphql-codegen/schema-ast": ["@graphql-codegen/schema-ast@6.0.1", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-tools/utils": "^11.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-P16b6XCWXfcrA4fkuAyqoy883USAULifv8YWgEOrNKDAnr2DR+Kr85jSomknIUTY39wiuvisv4/lrdXobwK6sA=="], + "@graphql-codegen/schema-ast": ["@graphql-codegen/schema-ast@6.1.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-tools/utils": "^11.2.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-/xuGkM5gUNFRoaQLumKbENdX7Hc8ha49z9OXsEZY8E+46mMjqzXGF0NtCJ892cmoX7EUgI5c8T+LZqS2upx2Aw=="], - "@graphql-codegen/typed-document-node": ["@graphql-codegen/typed-document-node@7.0.3", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-codegen/visitor-plugin-common": "^7.1.0", "auto-bind": "^5.0.0", "change-case-all": "^2.1.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-l/4KenYJG5D8Aj6Aa2KPeS0fdMIIi04Qx28d4SLwMWuyFU9WXspU5mR9YMNDRZzaTgBtGR8aMIl9RzyiWf5uUw=="], + "@graphql-codegen/typed-document-node": ["@graphql-codegen/typed-document-node@7.1.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-codegen/visitor-plugin-common": "^7.2.0", "auto-bind": "^5.0.0", "change-case-all": "^2.1.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-V6H+ItyqXtYY+JQb76LAoN627Xfzpn29/ifwCFAv61iEepzNzh86sa+yZclflr0G8LDmhcVY5hpPJd3a1qbOfw=="], - "@graphql-codegen/typescript": ["@graphql-codegen/typescript@6.0.2", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-codegen/schema-ast": "^6.0.1", "@graphql-codegen/visitor-plugin-common": "^7.0.3", "auto-bind": "^5.0.0", "tslib": "~2.8.0" }, "peerDependencies": { "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-zyLfKsFJ7TRkQ0PyaUVuiAek9TSbtVJwwBoOuaE9RAWr45+9Y5W1LYldpiSTcyfxKVSIniE7Gj0V87qzrpdyYw=="], + "@graphql-codegen/typescript": ["@graphql-codegen/typescript@6.1.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-codegen/schema-ast": "^6.1.0", "@graphql-codegen/visitor-plugin-common": "^7.2.0", "auto-bind": "^5.0.0", "tslib": "~2.8.0" }, "peerDependencies": { "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-2Hu3111O/AwV28Ap7tNsixlmXSAJuQbQArQklx+IC/tNswpckZnCfmlcBtTJrGU1+mJXEneJXGfb2XWvKjbhlQ=="], - "@graphql-codegen/typescript-operations": ["@graphql-codegen/typescript-operations@6.0.3", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-codegen/schema-ast": "^6.0.1", "@graphql-codegen/visitor-plugin-common": "^7.0.3", "auto-bind": "^5.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", "graphql-sock": "^1.0.0" }, "optionalPeers": ["graphql-sock"] }, "sha512-5gnHdBgKkpKJOiqyKo37UfwigNtezfN94UI/NnyCROl6oDAyt0A+1VeS5cBlgRECdD/TQ1vjHCu14B41Sl7yLw=="], - - "@graphql-codegen/typescript-react-apollo": ["@graphql-codegen/typescript-react-apollo@4.4.2", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^6.3.0", "@graphql-codegen/visitor-plugin-common": "^6.3.0", "auto-bind": "~4.0.0", "change-case-all": "1.0.15", "tslib": "^2.8.1" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-S/VQeLWMNzo/WnUpvCQELqh2qgAK4H9kkWyC8JrrrPHaV3w/BmOwzeHpcwlHKcuSYWRH6u61XPRQ5+eCjj00AQ=="], + "@graphql-codegen/typescript-operations": ["@graphql-codegen/typescript-operations@6.1.5", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-codegen/schema-ast": "^6.1.0", "@graphql-codegen/visitor-plugin-common": "^7.2.3", "auto-bind": "^5.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "graphql-sock": "^1.0.0" }, "optionalPeers": ["graphql-sock"] }, "sha512-ZiQ2CB6jiYYxFetdrutSsbNsiukh47UbVY9y3NjwWI8IUlslD+rDYN7MLDJrPFA5YXpv38ZBxh6q8PywRf1KfA=="], "@graphql-codegen/visitor-plugin-common": ["@graphql-codegen/visitor-plugin-common@7.1.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.0.1", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.1.1", "@graphql-tools/utils": "^11.0.0", "auto-bind": "^5.0.0", "change-case-all": "^2.1.0", "dependency-graph": "^1.0.0", "graphql-tag": "^2.11.0", "parse-filepath": "^1.0.2", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-CO4fJyflbYBuAwbQD16bAuWBIXkz9il3JwyC+pQzXh8NJ+BZZDXmYjmVeGeJuoMUIQDb+CNo2thCU0bFFamAkg=="], @@ -389,7 +386,7 @@ "@graphql-tools/url-loader": ["@graphql-tools/url-loader@9.1.2", "", { "dependencies": { "@graphql-tools/executor-graphql-ws": "^3.1.4", "@graphql-tools/executor-http": "^3.2.1", "@graphql-tools/executor-legacy-ws": "^1.1.28", "@graphql-tools/utils": "^11.1.0", "@graphql-tools/wrap": "^11.1.1", "@types/ws": "^8.0.0", "@whatwg-node/fetch": "^0.10.13", "@whatwg-node/promise-helpers": "^1.0.0", "isomorphic-ws": "^5.0.0", "sync-fetch": "0.6.0", "tslib": "^2.4.0", "ws": "^8.20.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-pVSiPrfWQKb3jq23Pl7EjbB2uv3tgZLnWo/axkmg4itAEZ5s/vV/jKa8P1HZzUnSVUTR+8tcEZVeNsUbzFCbkg=="], - "@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + "@graphql-tools/utils": ["@graphql-tools/utils@11.2.2", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-Do2A/t6ayqOma8m7PvpYMsCBswL+NB35BQSng4GWSBqafL2/BnfAZy/NSENPwV721Rm2fG0BHETFC0+FJJZmLw=="], "@graphql-tools/wrap": ["@graphql-tools/wrap@11.1.15", "", { "dependencies": { "@graphql-tools/delegate": "^12.0.16", "@graphql-tools/schema": "^10.0.29", "@graphql-tools/utils": "^11.0.0", "@whatwg-node/promise-helpers": "^1.3.2", "tslib": "^2.8.1" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-GCMx6l0MPwHVaBMHf29oG8eIrsJ8PBXq9y5DNX9/r9oCpCBfqxfWzcejx4CpO4chA3+yylGOKcAyEbOUgxfI1Q=="], @@ -727,19 +724,15 @@ "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "camel-case": ["camel-case@4.1.2", "", { "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" } }, "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw=="], - "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="], "caniuse-lite": ["caniuse-lite@1.0.30001793", "", {}, "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA=="], - "capital-case": ["capital-case@1.0.4", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", "upper-case-first": "^2.0.2" } }, "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A=="], - "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], - "change-case": ["change-case@4.1.2", "", { "dependencies": { "camel-case": "^4.1.2", "capital-case": "^1.0.4", "constant-case": "^3.0.4", "dot-case": "^3.0.4", "header-case": "^2.0.4", "no-case": "^3.0.4", "param-case": "^3.0.4", "pascal-case": "^3.1.2", "path-case": "^3.0.4", "sentence-case": "^3.0.4", "snake-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A=="], + "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], - "change-case-all": ["change-case-all@1.0.15", "", { "dependencies": { "change-case": "^4.1.2", "is-lower-case": "^2.0.2", "is-upper-case": "^2.0.2", "lower-case": "^2.0.2", "lower-case-first": "^2.0.2", "sponge-case": "^1.0.1", "swap-case": "^2.0.2", "title-case": "^3.0.3", "upper-case": "^2.0.2", "upper-case-first": "^2.0.2" } }, "sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ=="], + "change-case-all": ["change-case-all@2.1.0", "", { "dependencies": { "change-case": "^5.2.0", "sponge-case": "^2.0.2", "swap-case": "^3.0.2", "title-case": "^3.0.3" } }, "sha512-v6b0WWWkZUMHVuYk82l+WROgkUm4qEN2w5hKRNWtEOYwWqUGoi8C6xH0l1RLF1EoWqDFK6MFclmN3od6ws3/uw=="], "char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="], @@ -793,8 +786,6 @@ "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="], - "constant-case": ["constant-case@3.0.4", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", "upper-case": "^2.0.2" } }, "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ=="], - "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], @@ -847,8 +838,6 @@ "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], - "dot-case": ["dot-case@3.0.4", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w=="], - "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], @@ -989,8 +978,6 @@ "hasown": ["hasown@2.0.3", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg=="], - "header-case": ["header-case@2.0.4", "", { "dependencies": { "capital-case": "^1.0.4", "tslib": "^2.0.3" } }, "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q=="], - "hermes-compiler": ["hermes-compiler@250829098.0.14", "", {}, "sha512-5meXwsZxgiqFaJjNzwjzI9IyUkuGGBisu+z9BvQWmGVpjH6nz11hgqkyxe4dl8UAdyIV4lTbz91+Dlnjz0VxqA=="], "hermes-estree": ["hermes-estree@0.36.0", "", {}, "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w=="], @@ -1049,8 +1036,6 @@ "is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="], - "is-lower-case": ["is-lower-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ=="], - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], "is-relative": ["is-relative@1.0.0", "", { "dependencies": { "is-unc-path": "^1.0.0" } }, "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA=="], @@ -1061,8 +1046,6 @@ "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], - "is-upper-case": ["is-upper-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ=="], - "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], "is-wsl": ["is-wsl@1.1.0", "", {}, "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw=="], @@ -1185,10 +1168,6 @@ "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], - "lower-case": ["lower-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg=="], - - "lower-case-first": ["lower-case-first@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg=="], - "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="], @@ -1267,8 +1246,6 @@ "negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], - "no-case": ["no-case@3.0.4", "", { "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg=="], - "nocache": ["nocache@3.0.4", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="], "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], @@ -1311,8 +1288,6 @@ "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], - "param-case": ["param-case@3.0.4", "", { "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A=="], - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], "parse-filepath": ["parse-filepath@1.0.2", "", { "dependencies": { "is-absolute": "^1.0.0", "map-cache": "^0.2.0", "path-root": "^0.1.1" } }, "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q=="], @@ -1321,10 +1296,6 @@ "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], - "pascal-case": ["pascal-case@3.1.2", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g=="], - - "path-case": ["path-case@3.0.4", "", { "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg=="], - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-expression-matcher": ["path-expression-matcher@1.5.0", "", {}, "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ=="], @@ -1449,8 +1420,6 @@ "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], - "sentence-case": ["sentence-case@3.0.4", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", "upper-case-first": "^2.0.2" } }, "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg=="], - "serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="], "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], @@ -1485,15 +1454,13 @@ "slice-ansi": ["slice-ansi@8.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" } }, "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg=="], - "snake-case": ["snake-case@3.0.4", "", { "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg=="], - "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], "source-map-support": ["source-map-support@0.5.13", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w=="], "split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="], - "sponge-case": ["sponge-case@1.0.1", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA=="], + "sponge-case": ["sponge-case@2.0.3", "", {}, "sha512-i4h9ZGRfxV6Xw3mpZSFOfbXjf0cQcYmssGWutgNIfFZ2VM+YIWfD71N/kjjwK6X/AAHzBr+rciEcn/L34S8TGw=="], "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], @@ -1529,7 +1496,7 @@ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "swap-case": ["swap-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw=="], + "swap-case": ["swap-case@3.0.3", "", {}, "sha512-6p4op8wE9CQv7uDFzulI6YXUw4lD9n4oQierdbFThEKVWVQcbQcUjdP27W8XE7V4QnWmnq9jueSHceyyQnqQVA=="], "sync-fetch": ["sync-fetch@0.6.0", "", { "dependencies": { "node-fetch": "^3.3.2", "timeout-signal": "^2.0.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-IELLEvzHuCfc1uTsshPK58ViSdNqXxlml1U+fmwJIKLYKOr/rAtBrorE2RYm5IHaMpDNlmC0fr1LAvdXvyheEQ=="], @@ -1587,10 +1554,6 @@ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], - "upper-case": ["upper-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg=="], - - "upper-case-first": ["upper-case-first@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg=="], - "urlpattern-polyfill": ["urlpattern-polyfill@10.1.0", "", {}, "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw=="], "use-latest-callback": ["use-latest-callback@0.2.6", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg=="], @@ -1651,24 +1614,70 @@ "@babel/plugin-transform-runtime/babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.13.0", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.5", "core-js-compat": "^3.43.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A=="], - "@graphql-codegen/plugin-helpers/change-case-all": ["change-case-all@2.1.0", "", { "dependencies": { "change-case": "^5.2.0", "sponge-case": "^2.0.2", "swap-case": "^3.0.2", "title-case": "^3.0.3" } }, "sha512-v6b0WWWkZUMHVuYk82l+WROgkUm4qEN2w5hKRNWtEOYwWqUGoi8C6xH0l1RLF1EoWqDFK6MFclmN3od6ws3/uw=="], + "@graphql-codegen/client-preset/@graphql-codegen/visitor-plugin-common": ["@graphql-codegen/visitor-plugin-common@7.2.4", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.1.1", "@graphql-tools/utils": "^11.2.0", "auto-bind": "^5.0.0", "change-case-all": "^2.1.0", "dependency-graph": "^1.0.0", "graphql-tag": "^2.11.0", "parse-filepath": "^1.0.2", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-VMq1LNVLIuG4rmumKhzTeCcTDhQf2PLVWWUGe7LOwLstBy8xQ+JdDWntsaK0FbLm8p1pCr707Sx6Iy+GbE6RTg=="], + + "@graphql-codegen/gql-tag-operations/@graphql-codegen/visitor-plugin-common": ["@graphql-codegen/visitor-plugin-common@7.2.4", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.1.1", "@graphql-tools/utils": "^11.2.0", "auto-bind": "^5.0.0", "change-case-all": "^2.1.0", "dependency-graph": "^1.0.0", "graphql-tag": "^2.11.0", "parse-filepath": "^1.0.2", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-VMq1LNVLIuG4rmumKhzTeCcTDhQf2PLVWWUGe7LOwLstBy8xQ+JdDWntsaK0FbLm8p1pCr707Sx6Iy+GbE6RTg=="], + + "@graphql-codegen/introspection/@graphql-codegen/plugin-helpers": ["@graphql-codegen/plugin-helpers@7.0.1", "", { "dependencies": { "@graphql-tools/utils": "^11.0.0", "change-case-all": "^2.1.0", "common-tags": "1.8.2", "import-from": "4.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-S2X0YT3XQbP2haqhIeku8GOXo2j8QuBu7BrLsOEHz4UeMu78y3rja1Q4ri3oJ0jq4dMgaQlazoVHI/A+FAKMGw=="], + + "@graphql-codegen/typed-document-node/@graphql-codegen/visitor-plugin-common": ["@graphql-codegen/visitor-plugin-common@7.2.4", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.1.1", "@graphql-tools/utils": "^11.2.0", "auto-bind": "^5.0.0", "change-case-all": "^2.1.0", "dependency-graph": "^1.0.0", "graphql-tag": "^2.11.0", "parse-filepath": "^1.0.2", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-VMq1LNVLIuG4rmumKhzTeCcTDhQf2PLVWWUGe7LOwLstBy8xQ+JdDWntsaK0FbLm8p1pCr707Sx6Iy+GbE6RTg=="], + + "@graphql-codegen/typescript/@graphql-codegen/visitor-plugin-common": ["@graphql-codegen/visitor-plugin-common@7.2.4", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.1.1", "@graphql-tools/utils": "^11.2.0", "auto-bind": "^5.0.0", "change-case-all": "^2.1.0", "dependency-graph": "^1.0.0", "graphql-tag": "^2.11.0", "parse-filepath": "^1.0.2", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-VMq1LNVLIuG4rmumKhzTeCcTDhQf2PLVWWUGe7LOwLstBy8xQ+JdDWntsaK0FbLm8p1pCr707Sx6Iy+GbE6RTg=="], + + "@graphql-codegen/typescript-operations/@graphql-codegen/visitor-plugin-common": ["@graphql-codegen/visitor-plugin-common@7.2.4", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^7.1.0", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.1.1", "@graphql-tools/utils": "^11.2.0", "auto-bind": "^5.0.0", "change-case-all": "^2.1.0", "dependency-graph": "^1.0.0", "graphql-tag": "^2.11.0", "parse-filepath": "^1.0.2", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-VMq1LNVLIuG4rmumKhzTeCcTDhQf2PLVWWUGe7LOwLstBy8xQ+JdDWntsaK0FbLm8p1pCr707Sx6Iy+GbE6RTg=="], + + "@graphql-codegen/visitor-plugin-common/@graphql-codegen/plugin-helpers": ["@graphql-codegen/plugin-helpers@7.0.1", "", { "dependencies": { "@graphql-tools/utils": "^11.0.0", "change-case-all": "^2.1.0", "common-tags": "1.8.2", "import-from": "4.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-S2X0YT3XQbP2haqhIeku8GOXo2j8QuBu7BrLsOEHz4UeMu78y3rja1Q4ri3oJ0jq4dMgaQlazoVHI/A+FAKMGw=="], + + "@graphql-codegen/visitor-plugin-common/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], - "@graphql-codegen/typed-document-node/change-case-all": ["change-case-all@2.1.0", "", { "dependencies": { "change-case": "^5.2.0", "sponge-case": "^2.0.2", "swap-case": "^3.0.2", "title-case": "^3.0.3" } }, "sha512-v6b0WWWkZUMHVuYk82l+WROgkUm4qEN2w5hKRNWtEOYwWqUGoi8C6xH0l1RLF1EoWqDFK6MFclmN3od6ws3/uw=="], + "@graphql-tools/apollo-engine-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], - "@graphql-codegen/typescript-react-apollo/@graphql-codegen/plugin-helpers": ["@graphql-codegen/plugin-helpers@6.3.0", "", { "dependencies": { "@graphql-tools/utils": "^11.0.0", "change-case-all": "1.0.15", "common-tags": "1.8.2", "import-from": "4.0.0", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-Auc+/B7okDx9+pVgLVliZtZLYh6iltWXlnzzM+bRE+zh1T4r3hKbnr8xAmtT937ArfSgk5GHcQHr8LfPYnrRBg=="], + "@graphql-tools/batch-execute/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], - "@graphql-codegen/typescript-react-apollo/@graphql-codegen/visitor-plugin-common": ["@graphql-codegen/visitor-plugin-common@6.3.0", "", { "dependencies": { "@graphql-codegen/plugin-helpers": "^6.3.0", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.1.1", "@graphql-tools/utils": "^11.0.0", "auto-bind": "~4.0.0", "change-case-all": "1.0.15", "dependency-graph": "^1.0.0", "graphql-tag": "^2.11.0", "parse-filepath": "^1.0.2", "tslib": "^2.8.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "sha512-vGBoE+4huzZyNhyGSAhXAkdROHlwKxxuziZm4XtP1mxe7nuI+VgyOmXebafLijbmuDsptPXQN0C/htL54O8hrg=="], + "@graphql-tools/code-file-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], - "@graphql-codegen/typescript-react-apollo/auto-bind": ["auto-bind@4.0.0", "", {}, "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ=="], + "@graphql-tools/delegate/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], - "@graphql-codegen/visitor-plugin-common/change-case-all": ["change-case-all@2.1.0", "", { "dependencies": { "change-case": "^5.2.0", "sponge-case": "^2.0.2", "swap-case": "^3.0.2", "title-case": "^3.0.3" } }, "sha512-v6b0WWWkZUMHVuYk82l+WROgkUm4qEN2w5hKRNWtEOYwWqUGoi8C6xH0l1RLF1EoWqDFK6MFclmN3od6ws3/uw=="], + "@graphql-tools/executor/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/executor-common/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/executor-graphql-ws/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], "@graphql-tools/executor-graphql-ws/ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="], + "@graphql-tools/executor-http/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/executor-legacy-ws/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + "@graphql-tools/executor-legacy-ws/ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="], + "@graphql-tools/git-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/github-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/graphql-file-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/graphql-tag-pluck/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/import/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/json-file-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/load/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/merge/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/relay-operation-optimizer/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/schema/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + + "@graphql-tools/url-loader/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + "@graphql-tools/url-loader/ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="], + "@graphql-tools/wrap/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + "@inquirer/core/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], "@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], @@ -1745,6 +1754,8 @@ "glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + "graphql-config/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], + "graphql-config/cosmiconfig": ["cosmiconfig@8.3.6", "", { "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0", "path-type": "^4.0.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA=="], "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -1863,23 +1874,7 @@ "wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], - "@graphql-codegen/plugin-helpers/change-case-all/change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], - - "@graphql-codegen/plugin-helpers/change-case-all/sponge-case": ["sponge-case@2.0.3", "", {}, "sha512-i4h9ZGRfxV6Xw3mpZSFOfbXjf0cQcYmssGWutgNIfFZ2VM+YIWfD71N/kjjwK6X/AAHzBr+rciEcn/L34S8TGw=="], - - "@graphql-codegen/plugin-helpers/change-case-all/swap-case": ["swap-case@3.0.3", "", {}, "sha512-6p4op8wE9CQv7uDFzulI6YXUw4lD9n4oQierdbFThEKVWVQcbQcUjdP27W8XE7V4QnWmnq9jueSHceyyQnqQVA=="], - - "@graphql-codegen/typed-document-node/change-case-all/change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], - - "@graphql-codegen/typed-document-node/change-case-all/sponge-case": ["sponge-case@2.0.3", "", {}, "sha512-i4h9ZGRfxV6Xw3mpZSFOfbXjf0cQcYmssGWutgNIfFZ2VM+YIWfD71N/kjjwK6X/AAHzBr+rciEcn/L34S8TGw=="], - - "@graphql-codegen/typed-document-node/change-case-all/swap-case": ["swap-case@3.0.3", "", {}, "sha512-6p4op8wE9CQv7uDFzulI6YXUw4lD9n4oQierdbFThEKVWVQcbQcUjdP27W8XE7V4QnWmnq9jueSHceyyQnqQVA=="], - - "@graphql-codegen/visitor-plugin-common/change-case-all/change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], - - "@graphql-codegen/visitor-plugin-common/change-case-all/sponge-case": ["sponge-case@2.0.3", "", {}, "sha512-i4h9ZGRfxV6Xw3mpZSFOfbXjf0cQcYmssGWutgNIfFZ2VM+YIWfD71N/kjjwK6X/AAHzBr+rciEcn/L34S8TGw=="], - - "@graphql-codegen/visitor-plugin-common/change-case-all/swap-case": ["swap-case@3.0.3", "", {}, "sha512-6p4op8wE9CQv7uDFzulI6YXUw4lD9n4oQierdbFThEKVWVQcbQcUjdP27W8XE7V4QnWmnq9jueSHceyyQnqQVA=="], + "@graphql-codegen/introspection/@graphql-codegen/plugin-helpers/@graphql-tools/utils": ["@graphql-tools/utils@11.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "@whatwg-node/promise-helpers": "^1.0.0", "cross-inspect": "1.0.1", "tslib": "^2.4.0" }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-PtFVG4r8Z2LEBSaPYQMusBiB3o6kjLVJyjCLbnWem/SpSuM21v6LTmgpkXfYU1qpBV2UGsFyuEnSJInl8fR1Ag=="], "@istanbuljs/load-nyc-config/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], diff --git a/codegen.ts b/codegen.ts index c429392..4f85055 100644 --- a/codegen.ts +++ b/codegen.ts @@ -12,29 +12,41 @@ if (!schema) { const config: CodegenConfig = { overwrite: true, schema, - documents: ['src/**/*.graphql', 'src/**/*.{ts,tsx}'], + documents: [ + 'src/**/*.graphql', + 'src/**/*.{ts,tsx}', + // Our own output embeds every operation as a `gql` template; without this it + // would be read back in as a duplicate of each source document. + '!src/graphql/__generated__/**', + ], generates: { 'src/graphql/__generated__/types.ts': { - plugins: [ - 'typescript', - 'typescript-operations', - 'typescript-react-apollo', - ], + // Operation types plus a TypedDocumentNode per operation. Apollo Client + // v4's own hooks infer result and variable types straight off those + // documents — `useQuery(ElementDetailDocument, ...)` — so there are no + // generated hooks and nothing to hand-patch after a regen. + // + // Deliberately NOT using typescript-react-apollo (its generated hooks are + // Apollo v3-shaped and it peers at graphql <=16) or the `typescript` + // plugin (typescript-operations already emits the schema types our + // operations use; running both emits each one twice). + plugins: ['typescript-operations', 'typed-document-node'], config: { - withHooks: true, - // NOTE: @graphql-codegen/typescript-react-apollo has no Apollo Client - // v4 support (latest is 4.x, still v3-oriented). After regenerating, - // the output needs manual fixups to compile against @apollo/client v4: - // - `import * as Apollo from '@apollo/client'` -> '@apollo/client/react' - // - `Apollo.MutationFunction` -> `Apollo.useMutation.MutationFunction` - // - `Apollo.BaseMutationOptions` -> `Apollo.MutationHookOptions` - // - the generated *SuspenseQuery hooks need a "ts-ignore" directive (unused here) - // Longer term, migrate to @graphql-codegen/client-preset. - reactApolloVersion: 3, + // Keep documents as readable SDL template literals rather than inlining + // a parsed AST, so the generated file stays diffable. + documentMode: 'graphQLTag', + documentNodeImport: '@apollo/client#TypedDocumentNode', + gqlImport: '@apollo/client#gql', + // Note: these types carry no `__typename` (the plugin only emits it for + // selections that ask for it). Apollo still adds it on the wire and + // keys its cache off it — that's runtime behaviour, unaffected here. scalars: { // Map GraphQL scalars to TS types as you add them in the schema. - // ID: 'string', - // DateTime: 'string', + // All three arrive over the wire as ISO8601 strings; without this the + // plugin types them `unknown`, which no call site can use. + Date: 'string', + Time: 'string', + DateTime: 'string', }, }, }, diff --git a/package.json b/package.json index 7fdf98d..33a1c52 100644 --- a/package.json +++ b/package.json @@ -34,11 +34,10 @@ "@babel/preset-env": "^7.25.3", "@babel/runtime": "^7.25.0", "@biomejs/biome": "^2.4.15", - "@graphql-codegen/cli": "^7.0.0", + "@graphql-codegen/cli": "^7.2.0", "@graphql-codegen/introspection": "^6.0.0", - "@graphql-codegen/typescript": "^6.0.0", - "@graphql-codegen/typescript-operations": "^6.0.0", - "@graphql-codegen/typescript-react-apollo": "^4.0.0", + "@graphql-codegen/typed-document-node": "^7.1.0", + "@graphql-codegen/typescript-operations": "^6.1.5", "@react-native-community/cli": "20.2.0", "@react-native-community/cli-platform-android": "20.2.0", "@react-native/babel-preset": "0.86.0", diff --git a/src/auth/LoginScreen.tsx b/src/auth/LoginScreen.tsx index 9e0896e..5286711 100644 --- a/src/auth/LoginScreen.tsx +++ b/src/auth/LoginScreen.tsx @@ -1,3 +1,4 @@ +import {useMutation} from '@apollo/client/react'; import {useMemo, useState} from 'react'; import { ActivityIndicator, @@ -9,7 +10,7 @@ import { TextInput, View, } from 'react-native'; -import {useLoginMutation} from '../graphql/__generated__/types'; +import {LoginDocument} from '../graphql/__generated__/types'; import type {Theme} from '../theme/colors'; import {useTheme} from '../theme/useTheme'; import {clearSecurityWarning, useSecurityWarning} from './authClient'; @@ -50,7 +51,7 @@ export function LoginScreen() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [errorMessage, setErrorMessage] = useState(null); - const [login, {loading}] = useLoginMutation(); + const [login, {loading}] = useMutation(LoginDocument); const securityWarning = useSecurityWarning(); const canSubmit = email.length > 0 && password.length > 0 && !loading; diff --git a/src/auth/authClient.ts b/src/auth/authClient.ts index 44c1c9a..14b58b6 100644 --- a/src/auth/authClient.ts +++ b/src/auth/authClient.ts @@ -16,7 +16,6 @@ import {config} from '../config'; import { type LoginMutation, LogoutDocument, - type LogoutMutation, RenewTokenDocument, type RenewTokenMutation, } from '../graphql/__generated__/types'; @@ -74,7 +73,7 @@ async function doRefresh(): Promise { if (!current) return null; try { - const result = await apolloClient.mutate({ + const result = await apolloClient.mutate({ mutation: RenewTokenDocument, variables: {input: {refreshToken: current.refreshToken}}, // Don't read or write the cache for this housekeeping mutation. @@ -211,7 +210,7 @@ export async function logout(): Promise { const current = tokenStore.get(); if (current) { try { - await apolloClient.mutate({ + await apolloClient.mutate({ mutation: LogoutDocument, variables: {input: {refreshToken: current.refreshToken}}, fetchPolicy: 'no-cache', diff --git a/src/graphql/__generated__/types.ts b/src/graphql/__generated__/types.ts index f16d2f5..4f1d884 100644 --- a/src/graphql/__generated__/types.ts +++ b/src/graphql/__generated__/types.ts @@ -1,215 +1,54 @@ -import { gql } from '@apollo/client'; -import * as Apollo from '@apollo/client/react'; -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; +/** Internal type. DO NOT USE DIRECTLY. */ +type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -const defaultOptions = {} as const; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - /** - * The `Date` scalar type represents a date. The Date appears in a JSON - * response as an ISO8601 formatted string, without a time component. - */ - Date: { input: any; output: any; } - /** - * The `DateTime` scalar type represents a date and time in the UTC - * timezone. The DateTime appears in a JSON response as an ISO8601 formatted - * string, including UTC timezone ("Z"). The parsed date and time string will - * be converted to UTC if there is an offset. - */ - DateTime: { input: any; output: any; } - /** - * The `Time` scalar type represents a time. The Time appears in a JSON - * response as an ISO8601 formatted string, without a date component. - */ - Time: { input: any; output: any; } -}; - -export type CreateElementInput = { - completed: Scalars['Boolean']['input']; - description: Scalars['String']['input']; - icon: Scalars['String']['input']; - labels?: InputMaybe>; - location?: InputMaybe; - name: Scalars['String']['input']; - /** Ordered list of photo ids (from createPhoto) to attach to the element. */ - photoIds?: InputMaybe>; - schedule?: InputMaybe; - tripIds?: InputMaybe>; - uri: Scalars['String']['input']; -}; - -export type CreatePermissionInput = { - isPublic: Scalars['Boolean']['input']; - permit: Array; - tripId: Scalars['String']['input']; -}; - -export type CreateTripInput = { - /** Id of a photo (from createPhoto) to use as the banner. If omitted, a default is chosen from the name. */ - bannerPhotoId?: InputMaybe; - description?: InputMaybe; - name: Scalars['String']['input']; - timeZone?: InputMaybe; -}; - -export type Element = { - __typename?: 'Element'; - completed: Scalars['Boolean']['output']; - description: Scalars['String']['output']; - icon: Scalars['String']['output']; - id: Scalars['String']['output']; - labels: Array; - location?: Maybe; - name: Scalars['String']['output']; - photos: Array; - schedule?: Maybe; - trips: Array; - uri: Scalars['String']['output']; -}; - +import { TypedDocumentNode as DocumentNode } from '@apollo/client'; +import { gql } from '@apollo/client'; export type ElementInput = { - completed: Scalars['Boolean']['input']; - description: Scalars['String']['input']; - icon: Scalars['String']['input']; - id: Scalars['String']['input']; - labels?: InputMaybe>; - location?: InputMaybe; - name: Scalars['String']['input']; - /** - * The element's photos, as an ordered list of photo ids (from createPhoto). This - * is the complete desired set: reordering, removing, or adding ids - * reorders/removes/adds photos. Omit to leave photos unchanged. - */ - photoIds?: InputMaybe>; - schedule?: InputMaybe; - tripIds?: InputMaybe>; - uri: Scalars['String']['input']; -}; - -export type FileUploadUrl = { - __typename?: 'FileUploadUrl'; - key: Scalars['String']['output']; - url: Scalars['String']['output']; + completed: boolean; + description: string; + icon: string; + id: string; + labels?: Array | null | undefined; + location?: LocationInput | null | undefined; + name: string; + /** The element's photos, as an ordered list of photo ids (from createPhoto). This is the complete desired set: reordering, removing, or adding ids reorders/removes/adds photos. Omit to leave photos unchanged. */ + photoIds?: Array | null | undefined; + schedule?: ScheduleInput | null | undefined; + tripIds?: Array | null | undefined; + uri: string; }; export type GeoBounds = { - bottom: Scalars['Float']['input']; - left: Scalars['Float']['input']; - right: Scalars['Float']['input']; - top: Scalars['Float']['input']; -}; - -export type GeoPoint = { - latitude: Scalars['Float']['input']; - longitude: Scalars['Float']['input']; -}; - -export type GooglePlace = { - __typename?: 'GooglePlace'; - address: Scalars['String']['output']; - description?: Maybe; - latitude: Scalars['Float']['output']; - longitude: Scalars['Float']['output']; - name: Scalars['String']['output']; - placeId: Scalars['String']['output']; - rating?: Maybe; - types?: Maybe>; - url?: Maybe; - website?: Maybe; + bottom: number; + left: number; + right: number; + top: number; }; /** How a list of labels is matched against an element's labels */ -export enum LabelMatchMode { +export type LabelMatchMode = /** Element has every one of the given labels */ - All = 'ALL', + | 'ALL' /** Element has at least one of the given labels */ - Any = 'ANY' -} - -export type Location = { - __typename?: 'Location'; - address: Scalars['String']['output']; - id: Scalars['String']['output']; - latitude: Scalars['Float']['output']; - longitude: Scalars['Float']['output']; - placeId?: Maybe; -}; + | 'ANY'; export type LocationInput = { - address: Scalars['String']['input']; - latitude: Scalars['Float']['input']; - longitude: Scalars['Float']['input']; - placeId?: InputMaybe; + address: string; + latitude: number; + longitude: number; + placeId?: string | null | undefined; }; export type LoginInput = { /** Optional human-readable label for this session (e.g. "iPhone 15"). Displayed in the session list. */ - deviceLabel?: InputMaybe; - email: Scalars['String']['input']; - password: Scalars['String']['input']; -}; - -export type LoginToken = { - __typename?: 'LoginToken'; - accessToken: Scalars['String']['output']; - /** Absolute expiration time of the access token. */ - expiresAt: Scalars['DateTime']['output']; - refreshToken: Scalars['String']['output']; - user: User; + deviceLabel?: string | null | undefined; + email: string; + password: string; }; export type LogoutInput = { - refreshToken: Scalars['String']['input']; -}; - -export type LogoutSuccess = { - __typename?: 'LogoutSuccess'; - success: Scalars['Boolean']['output']; -}; - -export type Permission = { - __typename?: 'Permission'; - id: Scalars['String']['output']; - isPublic: Scalars['Boolean']['output']; - permit: Array; - trip: Trip; -}; - -export type PermissionInput = { - id: Scalars['String']['input']; - isPublic: Scalars['Boolean']['input']; - permit: Array; -}; - -export enum PermitType { - Read = 'READ', - Write = 'WRITE' -} - -export type Photo = { - __typename?: 'Photo'; - attributionUrl?: Maybe; - creditName?: Maybe; - creditUrl?: Maybe; - description: Scalars['String']['output']; - full: Scalars['String']['output']; - id: Scalars['String']['output']; - license?: Maybe; - regular: Scalars['String']['output']; - small: Scalars['String']['output']; - storageKey?: Maybe; - thumbnail: Scalars['String']['output']; - type?: Maybe; + refreshToken: string; }; /** @@ -224,370 +63,38 @@ export type Photo = { * (defaults to "" when omitted) but required for `unsplash`/`wikimedia`. */ export type PhotoInput = { - attributionUrl?: InputMaybe; - creditName?: InputMaybe; - creditUrl?: InputMaybe; + attributionUrl?: string | null | undefined; + creditName?: string | null | undefined; + creditUrl?: string | null | undefined; /** Image alt text. Optional for s3 (defaults to ""); required for unsplash/wikimedia. */ - description?: InputMaybe; - full?: InputMaybe; - license?: InputMaybe; - regular?: InputMaybe; - small?: InputMaybe; + description?: string | null | undefined; + full?: string | null | undefined; + license?: string | null | undefined; + regular?: string | null | undefined; + small?: string | null | undefined; /** Upload key from create_upload_url; required for s3 photos */ - storageKey?: InputMaybe; - thumbnail?: InputMaybe; + storageKey?: string | null | undefined; + thumbnail?: string | null | undefined; type: PhotoType; }; -export type PhotoResult = { - __typename?: 'PhotoResult'; - attributionUrl: Scalars['String']['output']; - urls: PhotoUrls; - user: PhotoUser; -}; - -export enum PhotoType { - S3 = 'S3', - Unsplash = 'UNSPLASH', - Wikimedia = 'WIKIMEDIA' -} - -export type PhotoUrls = { - __typename?: 'PhotoUrls'; - full: Scalars['String']['output']; - raw: Scalars['String']['output']; - regular: Scalars['String']['output']; - small: Scalars['String']['output']; - thumb: Scalars['String']['output']; -}; - -export type PhotoUser = { - __typename?: 'PhotoUser'; - name: Scalars['String']['output']; - portfolioUrl?: Maybe; -}; - -/** Restricts place search results to a category of place */ -export enum PlaceGranularity { - /** Precise street addresses only */ - Address = 'ADDRESS', - /** Cities only (locality / administrative_area_level_3) */ - Cities = 'CITIES', - /** Businesses and points of interest only */ - Establishment = 'ESTABLISHMENT', - /** Countries, states, regions, and cities */ - Regions = 'REGIONS' -} - -export type RegisterInput = { - email: Scalars['String']['input']; - password: Scalars['String']['input']; -}; - -export type RegisterSuccess = { - __typename?: 'RegisterSuccess'; - success: Scalars['Boolean']['output']; -}; +export type PhotoType = + | 'S3' + | 'UNSPLASH' + | 'WIKIMEDIA'; export type RenewTokenInput = { - refreshToken: Scalars['String']['input']; -}; - -export type ResetPasswordInput = { - confirmPassword: Scalars['String']['input']; - password: Scalars['String']['input']; - token: Scalars['String']['input']; -}; - -export type RevokeAllOtherSessionsPayload = { - __typename?: 'RevokeAllOtherSessionsPayload'; - revokedCount: Scalars['Int']['output']; -}; - -export type RevokeSessionInput = { - id: Scalars['String']['input']; -}; - -export type RevokeSessionPayload = { - __typename?: 'RevokeSessionPayload'; - /** True if the revoked session was the one used to make this request. Client should discard its tokens. */ - currentSessionRevoked: Scalars['Boolean']['output']; - revokedCount: Scalars['Int']['output']; -}; - -export type RootMutationType = { - __typename?: 'RootMutationType'; - confirmAccount: Scalars['String']['output']; - createElement: Element; - createPermission: Permission; - createPhoto: Photo; - createTrip: Trip; - deleteElement: Element; - deletePermission: Permission; - deleteTrip: Trip; - forgotPassword: Scalars['String']['output']; - importElement: Element; - importElementAsync: Scalars['Boolean']['output']; - importShare: Element; - login: LoginToken; - logout: LogoutSuccess; - register: RegisterSuccess; - renewToken: LoginToken; - resendConfirmation: Scalars['String']['output']; - resetPassword: Scalars['String']['output']; - revokeAllOtherSessions: RevokeAllOtherSessionsPayload; - revokeSession: RevokeSessionPayload; - updateElement: Element; - updatePermission: Permission; - updateTrip: Trip; -}; - - -export type RootMutationTypeConfirmAccountArgs = { - key: Scalars['String']['input']; -}; - - -export type RootMutationTypeCreateElementArgs = { - input: CreateElementInput; -}; - - -export type RootMutationTypeCreatePermissionArgs = { - input: CreatePermissionInput; -}; - - -export type RootMutationTypeCreatePhotoArgs = { - input: PhotoInput; -}; - - -export type RootMutationTypeCreateTripArgs = { - input: CreateTripInput; -}; - - -export type RootMutationTypeDeleteElementArgs = { - id: Scalars['String']['input']; -}; - - -export type RootMutationTypeDeletePermissionArgs = { - id: Scalars['String']['input']; -}; - - -export type RootMutationTypeDeleteTripArgs = { - id: Scalars['String']['input']; -}; - - -export type RootMutationTypeForgotPasswordArgs = { - email: Scalars['String']['input']; -}; - - -export type RootMutationTypeImportElementArgs = { - url: Scalars['String']['input']; -}; - - -export type RootMutationTypeImportElementAsyncArgs = { - url: Scalars['String']['input']; -}; - - -export type RootMutationTypeImportShareArgs = { - content: Scalars['String']['input']; -}; - - -export type RootMutationTypeLoginArgs = { - input: LoginInput; -}; - - -export type RootMutationTypeLogoutArgs = { - input: LogoutInput; -}; - - -export type RootMutationTypeRegisterArgs = { - input: RegisterInput; -}; - - -export type RootMutationTypeRenewTokenArgs = { - input: RenewTokenInput; -}; - - -export type RootMutationTypeResendConfirmationArgs = { - email: Scalars['String']['input']; -}; - - -export type RootMutationTypeResetPasswordArgs = { - input: ResetPasswordInput; -}; - - -export type RootMutationTypeRevokeSessionArgs = { - input: RevokeSessionInput; -}; - - -export type RootMutationTypeUpdateElementArgs = { - input: ElementInput; -}; - - -export type RootMutationTypeUpdatePermissionArgs = { - input: PermissionInput; -}; - - -export type RootMutationTypeUpdateTripArgs = { - input: TripInput; -}; - -export type RootQueryType = { - __typename?: 'RootQueryType'; - createUploadUrl: FileUploadUrl; - element: Element; - elements: Array; - myUser: User; - permission: Permission; - photoSearch: Array; - placeSearch: Array; - sessions: Array; - trip: Trip; - trips: Array; -}; - - -export type RootQueryTypeCreateUploadUrlArgs = { - bustCache?: InputMaybe; -}; - - -export type RootQueryTypeElementArgs = { - id: Scalars['String']['input']; -}; - - -export type RootQueryTypeElementsArgs = { - afterDate?: InputMaybe; - bounds?: InputMaybe; - completed?: InputMaybe; - deleted?: InputMaybe; - excludeTripId?: InputMaybe; - hasSchedule?: InputMaybe; - labels?: InputMaybe>; - labelsMatch?: InputMaybe; - search?: InputMaybe; - sortLocation?: InputMaybe; - tripId?: InputMaybe; -}; - - -export type RootQueryTypePermissionArgs = { - id: Scalars['String']['input']; -}; - - -export type RootQueryTypePhotoSearchArgs = { - query: Scalars['String']['input']; -}; - - -export type RootQueryTypePlaceSearchArgs = { - granularity?: InputMaybe; - query: Scalars['String']['input']; -}; - - -export type RootQueryTypeTripArgs = { - id: Scalars['String']['input']; -}; - - -export type RootQueryTypeTripsArgs = { - deleted?: InputMaybe; - search?: InputMaybe; -}; - -export type Schedule = { - __typename?: 'Schedule'; - allDay: Scalars['Boolean']['output']; - endDate: Scalars['Date']['output']; - endTime?: Maybe; - endTz: Scalars['String']['output']; - id: Scalars['String']['output']; - startDate: Scalars['Date']['output']; - startTime?: Maybe; - startTz: Scalars['String']['output']; + refreshToken: string; }; export type ScheduleInput = { - allDay: Scalars['Boolean']['input']; - endDate: Scalars['Date']['input']; - endTime?: InputMaybe; - endTz: Scalars['String']['input']; - startDate: Scalars['Date']['input']; - startTime?: InputMaybe; - startTz: Scalars['String']['input']; -}; - -export type Session = { - __typename?: 'Session'; - /** When this session was started. */ - createdAt: Scalars['DateTime']['output']; - /** True if this session is the one used to make the current request. */ - current: Scalars['Boolean']['output']; - deviceLabel?: Maybe; - id: Scalars['String']['output']; - /** When the access token for this session was last refreshed. */ - lastActiveAt: Scalars['DateTime']['output']; -}; - -export type Trip = { - __typename?: 'Trip'; - /** Banner photo displayed predominantly for a trip */ - bannerPhoto?: Maybe; - description: Scalars['String']['output']; - elements: Array; - icon: Scalars['String']['output']; - id: Scalars['String']['output']; - integrations: TripIntegrations; - name: Scalars['String']['output']; - permissions: Array; - timeZone: Scalars['String']['output']; -}; - -export type TripInput = { - /** Id of a photo to set as the banner. Omit to leave unchanged. */ - bannerPhotoId?: InputMaybe; - description?: InputMaybe; - icon?: InputMaybe; - id: Scalars['String']['input']; - name?: InputMaybe; - timeZone?: InputMaybe; -}; - -export type TripIntegrations = { - __typename?: 'TripIntegrations'; - calendarUri: Scalars['String']['output']; - email: Scalars['String']['output']; - publicUri?: Maybe; -}; - -export type User = { - __typename?: 'User'; - email: Scalars['String']['output']; - id: Scalars['String']['output']; - locale?: Maybe; + allDay: boolean; + endDate: string; + endTime?: string | null | undefined; + endTz: string; + startDate: string; + startTime?: string | null | undefined; + startTz: string; }; export type CreatePhotoMutationVariables = Exact<{ @@ -595,85 +102,85 @@ export type CreatePhotoMutationVariables = Exact<{ }>; -export type CreatePhotoMutation = { __typename?: 'RootMutationType', createPhoto: { __typename?: 'Photo', id: string, thumbnail: string, regular: string, description: string } }; +export type CreatePhotoMutation = { createPhoto: { id: string, thumbnail: string, regular: string, description: string } }; export type CreateUploadUrlQueryVariables = Exact<{ - bustCache?: InputMaybe; + bustCache?: number | null | undefined; }>; -export type CreateUploadUrlQuery = { __typename?: 'RootQueryType', createUploadUrl: { __typename?: 'FileUploadUrl', url: string, key: string } }; +export type CreateUploadUrlQuery = { createUploadUrl: { url: string, key: string } }; export type DeleteElementMutationVariables = Exact<{ - id: Scalars['String']['input']; + id: string; }>; -export type DeleteElementMutation = { __typename?: 'RootMutationType', deleteElement: { __typename?: 'Element', id: string } }; +export type DeleteElementMutation = { deleteElement: { id: string } }; export type ElementDetailQueryVariables = Exact<{ - id: Scalars['String']['input']; + id: string; }>; -export type ElementDetailQuery = { __typename?: 'RootQueryType', element: { __typename?: 'Element', id: string, name: string, icon: string, description: string, completed: boolean, uri: string, labels: Array, trips: Array<{ __typename?: 'Trip', id: string }>, location?: { __typename?: 'Location', id: string, address: string, latitude: number, longitude: number, placeId?: string | null } | null, photos: Array<{ __typename?: 'Photo', id: string, thumbnail: string, regular: string, description: string }>, schedule?: { __typename?: 'Schedule', id: string, allDay: boolean, startDate: any, endDate: any, startTime?: any | null, endTime?: any | null, startTz: string, endTz: string } | null } }; +export type ElementDetailQuery = { element: { id: string, name: string, icon: string, description: string, completed: boolean, uri: string, labels: Array, trips: Array<{ id: string }>, location: { id: string, address: string, latitude: number, longitude: number, placeId: string | null } | null, photos: Array<{ id: string, thumbnail: string, regular: string, description: string }>, schedule: { id: string, allDay: boolean, startDate: string, endDate: string, startTime: string | null, endTime: string | null, startTz: string, endTz: string } | null, metadata: { type: string | null, number: string | null, reservation: string | null, seat: string | null, paymentDetails: string | null, address: string | null, departureLocation: string | null, arrivalLocation: string | null } | null } }; export type ElementsQueryVariables = Exact<{ - bounds?: InputMaybe; - tripId?: InputMaybe; - labels?: InputMaybe | Scalars['String']['input']>; - labelsMatch?: InputMaybe; + bounds?: GeoBounds | null | undefined; + tripId?: string | null | undefined; + labels?: Array | string | null | undefined; + labelsMatch?: LabelMatchMode | null | undefined; }>; -export type ElementsQuery = { __typename?: 'RootQueryType', elements: Array<{ __typename?: 'Element', id: string, name: string, icon: string, labels: Array, location?: { __typename?: 'Location', id: string, latitude: number, longitude: number } | null }> }; +export type ElementsQuery = { elements: Array<{ id: string, name: string, icon: string, labels: Array, location: { id: string, latitude: number, longitude: number } | null }> }; export type ImportShareMutationVariables = Exact<{ - content: Scalars['String']['input']; + content: string; }>; -export type ImportShareMutation = { __typename?: 'RootMutationType', importShare: { __typename?: 'Element', id: string, name: string, icon: string, description: string, completed: boolean, uri: string, labels: Array, trips: Array<{ __typename?: 'Trip', id: string }>, location?: { __typename?: 'Location', id: string, address: string, latitude: number, longitude: number, placeId?: string | null } | null, photos: Array<{ __typename?: 'Photo', id: string, thumbnail: string, regular: string, description: string }>, schedule?: { __typename?: 'Schedule', id: string, allDay: boolean, startDate: any, endDate: any, startTime?: any | null, endTime?: any | null, startTz: string, endTz: string } | null } }; +export type ImportShareMutation = { importShare: { id: string, name: string, icon: string, description: string, completed: boolean, uri: string, labels: Array, trips: Array<{ id: string }>, location: { id: string, address: string, latitude: number, longitude: number, placeId: string | null } | null, photos: Array<{ id: string, thumbnail: string, regular: string, description: string }>, schedule: { id: string, allDay: boolean, startDate: string, endDate: string, startTime: string | null, endTime: string | null, startTz: string, endTz: string } | null, metadata: { type: string | null, number: string | null, reservation: string | null, seat: string | null, paymentDetails: string | null, address: string | null, departureLocation: string | null, arrivalLocation: string | null } | null } }; export type LoginMutationVariables = Exact<{ input: LoginInput; }>; -export type LoginMutation = { __typename?: 'RootMutationType', login: { __typename?: 'LoginToken', accessToken: string, refreshToken: string, expiresAt: any, user: { __typename?: 'User', id: string, email: string, locale?: string | null } } }; +export type LoginMutation = { login: { accessToken: string, refreshToken: string, expiresAt: string, user: { id: string, email: string, locale: string | null } } }; export type LogoutMutationVariables = Exact<{ input: LogoutInput; }>; -export type LogoutMutation = { __typename?: 'RootMutationType', logout: { __typename?: 'LogoutSuccess', success: boolean } }; +export type LogoutMutation = { logout: { success: boolean } }; export type RenewTokenMutationVariables = Exact<{ input: RenewTokenInput; }>; -export type RenewTokenMutation = { __typename?: 'RootMutationType', renewToken: { __typename?: 'LoginToken', accessToken: string, refreshToken: string, expiresAt: any, user: { __typename?: 'User', id: string, email: string, locale?: string | null } } }; +export type RenewTokenMutation = { renewToken: { accessToken: string, refreshToken: string, expiresAt: string, user: { id: string, email: string, locale: string | null } } }; export type SearchQueryVariables = Exact<{ - query: Scalars['String']['input']; + query: string; }>; -export type SearchQuery = { __typename?: 'RootQueryType', elements: Array<{ __typename?: 'Element', id: string, name: string, icon: string, labels: Array, location?: { __typename?: 'Location', id: string, address: string, latitude: number, longitude: number } | null }>, trips: Array<{ __typename?: 'Trip', id: string, name: string, icon: string, description: string }>, placeSearch: Array<{ __typename?: 'GooglePlace', placeId: string, name: string, address: string, latitude: number, longitude: number, types?: Array | null }> }; +export type SearchQuery = { elements: Array<{ id: string, name: string, icon: string, labels: Array, location: { id: string, address: string, latitude: number, longitude: number } | null }>, trips: Array<{ id: string, name: string, icon: string, description: string }>, placeSearch: Array<{ placeId: string, name: string, address: string, latitude: number, longitude: number, types: Array | null }> }; export type TripsQueryVariables = Exact<{ [key: string]: never; }>; -export type TripsQuery = { __typename?: 'RootQueryType', trips: Array<{ __typename?: 'Trip', id: string, name: string, icon: string }> }; +export type TripsQuery = { trips: Array<{ id: string, name: string, icon: string }> }; export type UpdateElementMutationVariables = Exact<{ input: ElementInput; }>; -export type UpdateElementMutation = { __typename?: 'RootMutationType', updateElement: { __typename?: 'Element', id: string, name: string, icon: string, description: string, completed: boolean, uri: string, labels: Array, trips: Array<{ __typename?: 'Trip', id: string }>, location?: { __typename?: 'Location', id: string, address: string, latitude: number, longitude: number, placeId?: string | null } | null, photos: Array<{ __typename?: 'Photo', id: string, thumbnail: string, regular: string, description: string }>, schedule?: { __typename?: 'Schedule', id: string, allDay: boolean, startDate: any, endDate: any, startTime?: any | null, endTime?: any | null, startTz: string, endTz: string } | null } }; +export type UpdateElementMutation = { updateElement: { id: string, name: string, icon: string, description: string, completed: boolean, uri: string, labels: Array, trips: Array<{ id: string }>, location: { id: string, address: string, latitude: number, longitude: number, placeId: string | null } | null, photos: Array<{ id: string, thumbnail: string, regular: string, description: string }>, schedule: { id: string, allDay: boolean, startDate: string, endDate: string, startTime: string | null, endTime: string | null, startTz: string, endTz: string } | null, metadata: { type: string | null, number: string | null, reservation: string | null, seat: string | null, paymentDetails: string | null, address: string | null, departureLocation: string | null, arrivalLocation: string | null } | null } }; export const CreatePhotoDocument = gql` @@ -685,33 +192,7 @@ export const CreatePhotoDocument = gql` description } } - `; -export type CreatePhotoMutationFn = Apollo.useMutation.MutationFunction; - -/** - * __useCreatePhotoMutation__ - * - * To run a mutation, you first call `useCreatePhotoMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useCreatePhotoMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [createPhotoMutation, { data, loading, error }] = useCreatePhotoMutation({ - * variables: { - * input: // value for 'input' - * }, - * }); - */ -export function useCreatePhotoMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreatePhotoDocument, options); - } -export type CreatePhotoMutationHookResult = ReturnType; -export type CreatePhotoMutationResult = Apollo.MutationResult; -export type CreatePhotoMutationOptions = Apollo.MutationHookOptions; + ` as unknown as DocumentNode; export const CreateUploadUrlDocument = gql` query CreateUploadUrl($bustCache: Int) { createUploadUrl(bustCache: $bustCache) { @@ -719,78 +200,14 @@ export const CreateUploadUrlDocument = gql` key } } - `; - -/** - * __useCreateUploadUrlQuery__ - * - * To run a query within a React component, call `useCreateUploadUrlQuery` and pass it any options that fit your needs. - * When your component renders, `useCreateUploadUrlQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useCreateUploadUrlQuery({ - * variables: { - * bustCache: // value for 'bustCache' - * }, - * }); - */ -export function useCreateUploadUrlQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(CreateUploadUrlDocument, options); - } -export function useCreateUploadUrlLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(CreateUploadUrlDocument, options); - } -// @ts-ignore -export function useCreateUploadUrlSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -// @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. -export function useCreateUploadUrlSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -export function useCreateUploadUrlSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - // @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. - return Apollo.useSuspenseQuery(CreateUploadUrlDocument, options); - } -export type CreateUploadUrlQueryHookResult = ReturnType; -export type CreateUploadUrlLazyQueryHookResult = ReturnType; -export type CreateUploadUrlSuspenseQueryHookResult = ReturnType; -export type CreateUploadUrlQueryResult = Apollo.QueryResult; + ` as unknown as DocumentNode; export const DeleteElementDocument = gql` mutation DeleteElement($id: String!) { deleteElement(id: $id) { id } } - `; -export type DeleteElementMutationFn = Apollo.useMutation.MutationFunction; - -/** - * __useDeleteElementMutation__ - * - * To run a mutation, you first call `useDeleteElementMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useDeleteElementMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [deleteElementMutation, { data, loading, error }] = useDeleteElementMutation({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useDeleteElementMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteElementDocument, options); - } -export type DeleteElementMutationHookResult = ReturnType; -export type DeleteElementMutationResult = Apollo.MutationResult; -export type DeleteElementMutationOptions = Apollo.MutationHookOptions; + ` as unknown as DocumentNode; export const ElementDetailDocument = gql` query ElementDetail($id: String!) { element(id: $id) { @@ -827,47 +244,19 @@ export const ElementDetailDocument = gql` startTz endTz } + metadata { + type + number + reservation + seat + paymentDetails + address + departureLocation + arrivalLocation + } } } - `; - -/** - * __useElementDetailQuery__ - * - * To run a query within a React component, call `useElementDetailQuery` and pass it any options that fit your needs. - * When your component renders, `useElementDetailQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useElementDetailQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useElementDetailQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: ElementDetailQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(ElementDetailDocument, options); - } -export function useElementDetailLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(ElementDetailDocument, options); - } -// @ts-ignore -export function useElementDetailSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -// @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. -export function useElementDetailSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -export function useElementDetailSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - // @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. - return Apollo.useSuspenseQuery(ElementDetailDocument, options); - } -export type ElementDetailQueryHookResult = ReturnType; -export type ElementDetailLazyQueryHookResult = ReturnType; -export type ElementDetailSuspenseQueryHookResult = ReturnType; -export type ElementDetailQueryResult = Apollo.QueryResult; + ` as unknown as DocumentNode; export const ElementsDocument = gql` query Elements($bounds: GeoBounds, $tripId: String, $labels: [String!], $labelsMatch: LabelMatchMode) { elements( @@ -887,48 +276,7 @@ export const ElementsDocument = gql` } } } - `; - -/** - * __useElementsQuery__ - * - * To run a query within a React component, call `useElementsQuery` and pass it any options that fit your needs. - * When your component renders, `useElementsQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useElementsQuery({ - * variables: { - * bounds: // value for 'bounds' - * tripId: // value for 'tripId' - * labels: // value for 'labels' - * labelsMatch: // value for 'labelsMatch' - * }, - * }); - */ -export function useElementsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(ElementsDocument, options); - } -export function useElementsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(ElementsDocument, options); - } -// @ts-ignore -export function useElementsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -// @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. -export function useElementsSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -export function useElementsSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - // @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. - return Apollo.useSuspenseQuery(ElementsDocument, options); - } -export type ElementsQueryHookResult = ReturnType; -export type ElementsLazyQueryHookResult = ReturnType; -export type ElementsSuspenseQueryHookResult = ReturnType; -export type ElementsQueryResult = Apollo.QueryResult; + ` as unknown as DocumentNode; export const ImportShareDocument = gql` mutation ImportShare($content: String!) { importShare(content: $content) { @@ -965,35 +313,19 @@ export const ImportShareDocument = gql` startTz endTz } + metadata { + type + number + reservation + seat + paymentDetails + address + departureLocation + arrivalLocation + } } } - `; -export type ImportShareMutationFn = Apollo.useMutation.MutationFunction; - -/** - * __useImportShareMutation__ - * - * To run a mutation, you first call `useImportShareMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useImportShareMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [importShareMutation, { data, loading, error }] = useImportShareMutation({ - * variables: { - * content: // value for 'content' - * }, - * }); - */ -export function useImportShareMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(ImportShareDocument, options); - } -export type ImportShareMutationHookResult = ReturnType; -export type ImportShareMutationResult = Apollo.MutationResult; -export type ImportShareMutationOptions = Apollo.MutationHookOptions; + ` as unknown as DocumentNode; export const LoginDocument = gql` mutation Login($input: LoginInput!) { login(input: $input) { @@ -1007,66 +339,14 @@ export const LoginDocument = gql` } } } - `; -export type LoginMutationFn = Apollo.useMutation.MutationFunction; - -/** - * __useLoginMutation__ - * - * To run a mutation, you first call `useLoginMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useLoginMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [loginMutation, { data, loading, error }] = useLoginMutation({ - * variables: { - * input: // value for 'input' - * }, - * }); - */ -export function useLoginMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(LoginDocument, options); - } -export type LoginMutationHookResult = ReturnType; -export type LoginMutationResult = Apollo.MutationResult; -export type LoginMutationOptions = Apollo.MutationHookOptions; + ` as unknown as DocumentNode; export const LogoutDocument = gql` mutation Logout($input: LogoutInput!) { logout(input: $input) { success } } - `; -export type LogoutMutationFn = Apollo.useMutation.MutationFunction; - -/** - * __useLogoutMutation__ - * - * To run a mutation, you first call `useLogoutMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useLogoutMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [logoutMutation, { data, loading, error }] = useLogoutMutation({ - * variables: { - * input: // value for 'input' - * }, - * }); - */ -export function useLogoutMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(LogoutDocument, options); - } -export type LogoutMutationHookResult = ReturnType; -export type LogoutMutationResult = Apollo.MutationResult; -export type LogoutMutationOptions = Apollo.MutationHookOptions; + ` as unknown as DocumentNode; export const RenewTokenDocument = gql` mutation RenewToken($input: RenewTokenInput!) { renewToken(input: $input) { @@ -1080,33 +360,7 @@ export const RenewTokenDocument = gql` } } } - `; -export type RenewTokenMutationFn = Apollo.useMutation.MutationFunction; - -/** - * __useRenewTokenMutation__ - * - * To run a mutation, you first call `useRenewTokenMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useRenewTokenMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [renewTokenMutation, { data, loading, error }] = useRenewTokenMutation({ - * variables: { - * input: // value for 'input' - * }, - * }); - */ -export function useRenewTokenMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(RenewTokenDocument, options); - } -export type RenewTokenMutationHookResult = ReturnType; -export type RenewTokenMutationResult = Apollo.MutationResult; -export type RenewTokenMutationOptions = Apollo.MutationHookOptions; + ` as unknown as DocumentNode; export const SearchDocument = gql` query Search($query: String!) { elements(search: $query) { @@ -1136,45 +390,7 @@ export const SearchDocument = gql` types } } - `; - -/** - * __useSearchQuery__ - * - * To run a query within a React component, call `useSearchQuery` and pass it any options that fit your needs. - * When your component renders, `useSearchQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useSearchQuery({ - * variables: { - * query: // value for 'query' - * }, - * }); - */ -export function useSearchQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: SearchQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SearchDocument, options); - } -export function useSearchLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SearchDocument, options); - } -// @ts-ignore -export function useSearchSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -// @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. -export function useSearchSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -export function useSearchSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - // @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. - return Apollo.useSuspenseQuery(SearchDocument, options); - } -export type SearchQueryHookResult = ReturnType; -export type SearchLazyQueryHookResult = ReturnType; -export type SearchSuspenseQueryHookResult = ReturnType; -export type SearchQueryResult = Apollo.QueryResult; + ` as unknown as DocumentNode; export const TripsDocument = gql` query Trips { trips { @@ -1183,44 +399,7 @@ export const TripsDocument = gql` icon } } - `; - -/** - * __useTripsQuery__ - * - * To run a query within a React component, call `useTripsQuery` and pass it any options that fit your needs. - * When your component renders, `useTripsQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useTripsQuery({ - * variables: { - * }, - * }); - */ -export function useTripsQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(TripsDocument, options); - } -export function useTripsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(TripsDocument, options); - } -// @ts-ignore -export function useTripsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -// @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. -export function useTripsSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions): Apollo.UseSuspenseQueryResult; -export function useTripsSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - // @ts-ignore typescript-react-apollo (v3 plugin) emits suspense hooks incompatible with Apollo Client v4 option/result types; these hooks are unused. - return Apollo.useSuspenseQuery(TripsDocument, options); - } -export type TripsQueryHookResult = ReturnType; -export type TripsLazyQueryHookResult = ReturnType; -export type TripsSuspenseQueryHookResult = ReturnType; -export type TripsQueryResult = Apollo.QueryResult; + ` as unknown as DocumentNode; export const UpdateElementDocument = gql` mutation UpdateElement($input: ElementInput!) { updateElement(input: $input) { @@ -1257,32 +436,16 @@ export const UpdateElementDocument = gql` startTz endTz } + metadata { + type + number + reservation + seat + paymentDetails + address + departureLocation + arrivalLocation + } } } - `; -export type UpdateElementMutationFn = Apollo.useMutation.MutationFunction; - -/** - * __useUpdateElementMutation__ - * - * To run a mutation, you first call `useUpdateElementMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateElementMutation` returns a tuple that includes: - * - A mutate function that you can call at any time to execute the mutation - * - An object with fields that represent the current status of the mutation's execution - * - * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; - * - * @example - * const [updateElementMutation, { data, loading, error }] = useUpdateElementMutation({ - * variables: { - * input: // value for 'input' - * }, - * }); - */ -export function useUpdateElementMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateElementDocument, options); - } -export type UpdateElementMutationHookResult = ReturnType; -export type UpdateElementMutationResult = Apollo.MutationResult; -export type UpdateElementMutationOptions = Apollo.MutationHookOptions; \ No newline at end of file + ` as unknown as DocumentNode; \ No newline at end of file diff --git a/src/graphql/queries/elementDetail.graphql b/src/graphql/queries/elementDetail.graphql index 7bab30f..1dca19a 100644 --- a/src/graphql/queries/elementDetail.graphql +++ b/src/graphql/queries/elementDetail.graphql @@ -33,5 +33,15 @@ query ElementDetail($id: String!) { startTz endTz } + metadata { + type + number + reservation + seat + paymentDetails + address + departureLocation + arrivalLocation + } } } diff --git a/src/graphql/queries/importShare.graphql b/src/graphql/queries/importShare.graphql index a5f9915..4a2f0fe 100644 --- a/src/graphql/queries/importShare.graphql +++ b/src/graphql/queries/importShare.graphql @@ -33,5 +33,15 @@ mutation ImportShare($content: String!) { startTz endTz } + metadata { + type + number + reservation + seat + paymentDetails + address + departureLocation + arrivalLocation + } } } diff --git a/src/graphql/queries/updateElement.graphql b/src/graphql/queries/updateElement.graphql index a30f36e..c7aa880 100644 --- a/src/graphql/queries/updateElement.graphql +++ b/src/graphql/queries/updateElement.graphql @@ -33,5 +33,15 @@ mutation UpdateElement($input: ElementInput!) { startTz endTz } + metadata { + type + number + reservation + seat + paymentDetails + address + departureLocation + arrivalLocation + } } } diff --git a/src/map/ElementDetailScreen.tsx b/src/map/ElementDetailScreen.tsx index d6bb395..a683223 100644 --- a/src/map/ElementDetailScreen.tsx +++ b/src/map/ElementDetailScreen.tsx @@ -1,3 +1,4 @@ +import {useQuery} from '@apollo/client/react'; import type {NativeStackScreenProps} from '@react-navigation/native-stack'; import {useMemo, useState} from 'react'; import { @@ -12,8 +13,8 @@ import { } from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; import { + ElementDetailDocument, type ElementDetailQuery, - useElementDetailQuery, } from '../graphql/__generated__/types'; import type {RootStackParamList} from '../navigation/types'; import {PhotoViewer} from '../photos/PhotoViewer'; @@ -21,6 +22,7 @@ import {photoImageSource} from '../photos/photoImageSource'; import type {Theme} from '../theme/colors'; import {useTheme} from '../theme/useTheme'; import {formatSchedule} from './formatSchedule'; +import {metadataRows} from './metadataRows'; type Props = NativeStackScreenProps; @@ -32,7 +34,9 @@ export function ElementDetailScreen({route, navigation}: Props) { const {elementId} = route.params; const theme = useTheme(); const styles = useMemo(() => makeStyles(theme), [theme]); - const {data, loading} = useElementDetailQuery({variables: {id: elementId}}); + const {data, loading} = useQuery(ElementDetailDocument, { + variables: {id: elementId}, + }); return ( @@ -69,6 +73,13 @@ function ModalContents({ const styles = useMemo(() => makeStyles(theme), [theme]); const safeAreaInsets = useSafeAreaInsets(); const [viewedPhoto, setViewedPhoto] = useState(null); + const booking = useMemo( + () => + metadataRows(element?.metadata, { + hasLocation: Boolean(element?.location), + }), + [element?.metadata, element?.location], + ); return ( @@ -171,6 +182,34 @@ function ModalContents({ ) : null} + {booking.length > 0 ? ( +
+ + {booking.map(({key, title, value, link}) => ( + + {title} + {link ? ( + Linking.openURL(link)} + style={({pressed}) => [ + styles.bookingValue, + pressed && styles.linkPressed, + ]}> + {value} + + ) : ( + + {value} + + )} + + ))} + +
+ ) : null} + {element.labels.length > 0 ? (
@@ -345,6 +384,25 @@ const makeStyles = (theme: Theme) => lineHeight: 21, color: theme.accent, }, + bookingRows: { + gap: 10, + }, + // Label beside its value rather than above it: booking values are mostly + // short codes, and the fixed label column lines them all up for scanning. + bookingRow: { + flexDirection: 'row', + alignItems: 'flex-start', + gap: 12, + }, + bookingLabel: { + width: 84, + fontSize: 13, + lineHeight: 21, + color: theme.textSecondary, + }, + bookingValue: { + flex: 1, + }, linkPressed: { opacity: 0.6, }, diff --git a/src/map/ElementEditScreen.tsx b/src/map/ElementEditScreen.tsx index 76c0612..bc2ea42 100644 --- a/src/map/ElementEditScreen.tsx +++ b/src/map/ElementEditScreen.tsx @@ -1,3 +1,4 @@ +import {useMutation, useQuery} from '@apollo/client/react'; import type {NativeStackScreenProps} from '@react-navigation/native-stack'; import {useMemo, useState} from 'react'; import { @@ -17,12 +18,12 @@ import { import {useSafeAreaInsets} from 'react-native-safe-area-context'; import EmojiPicker from 'rn-emoji-keyboard'; import { + DeleteElementDocument, + ElementDetailDocument, type ElementDetailQuery, type ElementInput, - useDeleteElementMutation, - useElementDetailQuery, - useTripsQuery, - useUpdateElementMutation, + TripsDocument, + UpdateElementDocument, } from '../graphql/__generated__/types'; import type {RootStackParamList} from '../navigation/types'; import {photoImageSource} from '../photos/photoImageSource'; @@ -47,7 +48,9 @@ export function ElementEditScreen({route, navigation}: Props) { const {elementId} = route.params; const theme = useTheme(); const styles = useMemo(() => makeStyles(theme), [theme]); - const {data, loading} = useElementDetailQuery({variables: {id: elementId}}); + const {data, loading} = useQuery(ElementDetailDocument, { + variables: {id: elementId}, + }); const element = data?.element; return ( @@ -113,10 +116,12 @@ function EditForm({ const [labelDraft, setLabelDraft] = useState(''); const [pickerOpen, setPickerOpen] = useState(false); const [errorMessage, setErrorMessage] = useState(null); - const [updateElement, {loading: saving}] = useUpdateElementMutation(); - const [deleteElement, {loading: deleting}] = useDeleteElementMutation(); + const [updateElement, {loading: saving}] = useMutation(UpdateElementDocument); + const [deleteElement, {loading: deleting}] = useMutation( + DeleteElementDocument, + ); const {pickAndUpload, uploading} = usePhotoUploader(); - const {data: tripsData} = useTripsQuery(); + const {data: tripsData} = useQuery(TripsDocument); const allTrips = tripsData?.trips ?? []; const selectedTrips = allTrips.filter(trip => tripIds.includes(trip.id)); diff --git a/src/map/ElementPreviewCard.tsx b/src/map/ElementPreviewCard.tsx index e4bf6fb..2e101b9 100644 --- a/src/map/ElementPreviewCard.tsx +++ b/src/map/ElementPreviewCard.tsx @@ -1,6 +1,7 @@ +import {useQuery} from '@apollo/client/react'; import {useMemo} from 'react'; import {Pressable, StyleSheet, Text, View} from 'react-native'; -import {useElementDetailQuery} from '../graphql/__generated__/types'; +import {ElementDetailDocument} from '../graphql/__generated__/types'; import type {Theme} from '../theme/colors'; import {useTheme} from '../theme/useTheme'; @@ -19,7 +20,9 @@ export function ElementPreviewCard({ }: Props) { const theme = useTheme(); const styles = useMemo(() => makeStyles(theme), [theme]); - const {data, loading} = useElementDetailQuery({variables: {id: elementId}}); + const {data, loading} = useQuery(ElementDetailDocument, { + variables: {id: elementId}, + }); const element = data?.element; return ( diff --git a/src/map/MapScreen.tsx b/src/map/MapScreen.tsx index c666d67..279071e 100644 --- a/src/map/MapScreen.tsx +++ b/src/map/MapScreen.tsx @@ -1,3 +1,4 @@ +import {useQuery} from '@apollo/client/react'; import { Camera, type CameraRef, @@ -24,10 +25,9 @@ import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; import {AccountMenu} from '../account/AccountMenu'; import { + ElementsDocument, type ElementsQuery, type ElementsQueryVariables, - LabelMatchMode, - useElementsQuery, } from '../graphql/__generated__/types'; import type { RootStackNavigation, @@ -231,9 +231,9 @@ export function MapScreen() { // Label filters apply on top of either mode below, narrowing the server-side // result. When none are active the vars are omitted so the query is unchanged. const labelVars = useMemo( - () => + (): Pick | undefined => labelFilters.length > 0 - ? {labels: labelFilters, labelsMatch: LabelMatchMode.All} + ? {labels: labelFilters, labelsMatch: 'ALL'} : undefined, [labelFilters], ); @@ -242,7 +242,8 @@ export function MapScreen() { // elements; otherwise fetch by viewport bounds. Reusing the single hook keeps // the element shape (and Apollo cache) identical across modes. Label filters // (if any) are layered onto whichever mode is active. - const {data, loading: elementsLoading} = useElementsQuery( + const {data, loading: elementsLoading} = useQuery( + ElementsDocument, tripFilter ? {variables: {tripId: tripFilter.id, ...labelVars}} : {skip: !bounds, variables: bounds ? {bounds, ...labelVars} : undefined}, diff --git a/src/map/SearchOverlay.tsx b/src/map/SearchOverlay.tsx index 0d58461..87b4588 100644 --- a/src/map/SearchOverlay.tsx +++ b/src/map/SearchOverlay.tsx @@ -1,3 +1,4 @@ +import {useLazyQuery} from '@apollo/client/react'; import {useCallback, useMemo, useRef, useState} from 'react'; import { ActivityIndicator, @@ -9,10 +10,7 @@ import { TextInput, View, } from 'react-native'; -import { - type SearchQuery, - useSearchLazyQuery, -} from '../graphql/__generated__/types'; +import {SearchDocument, type SearchQuery} from '../graphql/__generated__/types'; import type {Theme} from '../theme/colors'; import {useTheme} from '../theme/useTheme'; @@ -46,7 +44,7 @@ export function SearchOverlay({ const [text, setText] = useState(''); const [submitted, setSubmitted] = useState(false); const inputRef = useRef(null); - const [runSearch, {data, loading}] = useSearchLazyQuery({ + const [runSearch, {data, loading}] = useLazyQuery(SearchDocument, { fetchPolicy: 'network-only', }); diff --git a/src/map/metadataRows.ts b/src/map/metadataRows.ts new file mode 100644 index 0000000..60a89c1 --- /dev/null +++ b/src/map/metadataRows.ts @@ -0,0 +1,95 @@ +// Turn an element's parsed booking metadata (flight numbers, reservation codes, +// seats) into labelled rows, ready to render. +// +// This mirrors the web app's presentation so the same booking reads the same on +// both: the same row order, the same titles, and the same two judgement calls — +// `type` never gets a row of its own (it titles the number instead), and the +// raw `address` only appears when geocoding failed, since a geocoded one is +// already shown as the element's location. + +export type FormattableMetadata = { + type?: string | null; + number?: string | null; + reservation?: string | null; + seat?: string | null; + paymentDetails?: string | null; + address?: string | null; + departureLocation?: string | null; + arrivalLocation?: string | null; +}; + +export type MetadataRow = { + /** Stable key for lists — the metadata field this row came from. */ + key: string; + title: string; + value: string; + /** Somewhere to look the value up, when that's useful. */ + link: string | null; +}; + +// Fields we know how to present, in the order they read best. +const FIELDS = [ + 'number', + 'departureLocation', + 'arrivalLocation', + 'reservation', + 'seat', + 'paymentDetails', + 'address', +] as const satisfies readonly (keyof FormattableMetadata)[]; + +const TITLES: Record<(typeof FIELDS)[number], string> = { + number: 'Number', + departureLocation: 'From', + arrivalLocation: 'To', + reservation: 'Reservation', + seat: 'Seat', + paymentDetails: 'Payment', + address: 'Address', +}; + +// What a `number` is called depends on how you're travelling. Anything else +// (car, other, absent) keeps the generic title. +const NUMBER_TITLES: Record = { + flight: 'Flight', + train: 'Train', + bus: 'Bus', + ferry: 'Ferry', +}; + +export function metadataRows( + metadata: FormattableMetadata | null | undefined, + {hasLocation}: {hasLocation: boolean} = {hasLocation: false}, +): MetadataRow[] { + if (!metadata) return []; + + const rows: MetadataRow[] = []; + for (const field of FIELDS) { + const value = metadata[field]?.trim(); + if (!value) continue; + if (field === 'address' && hasLocation) continue; + rows.push({ + key: field, + title: field === 'number' ? numberTitle(metadata.type) : TITLES[field], + value, + link: field === 'number' ? flightStatusLink(metadata.type, value) : null, + }); + } + return rows; +} + +function numberTitle(type: string | null | undefined): string { + return (type && NUMBER_TITLES[type.toLowerCase()]) || TITLES.number; +} + +// A flight number is only worth tapping if it leads somewhere. Parsed numbers +// range from codes ("IB3216") to a spelled-out airline and number ("American +// Airlines 291"), so a status search handles both where a tracker URL wouldn't. +function flightStatusLink( + type: string | null | undefined, + value: string, +): string | null { + if (type?.toLowerCase() !== 'flight') return null; + const query = encodeURIComponent(`${value} flight status`); + return `https://www.google.com/search?q=${query}`; +} diff --git a/src/photos/photoUpload.ts b/src/photos/photoUpload.ts index e475c7b..f3848ea 100644 --- a/src/photos/photoUpload.ts +++ b/src/photos/photoUpload.ts @@ -1,14 +1,11 @@ -import {useApolloClient} from '@apollo/client/react'; +import {useApolloClient, useMutation} from '@apollo/client/react'; import ImageResizer from '@bam.tech/react-native-image-resizer'; import {useCallback, useState} from 'react'; import {launchImageLibrary} from 'react-native-image-picker'; import { + CreatePhotoDocument, type CreatePhotoMutation, CreateUploadUrlDocument, - type CreateUploadUrlQuery, - type CreateUploadUrlQueryVariables, - PhotoType, - useCreatePhotoMutation, } from '../graphql/__generated__/types'; // Server-side cap. We downsample on-device so the uploaded JPEG always lands @@ -121,7 +118,7 @@ export function usePhotoUploader(): { uploading: boolean; } { const client = useApolloClient(); - const [createPhoto] = useCreatePhotoMutation(); + const [createPhoto] = useMutation(CreatePhotoDocument); const [uploading, setUploading] = useState(false); const pickAndUpload = useCallback(async () => { @@ -133,10 +130,10 @@ export function usePhotoUploader(): { const uri = await downsampleToLimit(picked); // Step 1: signed upload URL. no-cache so each upload gets a fresh URL. - const {data: urlData} = await client.query< - CreateUploadUrlQuery, - CreateUploadUrlQueryVariables - >({query: CreateUploadUrlDocument, fetchPolicy: 'no-cache'}); + const {data: urlData} = await client.query({ + query: CreateUploadUrlDocument, + fetchPolicy: 'no-cache', + }); if (!urlData) throw new Error('Failed to get a photo upload URL'); const {url, key} = urlData.createUploadUrl; @@ -145,7 +142,7 @@ export function usePhotoUploader(): { // Step 3: register the uploaded object as a Photo. const {data: photoData} = await createPhoto({ - variables: {input: {type: PhotoType.S3, storageKey: key}}, + variables: {input: {type: 'S3', storageKey: key}}, }); const photo = photoData?.createPhoto; if (!photo) throw new Error('Photo could not be created.'); diff --git a/src/share/ImportShareScreen.tsx b/src/share/ImportShareScreen.tsx index 35231f6..081e716 100644 --- a/src/share/ImportShareScreen.tsx +++ b/src/share/ImportShareScreen.tsx @@ -1,3 +1,4 @@ +import {useMutation} from '@apollo/client/react'; import type {NativeStackScreenProps} from '@react-navigation/native-stack'; import {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import { @@ -8,7 +9,7 @@ import { View, } from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; -import {useImportShareMutation} from '../graphql/__generated__/types'; +import {ImportShareDocument} from '../graphql/__generated__/types'; import type {RootStackParamList} from '../navigation/types'; import type {Theme} from '../theme/colors'; import {useTheme} from '../theme/useTheme'; @@ -27,7 +28,7 @@ export function ImportShareScreen({route, navigation}: Props) { const theme = useTheme(); const styles = useMemo(() => makeStyles(theme), [theme]); const insets = useSafeAreaInsets(); - const [importShare] = useImportShareMutation(); + const [importShare] = useMutation(ImportShareDocument); const [failed, setFailed] = useState(false); // Guards against React's dev-mode double-invoked effect firing the mutation twice. const inFlight = useRef(false);