diff --git a/composables/services/apollo.ts b/composables/services/apollo.ts new file mode 100644 index 000000000..60c825e17 --- /dev/null +++ b/composables/services/apollo.ts @@ -0,0 +1,66 @@ +import { DefaultApolloClient } from '@vue/apollo-composable'; +import { ApolloClient, HttpLink, InMemoryCache, split } from '@apollo/client/core'; +import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; +import { getMainDefinition } from '@apollo/client/utilities'; +import { createClient } from 'graphql-ws'; + +export interface ApolloClientPayload { + apiKey: string; + httpEndpoint: string; + wsEndpoint: string; +} + +const useApollo = (payload: ApolloClientPayload) => { + console.debug('[useApollo.create]', payload); + + const unraidApiClient = ref>(); + + // Create an http link: + const httpLink = new HttpLink({ + uri: payload.httpEndpoint, + headers: { + 'x-api-key': payload.apiKey, + }, + }); + + // Create a GraphQLWsLink link: + const wsLink = new GraphQLWsLink( + createClient({ + url: payload.wsEndpoint, + connectionParams: () => ({ + headers: { + 'x-api-key': payload.apiKey, + }, + }), + }), + ); + + // using the ability to split links, you can send data to each link + // depending on what kind of operation is being sent + const link = split( + // split based on operation type + ({ query }) => { + const definition = getMainDefinition(query); + return ( + definition.kind === "OperationDefinition" && + definition.operation === "subscription" + ); + }, + wsLink, + httpLink, + ); + + console.debug('[useApollo.create] link', link); + + // Create the apollo client with cache implementation. + unraidApiClient.value = new ApolloClient({ + // link, + cache: new InMemoryCache(), + }); + + return { + unraidApiClient, + }; +}; + +export default useApollo; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 69b7eb116..cffb0c4b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,13 +7,18 @@ "name": "connect-components", "hasInstallScript": true, "dependencies": { + "@apollo/client": "^3.7.17", "@headlessui/vue": "^1.7.14", "@heroicons/vue": "^2.0.18", "@pinia/nuxt": "^0.4.11", + "@vue/apollo-composable": "^4.0.0-beta.8", "@vueuse/components": "^10.1.2", "crypto-js": "^4.1.1", "dayjs": "^1.11.7", "focus-trap": "^7.4.3", + "graphql": "^16.7.1", + "graphql-tag": "^2.12.6", + "graphql-ws": "^5.14.0", "hex-to-rgba": "^2.0.1", "wretch": "^2.6.0" }, @@ -63,6 +68,52 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/@apollo/client": { + "version": "3.7.17", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.17.tgz", + "integrity": "sha512-0EErSHEtKPNl5wgWikHJbKFAzJ/k11O0WO2QyqZSHpdxdAnw7UWHY4YiLbHCFG7lhrD+NTQ3Z/H9Jn4rcikoJA==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "@wry/context": "^0.7.0", + "@wry/equality": "^0.5.0", + "@wry/trie": "^0.4.0", + "graphql-tag": "^2.12.6", + "hoist-non-react-statics": "^3.3.2", + "optimism": "^0.16.2", + "prop-types": "^15.7.2", + "response-iterator": "^0.2.6", + "symbol-observable": "^4.0.0", + "ts-invariant": "^0.10.3", + "tslib": "^2.3.0", + "zen-observable-ts": "^1.2.5" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0", + "graphql-ws": "^5.5.5", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "subscriptions-transport-ws": "^0.9.0 || ^0.11.0" + }, + "peerDependenciesMeta": { + "graphql-ws": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "subscriptions-transport-ws": { + "optional": true + } + } + }, + "node_modules/@apollo/client/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/@aws-crypto/sha256-js": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz", @@ -1458,6 +1509,14 @@ "node": ">=12" } }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -3269,6 +3328,52 @@ } } }, + "node_modules/@vue/apollo-composable": { + "version": "4.0.0-beta.8", + "resolved": "https://registry.npmjs.org/@vue/apollo-composable/-/apollo-composable-4.0.0-beta.8.tgz", + "integrity": "sha512-njoXHgeUtAJxs2feSGkTCdqgBjopqUGIdsepYHI8OkniGSWUiYrQL/j395EJx4Umxtbc7ez+TbcJCAa7zjLIEQ==", + "dependencies": { + "throttle-debounce": "^3.0.1", + "ts-essentials": "^9.1.2", + "vue-demi": "^0.13.1" + }, + "peerDependencies": { + "@apollo/client": "^3.4.13", + "@vue/composition-api": "^1.0.0", + "graphql": ">=15", + "vue": "^2.6.0 || ^3.1.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vue/apollo-composable/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/@vue/babel-helper-vue-transform-on": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.1.5.tgz", @@ -3653,6 +3758,54 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@wry/context": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz", + "integrity": "sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/context/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/@wry/equality": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.6.tgz", + "integrity": "sha512-D46sfMTngaYlrH+OspKf8mIJETntFnf6Hsjb0V41jAXJ7Bx2kB8Rv8RCUujuVWYttFtHkUNp7g+FwxNQAr6mXA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/equality/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/@wry/trie": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", + "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/trie/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -6945,6 +7098,44 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, + "node_modules/graphql": { + "version": "16.7.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.7.1.tgz", + "integrity": "sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/graphql-tag/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/graphql-ws": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.14.0.tgz", + "integrity": "sha512-itrUTQZP/TgswR4GSSYuwWUzrE/w5GhbwM2GX3ic2U7aw33jgEsayfIlvaj7/GcIvZgNMzsPTrE5hqPuFUiE5g==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": ">=0.11 <=16" + } + }, "node_modules/gzip-size": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-7.0.0.tgz", @@ -7087,6 +7278,14 @@ "resolved": "https://registry.npmjs.org/hex-to-rgba/-/hex-to-rgba-2.0.1.tgz", "integrity": "sha512-5XqPJBpsEUMsseJUi2w2Hl7cHFFi3+OO10M2pzAvKB1zL6fc+koGMhmBqoDOCB4GemiRM/zvDMRIhVw6EkB8dQ==" }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", @@ -8447,6 +8646,17 @@ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -9670,7 +9880,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9825,6 +10034,31 @@ "opener": "bin/opener-bin.js" } }, + "node_modules/optimism": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz", + "integrity": "sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==", + "dependencies": { + "@wry/context": "^0.7.0", + "@wry/trie": "^0.3.0" + } + }, + "node_modules/optimism/node_modules/@wry/trie": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.2.tgz", + "integrity": "sha512-yRTyhWSls2OY/pYLfwff867r8ekooZ4UI+/gxot5Wj8EFwSf2rG+n+Mo/6LoLQm1TKA4GRj2+LCpbfS937dClQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/optimism/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", @@ -11070,6 +11304,16 @@ "node": ">= 6" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/protocols": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", @@ -11143,6 +11387,11 @@ "flat": "^5.0.2" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -11571,6 +11820,14 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/response-iterator": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.6.tgz", + "integrity": "sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -12666,6 +12923,14 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", @@ -13010,6 +13275,14 @@ "node": ">=0.8" } }, + "node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "engines": { + "node": ">=10" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -13083,12 +13356,36 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, + "node_modules/ts-essentials": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.3.2.tgz", + "integrity": "sha512-JxKJzuWqH1MmH4ZFHtJzGEhkfN3QvVR3C3w+4BIoWeoY68UVVoA2Np/Bca9z0IPSErVCWhv439aT0We4Dks8kQ==", + "peerDependencies": { + "typescript": ">=4.1.0" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, + "node_modules/ts-invariant": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", + "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-invariant/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -13160,6 +13457,19 @@ "node": ">= 0.6" } }, + "node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/ufo": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.2.tgz", @@ -14653,6 +14963,19 @@ "node": ">= 4.0.0" } }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "node_modules/zen-observable-ts": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz", + "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==", + "dependencies": { + "zen-observable": "0.8.15" + } + }, "node_modules/zhead": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/zhead/-/zhead-2.0.9.tgz", diff --git a/package.json b/package.json index f44854506..0e34e8a75 100644 --- a/package.json +++ b/package.json @@ -24,13 +24,18 @@ "nuxt-custom-elements": "^2.0.0-beta.12" }, "dependencies": { + "@apollo/client": "^3.7.17", "@headlessui/vue": "^1.7.14", "@heroicons/vue": "^2.0.18", "@pinia/nuxt": "^0.4.11", + "@vue/apollo-composable": "^4.0.0-beta.8", "@vueuse/components": "^10.1.2", "crypto-js": "^4.1.1", "dayjs": "^1.11.7", "focus-trap": "^7.4.3", + "graphql": "^16.7.1", + "graphql-tag": "^2.12.6", + "graphql-ws": "^5.14.0", "hex-to-rgba": "^2.0.1", "wretch": "^2.6.0" }, diff --git a/store/server.ts b/store/server.ts index 95904c6e0..f5c72b741 100644 --- a/store/server.ts +++ b/store/server.ts @@ -17,6 +17,7 @@ import { useErrorsStore, type Error } from '~/store/errors'; import { usePurchaseStore } from "~/store/purchase"; import { useTrialStore } from '~/store/trial'; import { useThemeStore, type Theme } from '~/store/theme'; +import { useUnraidApiStore } from '~/store/unraidApi'; import type { Server, ServerAccountCallbackSendPayload, @@ -40,6 +41,7 @@ export const useServerStore = defineStore('server', () => { const purchaseStore = usePurchaseStore(); const themeStore = useThemeStore(); const trialStore = useTrialStore(); + const unraidApiStore = useUnraidApiStore(); /** * State */ @@ -650,6 +652,18 @@ export const useServerStore = defineStore('server', () => { console.debug('[setServer] server.value', server.value); }; + watch(apiKey, (newVal, oldVal) => { + console.debug('[useUnraidApiStore] apiKey', newVal, oldVal); + if (oldVal) { + // stop old client + console.debug('[useUnraidApiStore] no apiKey – stop old client'); + } + if (newVal) { + // start new client + console.debug('[useUnraidApiStore] apiKey – start new client'); + unraidApiStore.createApolloClient(); + } + }); watch(theme, (newVal) => { if (newVal) themeStore.setTheme(newVal); }); diff --git a/store/unraidApi.ts b/store/unraidApi.ts new file mode 100644 index 000000000..e0133df8e --- /dev/null +++ b/store/unraidApi.ts @@ -0,0 +1,40 @@ +import { provideApolloClient } from '@vue/apollo-composable'; +import { defineStore, createPinia, setActivePinia } from 'pinia'; + +import useApollo from '~/composables/services/apollo'; + +/** + * @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components + * @see https://github.com/vuejs/pinia/discussions/1085 + */ +setActivePinia(createPinia()); + +const WINDOW_URL = new URL(window.location.origin); +const httpEndpoint = `${WINDOW_URL.protocol}//${WINDOW_URL.host}/graphql`; +const wsProtocol = WINDOW_URL.protocol.includes('https') ? 'wss://' : 'ws://'; +const wsEndpoint = `${wsProtocol}${WINDOW_URL.host}/graphql`; + +export const useUnraidApiStore = defineStore('unraidApi', () => { + console.debug('[useUnraidApiStore]'); + + const apiKey = ref(''); + + const setApiKey = (newApiKey: string) => apiKey.value = newApiKey; + + const createApolloClient = () => { + console.debug('[useUnraidApiStore] createClient'); + const { unraidApiClient} = useApollo({ + apiKey: apiKey.value, + httpEndpoint, + wsEndpoint, + }); + console.debug('[useUnraidApiStore] provideApolloClient', unraidApiClient.value); + // provideApolloClient(unraidApiClient); + }; + + return { + apiKey, + setApiKey, + createApolloClient, + }; +});