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);