From 4aefc0744ebd36cafd3f768353b63236e5e1d5f0 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 14:09:46 +0200 Subject: [PATCH 01/50] Add Config A configuration config has been added which currently includes the credentials of the anonymous user. --- src/config.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/config.json diff --git a/src/config.json b/src/config.json new file mode 100644 index 0000000..ab8d19a --- /dev/null +++ b/src/config.json @@ -0,0 +1,6 @@ +{ + "anonUser": { + "username": "cisco", + "password": "ciscocisco" + } +} \ No newline at end of file From b0f179610c4f4ef97c0997c4ab06e2fb201c4ce6 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 14:11:41 +0200 Subject: [PATCH 02/50] Exchange hard coded credentials with config credentials By implementing the config, the credentials can now be extracted from it. --- src/templates/snek/gql/tasks/auth.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/templates/snek/gql/tasks/auth.ts b/src/templates/snek/gql/tasks/auth.ts index f0f8eb5..1c779b9 100644 --- a/src/templates/snek/gql/tasks/auth.ts +++ b/src/templates/snek/gql/tasks/auth.ts @@ -8,6 +8,8 @@ import { User } from "../../../../session"; //> Types // Contains the type declarations for Apollo results import { ApolloResult } from "./index"; +//> Config +import Config from "../../../../config.json"; //#endregion //#region > Interfaces @@ -68,8 +70,8 @@ class SnekGqlAuthTasks { "mutation", this.parent.template.mutations.jwtAuth.auth, { - username: "cisco", - password: "ciscocisco", + username: Config.anonUser.username, + password: Config.anonUser.password, } ); From 1a88e6be52a575e604b8b0a1ce4b29a8b59a59c6 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 14:15:01 +0200 Subject: [PATCH 03/50] Update SnekSession Begin Return Value Now the return includes whether the authenticated user is anonymous or not. --- src/session/sessions.ts | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/session/sessions.ts b/src/session/sessions.ts index 33cdc18..80170f9 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -24,6 +24,8 @@ import SnekTasks from "../templates/snek/gql/tasks/index"; import { ApolloEndpoint } from "../endpoints/index"; // Contains basic session interfaces import { User } from "./index"; +//> Config +import Config from "../config.json"; //#endregion //#region > Classes @@ -206,31 +208,38 @@ class SnekSession extends CookieSession { * @returns {Promise} A UserData object */ async begin(user?: User): Promise { - let response; + let anonymous = false; if (!user && this.refreshToken) { /* Refresh token and retrieve a new refreshToken if necessary */ this.refresh(); } else { + let authData; + if (!user) { /* Authenticate anonymous user */ - response = await this.tasks.auth.anon(); + authData = (await this.tasks.auth.anon()).data?.auth; + anonymous = true; } else { /* Authenticate real user */ - response = await this.tasks.auth.nonanon(user); + authData = (await this.tasks.auth.nonanon(user)).data?.auth; } /* Set tokens */ - this.token = response.data?.auth.token; - this.refreshToken = response.data?.auth.refreshToken; + this.token = authData?.token; + this.refreshToken = authData?.refreshToken; - return response.data?.auth.user; + return { anonymous, ...authData?.user }; } /* Get user data */ - response = await this.tasks.user.whoami(); + const userData = (await this.tasks.user.whoami()).data?.whoami; + + if (userData?.username === Config.anonUser.username) { + anonymous = true; + } - return response.data?.whoami; + return { anonymous, ...userData }; } /** From 78d234c026c89813767955164156db8905d9b3f0 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 15:37:14 +0200 Subject: [PATCH 04/50] Update Registration Mutation The mutation has been updated to fit the currently newest engine version. Ref: https://github.com/snek-at/engine/tree/sub --- src/templates/snek/gql/mutations/user.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/templates/snek/gql/mutations/user.ts b/src/templates/snek/gql/mutations/user.ts index 6d70064..bde8128 100644 --- a/src/templates/snek/gql/mutations/user.ts +++ b/src/templates/snek/gql/mutations/user.ts @@ -17,17 +17,16 @@ import gql from "graphql-tag"; */ const registration = gql` mutation registration($token: String!, $values: GenericScalar!) { - registration: registrationRegistrationFormPage( - token: $token - url: "/registration" - values: $values - ) { - result - errors { - name - errors + registration: registrationFormPage( + url: "/registration/", + token: $token, + values: $values) { + result + errors { + name + errors + } } - } } `; From 4468f0fb3a76de5a09e859e2805368263cc47d3d Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 15:39:24 +0200 Subject: [PATCH 05/50] Update GitlabServer Query The query has been updated to fit the currently newest engine version. Ref: https://github.com/snek-at/engine/tree/sub --- src/templates/snek/gql/queries/general.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/templates/snek/gql/queries/general.ts b/src/templates/snek/gql/queries/general.ts index 3533f63..b1feef3 100644 --- a/src/templates/snek/gql/queries/general.ts +++ b/src/templates/snek/gql/queries/general.ts @@ -15,13 +15,13 @@ import gql from "graphql-tag"; */ const gitlabServer = gql` query gitLabServers($token: String!) { - page(url: "/registration", token: $token) { - ... on RegistrationRegistrationFormPage { + page(slug: "registration", token: $token) { + ... on RegistrationFormPage { supportedGitlabs { - ... on RegistrationGitlab_Server { + ... on Gitlab_Server { + id organisation domain - field } } } From 69669216428fcbdd34d3d6ff0fafd753df6503bc Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 15:40:27 +0200 Subject: [PATCH 06/50] Add AllUserPageUrls Query The query has been added because the AllPageUrl query which was used before returned not only user pages. Ref: https://github.com/snek-at/engine/tree/sub --- src/templates/snek/gql/queries/general.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/templates/snek/gql/queries/general.ts b/src/templates/snek/gql/queries/general.ts index b1feef3..ac8a91a 100644 --- a/src/templates/snek/gql/queries/general.ts +++ b/src/templates/snek/gql/queries/general.ts @@ -43,10 +43,26 @@ const allPageUrls = gql` } } `; + +/** + * List of user page urls. + * + * @param {string} JWT A users JWT + * @returns {string} A serialized JSON object with a list of all page urls + * @description A query to fetch all user page urls + */ +const allUserPageUrls = gql` + query userPages($token: String!) { + page(slug: "user", token: $token) { + children { + url + } + } +`; //#endregion //#region > Exports -export { gitlabServer, allPageUrls }; +export { gitlabServer, allPageUrls, allUserPageUrls }; //#endregion /** From 6a84565be920ca0202652a33d13374f25e3b0c71 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 15:42:03 +0200 Subject: [PATCH 07/50] Update Profile Query The query has been updated to fit the currently newest engine version. Now it uses a slug instead of URL. Ref: https://github.com/snek-at/engine/tree/sub --- src/templates/snek/gql/queries/user.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/templates/snek/gql/queries/user.ts b/src/templates/snek/gql/queries/user.ts index bf9977e..20db7a4 100644 --- a/src/templates/snek/gql/queries/user.ts +++ b/src/templates/snek/gql/queries/user.ts @@ -29,15 +29,15 @@ const whoami = gql` /** * Get user profile. * - * @param {string} url PageUrl of a user profile + * @param {string} slug Slug: > * @param {string} token A users JWT * @returns {string} A profile page of a user * @description A query to fetch profile data */ const profile = gql` - query profile($url: String!, $token: String!) { - profile: page(url: $url, token: $token) { - ... on ProfileProfilePage { + query profile($slug: String!, $token: String!) { + profile: page(slug: $slug, token: $token) { + ... on ProfilePage { username firstName lastName From 3ff6097242d628f305d356d93e9d8583938124d1 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 15:42:58 +0200 Subject: [PATCH 08/50] Update GitlabServerData Interface The type declaration has been improved. --- src/templates/snek/gql/tasks/general.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/snek/gql/tasks/general.ts b/src/templates/snek/gql/tasks/general.ts index 6efc0c0..d5660cd 100644 --- a/src/templates/snek/gql/tasks/general.ts +++ b/src/templates/snek/gql/tasks/general.ts @@ -14,7 +14,7 @@ import { ApolloResult } from "./index"; */ interface GitlabServerData { page: { - supportedGitlabs: []; + supportedGitlabs: { id: string; organisation: string; domain: string; }[]; }; } From f11310c0a0d22d6e6f6efc7049087f0ccaab1afe Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 15:43:44 +0200 Subject: [PATCH 09/50] Update AllPageUrlData Interface The type declaration has been improved. --- src/templates/snek/gql/tasks/general.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/snek/gql/tasks/general.ts b/src/templates/snek/gql/tasks/general.ts index d5660cd..050ba29 100644 --- a/src/templates/snek/gql/tasks/general.ts +++ b/src/templates/snek/gql/tasks/general.ts @@ -23,7 +23,7 @@ interface GitlabServerData { * data. */ interface AllPageUrlData { - pages: []; + pages: { urlPath: string }[]; } //#endregion From eb570eeb7378671d00fd14400ed82ba73047ea8c Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 15:44:31 +0200 Subject: [PATCH 10/50] Improve Code Quality A missing whitespace has been added by prettier. --- src/templates/snek/gql/tasks/general.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/snek/gql/tasks/general.ts b/src/templates/snek/gql/tasks/general.ts index 050ba29..8a538f3 100644 --- a/src/templates/snek/gql/tasks/general.ts +++ b/src/templates/snek/gql/tasks/general.ts @@ -36,7 +36,7 @@ class SnekGqlGeneralTasks { * @author Nico Schett * @param {string} parent The parent task */ - constructor(private parent: SnekTasks) {} + constructor(private parent: SnekTasks) { } /** * Gitlab Server. From ce78e5a2d2a7348394f298090e33e90f9ce9afbc Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 15:45:20 +0200 Subject: [PATCH 11/50] Add AllUserPageUrls Task and Interface A task which uses the allUserPageUrls query has been added. --- src/templates/snek/gql/tasks/general.ts | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/templates/snek/gql/tasks/general.ts b/src/templates/snek/gql/tasks/general.ts index 8a538f3..c1db3f1 100644 --- a/src/templates/snek/gql/tasks/general.ts +++ b/src/templates/snek/gql/tasks/general.ts @@ -25,6 +25,14 @@ interface GitlabServerData { interface AllPageUrlData { pages: { urlPath: string }[]; } + +/** + * @interface AllUserPageUrlsData defines the types of the response of the + * allUserPageUrls query. + */ +interface AllUserPageUrlsData { + page: { children: { url: string }[] }; +} //#endregion //#region > Classes @@ -73,6 +81,25 @@ class SnekGqlGeneralTasks { return response; } + + /** + * All user page urls. + * + * @returns {Promise>} A list of all user + * page urls. + * @description Get a list of all pages + */ + async allUserPageUrls(): Promise> { + const response = await this.parent.run( + "query", + this.parent.template.queries.general.allUserPageUrls, + { + token: await this.parent.session.upToDateToken(), + } + ); + + return response; + } } //#endregion From 9b2351c7354451e05c90d0869ef904462883c6df Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 23:55:17 +0200 Subject: [PATCH 12/50] Fix Syntax Error in AllUserPageUrls A syntax error has been fixed. --- src/templates/snek/gql/queries/general.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/templates/snek/gql/queries/general.ts b/src/templates/snek/gql/queries/general.ts index ac8a91a..5c354ae 100644 --- a/src/templates/snek/gql/queries/general.ts +++ b/src/templates/snek/gql/queries/general.ts @@ -58,6 +58,7 @@ const allUserPageUrls = gql` url } } + } `; //#endregion From 2cfd5da71340c3a637b2693dd458595a34706145 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 5 Aug 2020 23:56:27 +0200 Subject: [PATCH 13/50] Update Default SnekClient URL The default API URL has been updated due to a endpoint notation change in engine.snek.at. --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 81d35e9..f717cc3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -78,7 +78,7 @@ class SnekClient extends Client { * @param type A type description to differ between multiple instances */ constructor( - url: string = "https://engine.snek.at/api/graphiql", + url: string = "https://engine.snek.at/graphiql", headers: object = {}, type: string = "graphql" ) { From b1b4eeb0a6a9251a8b0ef33fcb70cab4849c7ada Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 6 Aug 2020 00:46:28 +0200 Subject: [PATCH 14/50] Update TokenAuth Mutation Field which cannot longer be queried are removed now. --- src/templates/snek/gql/mutations/jwtAuth.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/templates/snek/gql/mutations/jwtAuth.ts b/src/templates/snek/gql/mutations/jwtAuth.ts index aad63d6..f1c2309 100644 --- a/src/templates/snek/gql/mutations/jwtAuth.ts +++ b/src/templates/snek/gql/mutations/jwtAuth.ts @@ -21,11 +21,6 @@ const auth = gql` refreshToken user { username - firstName - lastName - email - dateJoined - lastLogin } } } From c311e6cd06d73697de607d464e8d0e201a5cd7b9 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 6 Aug 2020 00:46:50 +0200 Subject: [PATCH 15/50] Update Whoami Query Field which cannot longer be queried are removed now. --- src/templates/snek/gql/queries/user.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/templates/snek/gql/queries/user.ts b/src/templates/snek/gql/queries/user.ts index 20db7a4..d1b6f8a 100644 --- a/src/templates/snek/gql/queries/user.ts +++ b/src/templates/snek/gql/queries/user.ts @@ -17,11 +17,6 @@ const whoami = gql` query whoami($token: String!) { whoami: me(token: $token) { username - firstName - lastName - email - dateJoined - lastLogin } } `; From 6aec1dd26dce3fb2cdd8e3d6f67cb7005192370a Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 6 Aug 2020 00:48:07 +0200 Subject: [PATCH 16/50] Update AllUserPageUrls Query Url has been replaced by slug. Also the title has been added, which represents the plain username. --- src/templates/snek/gql/queries/general.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/templates/snek/gql/queries/general.ts b/src/templates/snek/gql/queries/general.ts index 5c354ae..d11b3e5 100644 --- a/src/templates/snek/gql/queries/general.ts +++ b/src/templates/snek/gql/queries/general.ts @@ -55,7 +55,8 @@ const allUserPageUrls = gql` query userPages($token: String!) { page(slug: "user", token: $token) { children { - url + slug + title } } } From 11d43fcde70055942d999433a7971d7112ceba9c Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 6 Aug 2020 00:48:45 +0200 Subject: [PATCH 17/50] Update Profile Task Url has been replace with slug due to changes in the profile query. --- src/templates/snek/gql/tasks/user.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/templates/snek/gql/tasks/user.ts b/src/templates/snek/gql/tasks/user.ts index 274ee7e..cc33c18 100644 --- a/src/templates/snek/gql/tasks/user.ts +++ b/src/templates/snek/gql/tasks/user.ts @@ -106,15 +106,15 @@ class SnekGqlUserTasks { /** * Get profile. * - * @param {string} url A url of a page + * @param {string} slug Slug: > * @returns {Promise>} The profile page of a user */ - async profile(url: string): Promise> { + async profile(slug: string): Promise> { const response = await this.parent.run( "query", this.parent.template.queries.user.profile, { - url, + slug, token: await this.parent.session.upToDateToken(), } ); From 2dbf63829cc06abf03e79b3c7477df6860a5a468 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 6 Aug 2020 00:49:35 +0200 Subject: [PATCH 18/50] Update Default SnekClient URL The default API URL has been updated due to CSRF protection errors. --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index f717cc3..92c55e8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -78,7 +78,7 @@ class SnekClient extends Client { * @param type A type description to differ between multiple instances */ constructor( - url: string = "https://engine.snek.at/graphiql", + url: string = "https://engine.snek.at/graphql", headers: object = {}, type: string = "graphql" ) { From 628d8f622cbbeabc73c9913129146cb868e15e1d Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 6 Aug 2020 01:47:54 +0200 Subject: [PATCH 19/50] Bump to v0.2.0 The version has been updated to 0.2.0. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 02d23e6..f3cf5b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "snek-client", - "version": "0.1.1", + "version": "0.2.0", "description": "Enoy it.", "main": "lib/index.js", "types": "lib/index.d.ts", From eb2b7e7abe76d449aefbd453fffa5936c5961b8f Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 12 Aug 2020 15:03:28 +0200 Subject: [PATCH 20/50] Update registration mutation It is updated due to engine breaking changes. --- src/templates/snek/gql/mutations/user.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/templates/snek/gql/mutations/user.ts b/src/templates/snek/gql/mutations/user.ts index bde8128..45132fc 100644 --- a/src/templates/snek/gql/mutations/user.ts +++ b/src/templates/snek/gql/mutations/user.ts @@ -17,16 +17,17 @@ import gql from "graphql-tag"; */ const registration = gql` mutation registration($token: String!, $values: GenericScalar!) { - registration: registrationFormPage( - url: "/registration/", - token: $token, - values: $values) { - result - errors { - name - errors - } + registration: personRegistrationFormPage( + url: "/person-registration-form/" + token: $token + values: $values + ) { + result + errors { + name + errors } + } } `; @@ -40,8 +41,8 @@ const registration = gql` * @description A mutation to cache user information server side */ const cache = gql` - mutation cache($token: String!, $platformData: String!) { - cache: cacheUser(token: $token, platformData: $platformData) { + mutation cache($token: String!, $cache: String!) { + cache: cacheUser(token: $token, cache: $cache) { user { id } From 2a740a5a7b2e6632bb604612cbbce87e8e27afad Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 12 Aug 2020 15:04:07 +0200 Subject: [PATCH 21/50] Update cache mutation It is updated due to engine breaking changes. --- src/templates/snek/gql/tasks/user.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/templates/snek/gql/tasks/user.ts b/src/templates/snek/gql/tasks/user.ts index cc33c18..1b1f21a 100644 --- a/src/templates/snek/gql/tasks/user.ts +++ b/src/templates/snek/gql/tasks/user.ts @@ -87,16 +87,16 @@ class SnekGqlUserTasks { /** * Cache a user. * - * @param {string} platformData A serialized JSON object to be cached + * @param {string} cache A serialized JSON object to be cached * @returns {Promise>} Cache data */ - async cache(platformData: string): Promise> { + async cache(cache: string): Promise> { const response = await this.parent.run( "mutation", this.parent.template.mutations.user.cache, { token: await this.parent.session.upToDateToken(), - platformData, + cache, } ); From b9402d68872e8ba3e25010ebbe98e8bf12c0dcaf Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 12 Aug 2020 15:05:10 +0200 Subject: [PATCH 22/50] Update gitlabserver query It is updated due to engine breaking changes. --- src/templates/snek/gql/queries/general.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/templates/snek/gql/queries/general.ts b/src/templates/snek/gql/queries/general.ts index d11b3e5..ba7459e 100644 --- a/src/templates/snek/gql/queries/general.ts +++ b/src/templates/snek/gql/queries/general.ts @@ -15,10 +15,10 @@ import gql from "graphql-tag"; */ const gitlabServer = gql` query gitLabServers($token: String!) { - page(slug: "registration", token: $token) { - ... on RegistrationFormPage { + page(slug: "person-registration-form", token: $token) { + ... on PersonRegistrationFormPage { supportedGitlabs { - ... on Gitlab_Server { + ... on GitlabServer { id organisation domain From f1260026b16137c38c4e7a0e38581ba24dadae18 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 12 Aug 2020 15:05:30 +0200 Subject: [PATCH 23/50] Update alluserpages query It is updated due to engine breaking changes. --- src/templates/snek/gql/queries/general.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/snek/gql/queries/general.ts b/src/templates/snek/gql/queries/general.ts index ba7459e..37eff20 100644 --- a/src/templates/snek/gql/queries/general.ts +++ b/src/templates/snek/gql/queries/general.ts @@ -53,7 +53,7 @@ const allPageUrls = gql` */ const allUserPageUrls = gql` query userPages($token: String!) { - page(slug: "user", token: $token) { + page(slug: "people", token: $token) { children { slug title From 8a28068a7718d30188e5119f4a352123fb3583c4 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 12 Aug 2020 15:05:49 +0200 Subject: [PATCH 24/50] Update profile query It is updated due to engine breaking changes. --- src/templates/snek/gql/queries/user.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/templates/snek/gql/queries/user.ts b/src/templates/snek/gql/queries/user.ts index d1b6f8a..0637899 100644 --- a/src/templates/snek/gql/queries/user.ts +++ b/src/templates/snek/gql/queries/user.ts @@ -30,19 +30,20 @@ const whoami = gql` * @description A query to fetch profile data */ const profile = gql` - query profile($slug: String!, $token: String!) { - profile: page(slug: $slug, token: $token) { - ... on ProfilePage { - username - firstName - lastName - email - verified - platformData - sources - bids + query profile($username: String!, $token: String!) { + profile: user(username: $username, token: $token) { + username + firstName + lastName + email + verified: isActive + personpage { + title tids + bids } + platformData: cache + sources } } `; From c73ba3a20741c1c53c2f3b939499a87ae8fd5d49 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 12 Aug 2020 15:06:18 +0200 Subject: [PATCH 25/50] Update profile task The task is updated due to changes in the profile query. --- src/templates/snek/gql/tasks/user.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/templates/snek/gql/tasks/user.ts b/src/templates/snek/gql/tasks/user.ts index 1b1f21a..a59d415 100644 --- a/src/templates/snek/gql/tasks/user.ts +++ b/src/templates/snek/gql/tasks/user.ts @@ -106,15 +106,15 @@ class SnekGqlUserTasks { /** * Get profile. * - * @param {string} slug Slug: > + * @param {string} username Username: * @returns {Promise>} The profile page of a user */ - async profile(slug: string): Promise> { + async profile(username: string): Promise> { const response = await this.parent.run( "query", this.parent.template.queries.user.profile, { - slug, + username, token: await this.parent.session.upToDateToken(), } ); From eacfd7fbb72f9c335fee873bc9744c544b69b55c Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 12 Aug 2020 16:47:41 +0200 Subject: [PATCH 26/50] Add type declaration A return type has been added. --- src/templates/snek/gql/tasks/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/templates/snek/gql/tasks/index.ts b/src/templates/snek/gql/tasks/index.ts index ae0c713..f929601 100644 --- a/src/templates/snek/gql/tasks/index.ts +++ b/src/templates/snek/gql/tasks/index.ts @@ -50,7 +50,11 @@ class SnekTasks extends TaskError { this.user = new SnekGqlUserTasks(this); } - async run(type: string, query: DocumentNode, variables: object) { + async run( + type: string, + query: DocumentNode, + variables: object + ): Promise> { let response: ApolloResult; if (type === "query") { From 733a509e06d7d1ec08f4e24dd4c690ec1fb27c7b Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 12 Aug 2020 16:49:54 +0200 Subject: [PATCH 27/50] Update token aliveness Now a custom task checks and refreshes the token. --- src/session/sessions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/session/sessions.ts b/src/session/sessions.ts index 80170f9..c3fa5e4 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -294,7 +294,7 @@ class SnekSession extends CookieSession { async customTask(type: string, data: DocumentNode, variables: object) { return this.tasks.run(type, data, { ...variables, - token: this.token, + token: await this.upToDateToken(), refreshToken: this.refreshToken, }); } From 37b77da5c9f8bc037c58fa1bb623532986292cef Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 24 Aug 2020 18:08:24 +0200 Subject: [PATCH 28/50] Update profile query and task Once again, the profile query and task have been updated due to a structure change in engine. --- src/templates/snek/gql/queries/user.ts | 47 +++++++++++++++++++------- src/templates/snek/gql/tasks/user.ts | 34 ++++++++++++++++--- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/templates/snek/gql/queries/user.ts b/src/templates/snek/gql/queries/user.ts index 0637899..2b680c1 100644 --- a/src/templates/snek/gql/queries/user.ts +++ b/src/templates/snek/gql/queries/user.ts @@ -24,26 +24,49 @@ const whoami = gql` /** * Get user profile. * - * @param {string} slug Slug: > + * @param {string} slug Slug: > * @param {string} token A users JWT * @returns {string} A profile page of a user * @description A query to fetch profile data */ const profile = gql` - query profile($username: String!, $token: String!) { - profile: user(username: $username, token: $token) { - username - firstName - lastName - email - verified: isActive - personpage { - title + query profile($slug: String!, $token: String!) { + page(slug: $slug, token: $token) { + ... on PersonFormPage { + personName: title + firstName + lastName + email + platformData: cache + sources + person { + cache + sources + } tids bids + follows { + personName: slug + } + followedBy { + personName: slug + } + likes { + personName: slug + } + likedBy { + personName: slug + } + achievements { + id + title + image { + src + imageSourceUrl + } + points + } } - platformData: cache - sources } } `; diff --git a/src/templates/snek/gql/tasks/user.ts b/src/templates/snek/gql/tasks/user.ts index a59d415..51ac9ad 100644 --- a/src/templates/snek/gql/tasks/user.ts +++ b/src/templates/snek/gql/tasks/user.ts @@ -32,15 +32,39 @@ interface CacheData { */ interface ProfileData { profile: { - username: string; + profileName: string; firstName: string; lastName: string; email: string; - verified: string; platformData: string; sources: string; bids: string; tids: string; + person: { + cache: string; + sources: string; + }; + follows: { + personName: string; + }[]; + followedBy: { + personName: string; + }[]; + likes: { + personName: string; + }[]; + likedBy: { + personName: string; + }[]; + achievements: { + id: string; + title: string; + image: { + src: string; + imageSourceUrl: string; + }; + points: string; + }; }; } @@ -106,15 +130,15 @@ class SnekGqlUserTasks { /** * Get profile. * - * @param {string} username Username: + * @param {string} slug Slug: > * @returns {Promise>} The profile page of a user */ - async profile(username: string): Promise> { + async profile(slug: string): Promise> { const response = await this.parent.run( "query", this.parent.template.queries.user.profile, { - username, + slug, token: await this.parent.session.upToDateToken(), } ); From f07745088c82567166416b8f3c1218b78b2c099a Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 26 Aug 2020 11:42:40 +0200 Subject: [PATCH 29/50] Improve profile task The person task no longer accepts a slug but a personName. --- src/templates/snek/gql/tasks/user.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/templates/snek/gql/tasks/user.ts b/src/templates/snek/gql/tasks/user.ts index 51ac9ad..2a0cca0 100644 --- a/src/templates/snek/gql/tasks/user.ts +++ b/src/templates/snek/gql/tasks/user.ts @@ -130,15 +130,15 @@ class SnekGqlUserTasks { /** * Get profile. * - * @param {string} slug Slug: > + * @param {string} personName personName: * @returns {Promise>} The profile page of a user */ - async profile(slug: string): Promise> { + async profile(personName: string): Promise> { const response = await this.parent.run( "query", this.parent.template.queries.user.profile, { - slug, + slug: `p-${personName}`, token: await this.parent.session.upToDateToken(), } ); From 214ca592c8d469660251487ce3a95e265234fbc8 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 26 Aug 2020 15:38:46 +0200 Subject: [PATCH 30/50] Update cache mutation and task The cacheing task requires a person name now. --- src/templates/snek/gql/mutations/user.ts | 6 +++--- src/templates/snek/gql/tasks/user.ts | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/templates/snek/gql/mutations/user.ts b/src/templates/snek/gql/mutations/user.ts index 45132fc..7e5f9a1 100644 --- a/src/templates/snek/gql/mutations/user.ts +++ b/src/templates/snek/gql/mutations/user.ts @@ -41,9 +41,9 @@ const registration = gql` * @description A mutation to cache user information server side */ const cache = gql` - mutation cache($token: String!, $cache: String!) { - cache: cacheUser(token: $token, cache: $cache) { - user { + mutation cache($token: String!, $personName: String!, $cache: String!) { + cache: cacheUser(token: $token, personName: $personName, cache: $cache) { + personPage { id } } diff --git a/src/templates/snek/gql/tasks/user.ts b/src/templates/snek/gql/tasks/user.ts index 2a0cca0..e61d32e 100644 --- a/src/templates/snek/gql/tasks/user.ts +++ b/src/templates/snek/gql/tasks/user.ts @@ -111,15 +111,20 @@ class SnekGqlUserTasks { /** * Cache a user. * + * @param {string} personName The name of a users person page * @param {string} cache A serialized JSON object to be cached * @returns {Promise>} Cache data */ - async cache(cache: string): Promise> { + async cache( + personName: string, + cache: string + ): Promise> { const response = await this.parent.run( "mutation", this.parent.template.mutations.user.cache, { token: await this.parent.session.upToDateToken(), + personName, cache, } ); From 48ff645960c8bbcbfc2da8e854e3a8f90504464a Mon Sep 17 00:00:00 2001 From: schettn Date: Fri, 4 Sep 2020 02:15:51 +0200 Subject: [PATCH 31/50] Add instagram session A session which can handle the rest api access to instagram/facebook has been implemented. --- src/session/sessions.ts | 65 ++++++++++++++++++++++++++++++-- src/templates/instagram/index.ts | 7 ++++ src/templates/instagram/tasks.ts | 42 +++++++++++++++++++++ src/templates/instagram/urls.ts | 7 ++++ 4 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 src/templates/instagram/index.ts create mode 100644 src/templates/instagram/tasks.ts create mode 100644 src/templates/instagram/urls.ts diff --git a/src/session/sessions.ts b/src/session/sessions.ts index c3fa5e4..cbfb64e 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -20,12 +20,13 @@ import SnekTemplate from "../templates/snek/index"; // Contains SNEK tasks import SnekTasks from "../templates/snek/gql/tasks/index"; //> Interfaces -// Contains the interface for the apollo endpoint -import { ApolloEndpoint } from "../endpoints/index"; +// Contains the interface for the apollo and scraper endpoint +import { ApolloEndpoint, ScraperEndpoint } from "../endpoints/index"; // Contains basic session interfaces import { User } from "./index"; //> Config import Config from "../config.json"; +import { InstagramTasks } from "../templates/instagram"; //#endregion //#region > Classes @@ -141,6 +142,64 @@ class CookieSession extends Session { } } +class InstagramSession extends Session { + /* Define tasks */ + public tasks: InstagramTasks; + + /** + * Initializes a Instagram session. + * + * @constructor + * @author Nico Schett + * @param {string} sId A session name + * @param {string} token A instagram access token + * @param {Endpoint} ep A endpoint + * @param {SnekTemplate} template A template set + */ + constructor(sId: string, token: string, public ep: ScraperEndpoint) { + super(sId); + + this.tokenName = sId + "-" + this.tokenName; + + this.token = token; + this.tasks = new InstagramTasks(this); + } + + //> Methods + /** + * Refreshes the current set access token. + * + * @returns {Promise} The session token if set + */ + async upToDateToken(): Promise { + let token = super.token; + + /* Refresh token if there is none */ + if (!token) { + await this.refresh(); + + token = super.token; + } + + return token; + } + + /** + * Refreshes a session. + */ + async refresh() { + this.token = await this.tasks.refreshToken(); + } + + /** + * The runner allows to access every endpoint of the instagram api without + * caring about refreshing the access tokens. + */ + getRunner() { + return this.tasks.getScraper(); + } +} + /** @class A SNEK SubSession */ class SnekSession extends CookieSession { /* Define tasks */ @@ -302,7 +361,7 @@ class SnekSession extends CookieSession { //#endregion //#region > Exports -export { GithubSession, SnekSession }; +export { GithubSession, InstagramSession, SnekSession }; //#endregion /** diff --git a/src/templates/instagram/index.ts b/src/templates/instagram/index.ts new file mode 100644 index 0000000..40631b2 --- /dev/null +++ b/src/templates/instagram/index.ts @@ -0,0 +1,7 @@ +//#region > Imports +import InstagramTasks from "./tasks"; +//#endregion + +//#region > Exports +export { InstagramTasks }; +//#endregion diff --git a/src/templates/instagram/tasks.ts b/src/templates/instagram/tasks.ts new file mode 100644 index 0000000..eaa9f80 --- /dev/null +++ b/src/templates/instagram/tasks.ts @@ -0,0 +1,42 @@ +import Scraper from "../../endpoints/scraper"; +//> Sessions +// Contains the SNEK session +import { InstagramSession } from "../../session/sessions"; + +import * as urls from "./urls"; + +//#region > Classes +/** @class A Template with initializes all tasks */ +class InstagramTasks { + /** + * Initializes a InstagramSession. + * + * @constructor + * @author Nico Schett + * @param {string} session A session to initialize all corresponding tasks + */ + constructor(public session: InstagramSession) {} + + async getScraper() { + const scraper = new Scraper("https://graph.instagram.com", { + headers: { Authorization: `Bearer ${this.session.upToDateToken()}` }, + }); + + return scraper; + } + + async refreshToken() { + const scraper = new Scraper("https://graph.instagram.com", { + headers: { Authorization: `Bearer ${this.session.token}` }, + }); + + const res = await scraper.getJson<{ access_token: string }>( + urls.TOKEN_REFRESH_URI + ); + + return res.access_token; + } +} + +export default InstagramTasks; +//#endregion diff --git a/src/templates/instagram/urls.ts b/src/templates/instagram/urls.ts new file mode 100644 index 0000000..ad9f60f --- /dev/null +++ b/src/templates/instagram/urls.ts @@ -0,0 +1,7 @@ +/** + * Uris for instagram api access + * Ref: https://developers.facebook.com/docs/ + */ + +export const TOKEN_REFRESH_URI = + "/refresh_access_token?grant_type=ig_refresh_token"; From a8a23d32e72480f7d7bd7bdc288446928c59a95c Mon Sep 17 00:00:00 2001 From: schettn Date: Sat, 5 Sep 2020 15:09:25 +0200 Subject: [PATCH 32/50] Rename instagram uri to path The uris has been renamed to paths. --- src/templates/instagram/{urls.ts => paths.ts} | 2 +- src/templates/instagram/tasks.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/templates/instagram/{urls.ts => paths.ts} (80%) diff --git a/src/templates/instagram/urls.ts b/src/templates/instagram/paths.ts similarity index 80% rename from src/templates/instagram/urls.ts rename to src/templates/instagram/paths.ts index ad9f60f..acb1388 100644 --- a/src/templates/instagram/urls.ts +++ b/src/templates/instagram/paths.ts @@ -3,5 +3,5 @@ * Ref: https://developers.facebook.com/docs/ */ -export const TOKEN_REFRESH_URI = +export const TOKEN_REFRESH_PATH = "/refresh_access_token?grant_type=ig_refresh_token"; diff --git a/src/templates/instagram/tasks.ts b/src/templates/instagram/tasks.ts index eaa9f80..a57d103 100644 --- a/src/templates/instagram/tasks.ts +++ b/src/templates/instagram/tasks.ts @@ -2,8 +2,8 @@ import Scraper from "../../endpoints/scraper"; //> Sessions // Contains the SNEK session import { InstagramSession } from "../../session/sessions"; - -import * as urls from "./urls"; +//> Instagram Endpoint paths +import * as paths from "./paths"; //#region > Classes /** @class A Template with initializes all tasks */ @@ -31,7 +31,7 @@ class InstagramTasks { }); const res = await scraper.getJson<{ access_token: string }>( - urls.TOKEN_REFRESH_URI + paths.TOKEN_REFRESH_PATH ); return res.access_token; From 6b750335fcf70e37305f2705c77aebd89ad38d91 Mon Sep 17 00:00:00 2001 From: schettn Date: Sat, 5 Sep 2020 15:23:23 +0200 Subject: [PATCH 33/50] Optimise tasks and clients - All tasks which are not directly required by a related session have been removed. - The template classes have been removed completely. --- src/endpoints/index.ts | 6 +- src/index.ts | 55 ++++-- src/session/sessions.ts | 44 ++--- src/templates/index.ts | 28 --- src/templates/instagram/index.ts | 7 - src/templates/instagram/tasks.ts | 15 +- src/templates/snek/{gql => }/errors.ts | 6 +- src/templates/snek/gql/index.ts | 35 ---- src/templates/snek/gql/mutations/index.ts | 24 --- src/templates/snek/gql/mutations/user.ts | 61 ------ src/templates/snek/gql/queries/general.ts | 73 ------- src/templates/snek/gql/queries/index.ts | 24 --- src/templates/snek/gql/queries/user.ts | 82 -------- src/templates/snek/gql/tasks/auth.ts | 146 -------------- src/templates/snek/gql/tasks/general.ts | 113 ----------- src/templates/snek/gql/tasks/index.ts | 88 --------- src/templates/snek/gql/tasks/user.ts | 180 ------------------ src/templates/snek/index.ts | 20 -- .../jwtAuth.ts => mutations/auth.ts} | 0 src/templates/snek/queries/user.ts | 26 +++ src/templates/snek/tasks/auth.ts | 114 +++++++++++ src/templates/snek/tasks/index.ts | 61 ++++++ src/templates/snek/tasks/user.ts | 50 +++++ src/templates/snek/types.ts | 54 ++++++ 24 files changed, 371 insertions(+), 941 deletions(-) delete mode 100644 src/templates/index.ts delete mode 100644 src/templates/instagram/index.ts rename src/templates/snek/{gql => }/errors.ts (90%) delete mode 100644 src/templates/snek/gql/index.ts delete mode 100644 src/templates/snek/gql/mutations/index.ts delete mode 100644 src/templates/snek/gql/mutations/user.ts delete mode 100644 src/templates/snek/gql/queries/general.ts delete mode 100644 src/templates/snek/gql/queries/index.ts delete mode 100644 src/templates/snek/gql/queries/user.ts delete mode 100644 src/templates/snek/gql/tasks/auth.ts delete mode 100644 src/templates/snek/gql/tasks/general.ts delete mode 100644 src/templates/snek/gql/tasks/index.ts delete mode 100644 src/templates/snek/gql/tasks/user.ts delete mode 100644 src/templates/snek/index.ts rename src/templates/snek/{gql/mutations/jwtAuth.ts => mutations/auth.ts} (100%) create mode 100644 src/templates/snek/queries/user.ts create mode 100644 src/templates/snek/tasks/auth.ts create mode 100644 src/templates/snek/tasks/index.ts create mode 100644 src/templates/snek/tasks/user.ts create mode 100644 src/templates/snek/types.ts diff --git a/src/endpoints/index.ts b/src/endpoints/index.ts index 69a99a9..db52a76 100644 --- a/src/endpoints/index.ts +++ b/src/endpoints/index.ts @@ -75,21 +75,21 @@ interface ScraperEndpoint extends Endpoint { /** * GetJson: A method which gets json data from a specific url. * - * @param url A web url + * @param path Path to the endpoint * @returns {Promise} Json data in the given format */ getJson(url: string): Promise; /** * GetDom: A method which gets DOM data from a specific url. * - * @param url A web url + * @param path Path to the endpoint * @returns {Promise} A DOM Document */ getDom(url: string): Promise; /** * Post: A method to post data to a specific url. * - * @param {string} url A web url + * @param {string} path Path to the endpoint * @param data Data which is filled into the body of a post request * @returns {Promise} A DOM Document */ diff --git a/src/index.ts b/src/index.ts index 92c55e8..c051621 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,17 +4,16 @@ import Apollo from "./endpoints/apollo"; // Contains the scraper endpoint import Scraper from "./endpoints/scraper"; -//> Templates -// Contains the main template -import { MainTemplate } from "./templates/index"; //> Sessions // Contains the SNEK and github session -import { SnekSession, GithubSession } from "./session/sessions"; +import { + SnekSession, + GithubSession, + InstagramSession, +} from "./session/sessions"; //> Interfaces // Contains interfaces for scraper and apollo import { ScraperEndpoint, ApolloEndpoint } from "./endpoints/index"; -// Contains the interface for the main template -import { IMainTemplate } from "./templates/index"; //#endregion //#region > Interfaces @@ -64,7 +63,6 @@ class Client implements IClient { /** @class A client implementation for SNEK interaction */ class SnekClient extends Client { gql: ApolloEndpoint; - template: IMainTemplate; session: SnekSession; /** @@ -84,16 +82,14 @@ class SnekClient extends Client { ) { super({ type, url, headers }); - this.template = new MainTemplate(); this.gql = new Apollo(url, { headers }); - this.session = new SnekSession("snek", this.gql, this.template.snek); + this.session = new SnekSession("snek", this.gql); } } /** @class A client implementation for github interaction */ class GithubClient extends Client { gql: ApolloEndpoint; - template: IMainTemplate; session: GithubSession; /** @@ -113,9 +109,42 @@ class GithubClient extends Client { ) { super({ type, url, headers }); - this.template = new MainTemplate(); this.gql = new Apollo(url, { headers }); - this.session = new GithubSession("github", this.gql, this.template); + this.session = new GithubSession("github", this.gql); + } +} + +/** @class A client implementation for instagram interaction */ +class InstagramClient extends Client { + ep: ScraperEndpoint; + session: InstagramSession; + + /** + * Initializes a Github client. + * + * @constructor + * @author Nico Schett + * @param url The base URL the GithubClient should be working on. + * Default: "https://api.github.com/graphql". + * @param headers A object containing various request headers + * @param type A type description to differ between multiple instances + */ + constructor( + url: string = "https://api.github.com/graphql", + headers: { accessToken: string }, + type: string = "scraper" + ) { + super({ type, url, headers }); + + this.ep = new Scraper("https://graph.instagram.com", { + headers: { Authorization: `Bearer ${headers.accessToken}` }, + }); + + this.session = new InstagramSession( + "instagram", + headers.accessToken, + this.ep + ); } } @@ -148,7 +177,7 @@ class WebClient extends Client { //#endregion //#region > Exports -export { SnekClient, GithubClient, WebClient }; +export { SnekClient, GithubClient, InstagramClient, WebClient }; //#endregion /** diff --git a/src/session/sessions.ts b/src/session/sessions.ts index cbfb64e..ffaf09a 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -11,22 +11,19 @@ import Cookies from "js-cookie"; //> Session // Contains the base session import Session from "./index"; -//> Templates -// Contains the main template for the sessions -import { IMainTemplate } from "../templates/index"; -// Contains the SNEK template -import SnekTemplate from "../templates/snek/index"; //> Tasks // Contains SNEK tasks -import SnekTasks from "../templates/snek/gql/tasks/index"; +import SnekTasks from "../templates/snek/tasks/index"; +import InstagramTasks from "../templates/instagram/tasks"; //> Interfaces // Contains the interface for the apollo and scraper endpoint import { ApolloEndpoint, ScraperEndpoint } from "../endpoints/index"; // Contains basic session interfaces import { User } from "./index"; +// Contains the snek template types +import { TaskTypes } from "../templates/snek/types"; //> Config import Config from "../config.json"; -import { InstagramTasks } from "../templates/instagram"; //#endregion //#region > Classes @@ -39,14 +36,8 @@ class GithubSession extends Session { * @author Nico Schett * @param {string} sId A session name * @param {Endpoint} ep A endpoint - * @param {IMainTemplate} template A template set */ - constructor( - sId: string, - public ep: ApolloEndpoint, - public template: IMainTemplate - ) { - /** @todo Change template set to dedicated github template set */ + constructor(sId: string, public ep: ApolloEndpoint) { super(sId); } @@ -154,7 +145,6 @@ class InstagramSession extends Session { * @param {string} sId A session name * @param {string} token A instagram access token * @param {Endpoint} ep A endpoint - * @param {SnekTemplate} template A template set */ constructor(sId: string, token: string, public ep: ScraperEndpoint) { super(sId); @@ -196,7 +186,9 @@ class InstagramSession extends Session { * caring about refreshing the access tokens. */ getRunner() { - return this.tasks.getScraper(); + this.ep.headers = { Authorization: `Bearer ${this.upToDateToken()}` }; + + return this.ep; } } @@ -212,13 +204,8 @@ class SnekSession extends CookieSession { * @author Nico Schett * @param {string} sId A session name * @param {Endpoint} ep A endpoint - * @param {SnekTemplate} template A template set */ - constructor( - sId: string, - public ep: ApolloEndpoint, - public template: SnekTemplate - ) { + constructor(sId: string, public ep: ApolloEndpoint) { super(sId); this.tokenName = sId + "-" + this.tokenName; @@ -277,11 +264,12 @@ class SnekSession extends CookieSession { if (!user) { /* Authenticate anonymous user */ - authData = (await this.tasks.auth.anon()).data?.auth; + + authData = (await this.tasks.set.auth.anon()).data?.auth; anonymous = true; } else { /* Authenticate real user */ - authData = (await this.tasks.auth.nonanon(user)).data?.auth; + authData = (await this.tasks.set.auth.nonanon(user)).data?.auth; } /* Set tokens */ @@ -292,7 +280,7 @@ class SnekSession extends CookieSession { } /* Get user data */ - const userData = (await this.tasks.user.whoami()).data?.whoami; + const userData = (await this.tasks.set.user.whoami()).data?.whoami; if (userData?.username === Config.anonUser.username) { anonymous = true; @@ -310,7 +298,7 @@ class SnekSession extends CookieSession { async refresh() { if (!this.token) { if (this.refreshToken) { - let response = await this.tasks.auth.refresh(); + let response = await this.tasks.set.auth.refresh(); this.token = response.data?.refresh.token; this.refreshToken = response.data?.refresh.refreshToken; @@ -329,7 +317,7 @@ class SnekSession extends CookieSession { async end() { /* Revoke token if it is set */ if (this.refreshToken !== "") { - let response = await this.tasks.auth.revoke(); + let response = await this.tasks.set.auth.revoke(); //#DEBUG TSID1 //console.log("TID-1(REVOKE)", response.data?.revoke.revoked); @@ -350,7 +338,7 @@ class SnekSession extends CookieSession { * are set by default! * When no type is specified, query is set as default. */ - async customTask(type: string, data: DocumentNode, variables: object) { + async runner(type: TaskTypes, data: DocumentNode, variables: object) { return this.tasks.run(type, data, { ...variables, token: await this.upToDateToken(), diff --git a/src/templates/index.ts b/src/templates/index.ts deleted file mode 100644 index c8b6f55..0000000 --- a/src/templates/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -//#region > Imports -//> SNEK Templates -import SnekTemplate from "./snek"; -//#endregion - -//#region > Interfaces -/** @interface IMainTemplate defines the structure of the base templates */ -interface IMainTemplate { - snek: SnekTemplate; -} -//#endregion - -//#region > Classes -/** @class A Template which initializes all SubTemplates */ -class MainTemplate implements IMainTemplate { - public snek = new SnekTemplate(); -} -//#endregion - -//#region > Exports -export type { IMainTemplate }; -export { MainTemplate }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/instagram/index.ts b/src/templates/instagram/index.ts deleted file mode 100644 index 40631b2..0000000 --- a/src/templates/instagram/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -//#region > Imports -import InstagramTasks from "./tasks"; -//#endregion - -//#region > Exports -export { InstagramTasks }; -//#endregion diff --git a/src/templates/instagram/tasks.ts b/src/templates/instagram/tasks.ts index a57d103..ac2a020 100644 --- a/src/templates/instagram/tasks.ts +++ b/src/templates/instagram/tasks.ts @@ -1,4 +1,3 @@ -import Scraper from "../../endpoints/scraper"; //> Sessions // Contains the SNEK session import { InstagramSession } from "../../session/sessions"; @@ -17,20 +16,10 @@ class InstagramTasks { */ constructor(public session: InstagramSession) {} - async getScraper() { - const scraper = new Scraper("https://graph.instagram.com", { - headers: { Authorization: `Bearer ${this.session.upToDateToken()}` }, - }); - - return scraper; - } - async refreshToken() { - const scraper = new Scraper("https://graph.instagram.com", { - headers: { Authorization: `Bearer ${this.session.token}` }, - }); + const runner = this.session.getRunner(); - const res = await scraper.getJson<{ access_token: string }>( + const res = await runner.getJson<{ access_token: string }>( paths.TOKEN_REFRESH_PATH ); diff --git a/src/templates/snek/gql/errors.ts b/src/templates/snek/errors.ts similarity index 90% rename from src/templates/snek/gql/errors.ts rename to src/templates/snek/errors.ts index 5e8fa5d..ce24e25 100644 --- a/src/templates/snek/gql/errors.ts +++ b/src/templates/snek/errors.ts @@ -1,10 +1,10 @@ //#region > Imports //> Sessions // Contains the SNEK session -import { SnekSession } from "../../../session/sessions"; +import { SnekSession } from "../../session/sessions"; //> Types // Contains the type declarations for Apollo results -import { ApolloResult } from "./index"; +import * as types from "./types"; //#endregion //#region > Classes @@ -25,7 +25,7 @@ class TaskError { * @param {Response} response A SNEK-client graphql response * @returns {boolean} "false" if an error occurs. Otherwise "true" */ - handleErrors(response: ApolloResult): boolean { + handleErrors(response: types.ApolloResult): boolean { const errors = response.errors; if (errors && errors.length > 0) { diff --git a/src/templates/snek/gql/index.ts b/src/templates/snek/gql/index.ts deleted file mode 100644 index d9ee2a0..0000000 --- a/src/templates/snek/gql/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -//#region > Imports -//> Queries -import { SnekGqlQuery } from "./queries/index"; -//> Mutations -import { SnekGqlMutation } from "./mutations/index"; -//> Types -// Contains the type declarations for Apollo results -import { ApolloResult } from "../../../endpoints/index"; -//#endregion - -//#region > Interfaces -/** @interface SnekGqlTemplate defines the structure for the gql template */ -interface SnekGqlTemplate { - queries: SnekGqlQuery; - mutations: SnekGqlMutation; -} -//#endregion - -//#region > Classes -/** @class A Template which initializes all SubTemplates */ -class SnekGql { - public queries = new SnekGqlQuery(); - public mutations = new SnekGqlMutation(); -} -//#endregion - -//#region > Exports -export type { SnekGqlTemplate, ApolloResult }; -export default SnekGql; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/mutations/index.ts b/src/templates/snek/gql/mutations/index.ts deleted file mode 100644 index c03cda1..0000000 --- a/src/templates/snek/gql/mutations/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -//#region > Imports -//> Mutations -// Contains the jwtAuth mutations -import * as _jwtAuth from "./jwtAuth"; -// Contains the user mutations -import * as _user from "./user"; -//#endregion - -//#region > Classes -/** @class A Template which initializes all mutations */ -class SnekGqlMutation { - public jwtAuth = _jwtAuth; - public user = _user; -} -//#endregion - -//#region > Exports -export { SnekGqlMutation }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/mutations/user.ts b/src/templates/snek/gql/mutations/user.ts deleted file mode 100644 index 7e5f9a1..0000000 --- a/src/templates/snek/gql/mutations/user.ts +++ /dev/null @@ -1,61 +0,0 @@ -//#region > Imports -//#PACKAGE "graphql-tag" -//## npm install "graphql-tag"@2.10.3 -// Contains a gql tag for wrapping queries -import gql from "graphql-tag"; -//#endregion - -//#region > Queries -/** - * User registration. - * - * @param {string} token A users JWT - * @param {string} values Registration parameters defined by registration page - * @returns {string} Registration conformation - * @description A mutation to register a user by providing values and a valid - * JWT. This could be a JWT of the anonymous user. - */ -const registration = gql` - mutation registration($token: String!, $values: GenericScalar!) { - registration: personRegistrationFormPage( - url: "/person-registration-form/" - token: $token - values: $values - ) { - result - errors { - name - errors - } - } - } -`; - -/** - * Cache user. - * - * @param {string} token A users JWT - * @param {string} platformData A serialized JSON object of all generated user - * data. - * @returns {string} PlatformData of a user - * @description A mutation to cache user information server side - */ -const cache = gql` - mutation cache($token: String!, $personName: String!, $cache: String!) { - cache: cacheUser(token: $token, personName: $personName, cache: $cache) { - personPage { - id - } - } - } -`; -//#endregion - -//#region > Exports -export { registration, cache }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/queries/general.ts b/src/templates/snek/gql/queries/general.ts deleted file mode 100644 index 37eff20..0000000 --- a/src/templates/snek/gql/queries/general.ts +++ /dev/null @@ -1,73 +0,0 @@ -//#region > Imports -//#PACKAGE "graphql-tag" -//## npm install "graphql-tag"@2.10.3 -// Contains a gql tag for wrapping queries -import gql from "graphql-tag"; -//#endregion - -//#region > Queries -/** - * List of GitLab server. - * - * @param {string} JWT A users JWT - * @returns {string} A serialized JSON object with a list of GitLab server - * @description A query to fetch all available GitLab server - */ -const gitlabServer = gql` - query gitLabServers($token: String!) { - page(slug: "person-registration-form", token: $token) { - ... on PersonRegistrationFormPage { - supportedGitlabs { - ... on GitlabServer { - id - organisation - domain - } - } - } - } - } -`; - -/** - * List of page urls. - * - * @param {string} JWT A users JWT - * @returns {string} A serialized JSON object with a list of all page urls - * @description A query to fetch all pages urls - */ -const allPageUrls = gql` - query pages($token: String!) { - pages(token: $token) { - urlPath - } - } -`; - -/** - * List of user page urls. - * - * @param {string} JWT A users JWT - * @returns {string} A serialized JSON object with a list of all page urls - * @description A query to fetch all user page urls - */ -const allUserPageUrls = gql` - query userPages($token: String!) { - page(slug: "people", token: $token) { - children { - slug - title - } - } - } -`; -//#endregion - -//#region > Exports -export { gitlabServer, allPageUrls, allUserPageUrls }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/queries/index.ts b/src/templates/snek/gql/queries/index.ts deleted file mode 100644 index df1bca7..0000000 --- a/src/templates/snek/gql/queries/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -//#region > Imports -//> Queries -// Contains the general queries -import * as _general from "./general"; -// Contains the user queries -import * as _user from "./user"; -//#endregion - -//#region > Classes -/** @class A template which initializes all SubTemplates */ -class SnekGqlQuery { - public general = _general; - public user = _user; -} -//#endregion - -//#region > Exports -export { SnekGqlQuery }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/queries/user.ts b/src/templates/snek/gql/queries/user.ts deleted file mode 100644 index 2b680c1..0000000 --- a/src/templates/snek/gql/queries/user.ts +++ /dev/null @@ -1,82 +0,0 @@ -//#region > Imports -//#PACKAGE "graphql-tag" -//## npm install "graphql-tag"@2.10.3 -// Contains a gql tag for wrapping queries -import gql from "graphql-tag"; -//#endregion - -//#region > Queries -/** - * Whoami. - * - * @param {string} token A users JWT - * @returns {string} A username - * @description A query to fetch the username of the according token - */ -const whoami = gql` - query whoami($token: String!) { - whoami: me(token: $token) { - username - } - } -`; - -/** - * Get user profile. - * - * @param {string} slug Slug: > - * @param {string} token A users JWT - * @returns {string} A profile page of a user - * @description A query to fetch profile data - */ -const profile = gql` - query profile($slug: String!, $token: String!) { - page(slug: $slug, token: $token) { - ... on PersonFormPage { - personName: title - firstName - lastName - email - platformData: cache - sources - person { - cache - sources - } - tids - bids - follows { - personName: slug - } - followedBy { - personName: slug - } - likes { - personName: slug - } - likedBy { - personName: slug - } - achievements { - id - title - image { - src - imageSourceUrl - } - points - } - } - } - } -`; -//#endregion - -//#region > Exports -export { whoami, profile }; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/tasks/auth.ts b/src/templates/snek/gql/tasks/auth.ts deleted file mode 100644 index 1c779b9..0000000 --- a/src/templates/snek/gql/tasks/auth.ts +++ /dev/null @@ -1,146 +0,0 @@ -//#region > Imports -//> Parent Task -// Contains the SNEK parent task -import SnekTasks from "./index"; -//> Interfaces -// Contains the user interface for authentication -import { User } from "../../../../session"; -//> Types -// Contains the type declarations for Apollo results -import { ApolloResult } from "./index"; -//> Config -import Config from "../../../../config.json"; -//#endregion - -//#region > Interfaces -/** - * @interface AuthData defines the structure of the authentication result data - */ -interface AuthData { - auth: { - token: string; - refreshToken: string; - user: { - username: string; - }; - }; -} - -/** - * @interface RefreshData defines the structure of the refresh result data - */ -interface RefreshData { - refresh: { - payload: string; - token: string; - refreshToken: string; - }; -} - -/** - * @interface RevokeData defines the structure of the revoke result data - */ -interface RevokeData { - revoke: { - revoked: string; - }; -} -//#endregion - -//#region > Classes -/** @class A set of session aware tasks */ -class SnekGqlAuthTasks { - /** - * Initializes session aware SnekGqlAuth Task. - * - * @constructor - * @author Nico Schett - * @param {string} session A session for the tasks - */ - constructor(private parent: SnekTasks) {} - - /** - * Anonymous login. - * - * @returns {Promise>} Authentication data - * @description Authenticates the anonymous user to obtain a JWT - */ - async anon(): Promise> { - const response = await this.parent.run( - "mutation", - this.parent.template.mutations.jwtAuth.auth, - { - username: Config.anonUser.username, - password: Config.anonUser.password, - } - ); - - return response; - } - - /** - * User login. - * - * @param {string} user A User defined by username and password - * @returns {Promise>} Authentication data - * @description Authenticates a real user to obtain a JWT - */ - async nonanon(user: User): Promise> { - const response = await this.parent.run( - "mutation", - this.parent.template.mutations.jwtAuth.auth, - { - username: user.username, - password: user.password, - } - ); - - return response; - } - - /** - * Refresh a token. - * - * @param {string} user A User defined by username and password - * @returns {Promise>} Refresh data - */ - async refresh(): Promise> { - const response = await this.parent.run( - "mutation", - this.parent.template.mutations.jwtAuth.refresh, - { - refreshToken: this.parent.session.refreshToken, - } - ); - - return response; - } - - /** - * Revoke a token. - * - * @param {string} user A User defined by username and password - * @returns {Promise>} Revoke acknowledgment - */ - async revoke(): Promise> { - const response = await this.parent.run( - "mutation", - this.parent.template.mutations.jwtAuth.revoke, - { - refreshToken: this.parent.session.refreshToken, - } - ); - - return response; - } -} -//#endregion - -//#region > Exports -export default SnekGqlAuthTasks; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/tasks/general.ts b/src/templates/snek/gql/tasks/general.ts deleted file mode 100644 index c1db3f1..0000000 --- a/src/templates/snek/gql/tasks/general.ts +++ /dev/null @@ -1,113 +0,0 @@ -//#region > Imports -//> Parent Task -// Contains the SNEK parent task -import SnekTasks from "./index"; -//> Types -// Contains the type declarations for Apollo results -import { ApolloResult } from "./index"; -//#endregion - -//#region > Interfaces -/** - * @interface GitlabServerData defines the structure of the Gitlab server result - * data. - */ -interface GitlabServerData { - page: { - supportedGitlabs: { id: string; organisation: string; domain: string; }[]; - }; -} - -/** - * @interface AllPageUrlData defines the structure of the all page url result - * data. - */ -interface AllPageUrlData { - pages: { urlPath: string }[]; -} - -/** - * @interface AllUserPageUrlsData defines the types of the response of the - * allUserPageUrls query. - */ -interface AllUserPageUrlsData { - page: { children: { url: string }[] }; -} -//#endregion - -//#region > Classes -/** @class A set of session aware tasks */ -class SnekGqlGeneralTasks { - /** - * Initializes SnekGqlGeneral tasks. - * @constructor - * @author Nico Schett - * @param {string} parent The parent task - */ - constructor(private parent: SnekTasks) { } - - /** - * Gitlab Server. - * - * @returns {Promise>} A list of Gitlab server - * @description Get all Gitlab servers which are registered in the SNEK-engine - */ - async gitlabServer(): Promise> { - const response = await this.parent.run( - "query", - this.parent.template.queries.general.gitlabServer, - { - token: await this.parent.session.upToDateToken(), - } - ); - - return response; - } - - /** - * All page url. - * - * @returns {Promise>} A list of all page urls - * @description Get a list of all pages - */ - async allPageUrls(): Promise> { - const response = await this.parent.run( - "query", - this.parent.template.queries.general.allPageUrls, - { - token: await this.parent.session.upToDateToken(), - } - ); - - return response; - } - - /** - * All user page urls. - * - * @returns {Promise>} A list of all user - * page urls. - * @description Get a list of all pages - */ - async allUserPageUrls(): Promise> { - const response = await this.parent.run( - "query", - this.parent.template.queries.general.allUserPageUrls, - { - token: await this.parent.session.upToDateToken(), - } - ); - - return response; - } -} -//#endregion - -//#region > Exports -export default SnekGqlGeneralTasks; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/tasks/index.ts b/src/templates/snek/gql/tasks/index.ts deleted file mode 100644 index f929601..0000000 --- a/src/templates/snek/gql/tasks/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -//#region > Imports -//#PACKAGE "graphql" -//## npm install "graphql"@14.6.0 -// Contains the interface for gql queries, mutations and subscriptions -import { DocumentNode } from "graphql"; - -//> Sessions -// Contains the SNEK session -import { SnekSession } from "../../../../session/sessions"; -//> Tasks -// Contains the SnekGqlAuth task -import SnekGqlAuthTasks from "./auth"; -// Contains the SnekGqlGeneral task -import SnekGqlGeneralTasks from "./general"; -// Contains the SnekGqlUser task -import SnekGqlUserTasks from "./user"; -// Contains error handling for tasks -import { TaskError } from "../errors"; -//> Interfaces -// Contains the snek template -import { SnekGqlTemplate } from "../index"; -//> Types -// Contains the type declarations for Apollo results -import { ApolloResult } from "../index"; -//#endregion - -//#region > Classes -/** @class A Template with initializes all tasks */ -class SnekTasks extends TaskError { - public template!: SnekGqlTemplate; - public general!: SnekGqlGeneralTasks; - public auth!: SnekGqlAuthTasks; - public user!: SnekGqlUserTasks; - - /** - * Initializes a SnekSession. - * - * @constructor - * @author Nico Schett - * @param {string} session A session to initialize all corresponding tasks - */ - constructor(session: SnekSession) { - super(session); - - this.template = session.template.snekGql; - - /* Init tasks */ - this.general = new SnekGqlGeneralTasks(this); - this.auth = new SnekGqlAuthTasks(this); - this.user = new SnekGqlUserTasks(this); - } - - async run( - type: string, - query: DocumentNode, - variables: object - ): Promise> { - let response: ApolloResult; - - if (type === "query") { - response = await this.session.ep.sendQuery(query, variables); - } else if (type === "mutation") { - response = await this.session.ep.sendMutation(query, variables); - } else { - console.warn( - "No query type specified! Please re-check." + - "Selecting type 'query' as default" - ); - - response = await this.session.ep.sendQuery(query, variables); - } - - this.handleErrors(response); - - return response; - } -} -//#endregion - -//#region > Exports -export type { ApolloResult }; -export default SnekTasks; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/tasks/user.ts b/src/templates/snek/gql/tasks/user.ts deleted file mode 100644 index e61d32e..0000000 --- a/src/templates/snek/gql/tasks/user.ts +++ /dev/null @@ -1,180 +0,0 @@ -//#region > Imports -//> Parent Task -// Contains the SNEK parent task -import SnekTasks from "./index"; -//> Types -// Contains the type declarations for Apollo results -import { ApolloResult } from "./index"; -//#endregion - -//#region > Interfaces -/** - * @interface RegistrationData defines the structure of the registration result - * data. - */ -interface RegistrationData { - result: string; -} - -/** - * @interface CacheData defines the structure of the cache result - * data. - */ -interface CacheData { - user: { - id: number; - }; -} - -/** - * @interface ProfileData defines the structure of the profile result - * data. - */ -interface ProfileData { - profile: { - profileName: string; - firstName: string; - lastName: string; - email: string; - platformData: string; - sources: string; - bids: string; - tids: string; - person: { - cache: string; - sources: string; - }; - follows: { - personName: string; - }[]; - followedBy: { - personName: string; - }[]; - likes: { - personName: string; - }[]; - likedBy: { - personName: string; - }[]; - achievements: { - id: string; - title: string; - image: { - src: string; - imageSourceUrl: string; - }; - points: string; - }; - }; -} - -/** - * @interface WhoamiData defines the structure of the whoami result - * data. - */ -interface WhoamiData { - whoami: { - username: string; - }; -} -//#endregion - -//#region > Classes -/** @class A set of session aware tasks */ -class SnekGqlUserTasks { - /** - * @constructor - * @author Nico Schett - * @param {string} parent The parent task - */ - constructor(private parent: SnekTasks) {} - - /** - * Register a user. - * - * @param {object} values Registration parameters like username, email,... - * @returns {Promise>} Registration data - */ - async registration(values: object): Promise> { - const response = await this.parent.run( - "mutation", - this.parent.template.mutations.user.registration, - { - token: await this.parent.session.upToDateToken(), - values, - } - ); - - return response; - } - - /** - * Cache a user. - * - * @param {string} personName The name of a users person page - * @param {string} cache A serialized JSON object to be cached - * @returns {Promise>} Cache data - */ - async cache( - personName: string, - cache: string - ): Promise> { - const response = await this.parent.run( - "mutation", - this.parent.template.mutations.user.cache, - { - token: await this.parent.session.upToDateToken(), - personName, - cache, - } - ); - - return response; - } - - /** - * Get profile. - * - * @param {string} personName personName: - * @returns {Promise>} The profile page of a user - */ - async profile(personName: string): Promise> { - const response = await this.parent.run( - "query", - this.parent.template.queries.user.profile, - { - slug: `p-${personName}`, - token: await this.parent.session.upToDateToken(), - } - ); - - return response; - } - - /** - * Whoami check. - * - * @returns {Promise>} User data - */ - async whoami(): Promise> { - const response = await this.parent.run( - "query", - this.parent.template.queries.user.whoami, - { - token: await this.parent.session.upToDateToken(), - } - ); - - return response; - } -} -//#endregion - -//#region > Exports -export default SnekGqlUserTasks; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/index.ts b/src/templates/snek/index.ts deleted file mode 100644 index 22e195a..0000000 --- a/src/templates/snek/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -//#region > Imports -//> SNEK Gql Tools -import SnekGql from "./gql"; -//#endregion - -//#region > Classes -/** @class A Template which initializes all SubTemplates */ -class SnekTemplate { - public snekGql = new SnekGql(); -} -//#endregion - -//#region > Exports -export default SnekTemplate; -//#endregion - -/** - * SPDX-License-Identifier: (EUPL-1.2) - * Copyright © Simon Prast - */ diff --git a/src/templates/snek/gql/mutations/jwtAuth.ts b/src/templates/snek/mutations/auth.ts similarity index 100% rename from src/templates/snek/gql/mutations/jwtAuth.ts rename to src/templates/snek/mutations/auth.ts diff --git a/src/templates/snek/queries/user.ts b/src/templates/snek/queries/user.ts new file mode 100644 index 0000000..b8fd6d7 --- /dev/null +++ b/src/templates/snek/queries/user.ts @@ -0,0 +1,26 @@ +//#region > Imports +//#PACKAGE "graphql-tag" +// Contains a gql tag for wrapping queries +import gql from "graphql-tag"; +//#endregion + +//#region > Queries +/** + * Whoami. + * + * @param {string} token A users JWT + * @returns {string} A username + * @description A query to fetch the username of the according token + */ +const whoami = gql` + query whoami($token: String!) { + whoami: me(token: $token) { + username + } + } +`; +//#endregion + +//#region > Exports +export { whoami }; +//#endregion diff --git a/src/templates/snek/tasks/auth.ts b/src/templates/snek/tasks/auth.ts new file mode 100644 index 0000000..65f8b83 --- /dev/null +++ b/src/templates/snek/tasks/auth.ts @@ -0,0 +1,114 @@ +//#region > Imports +//> Parent Task +// Contains the SNEK parent task +import MainTask from "./index"; +//> Types +// Contains the graphql response types +import { + User, + ApolloResult, + GraphQLAuthentication, + GraphQLRefresh, + GraphQLRevoke, +} from "../types"; +//> Config +import Config from "../../../config.json"; +//#endregion + +//#region > Classes +/** @class A set of session aware tasks */ +class AuthTask { + /** + * Initializes session aware SnekGqlAuth Task. + * + * @constructor + * @author Nico Schett + * @param {string} session A session for the tasks + */ + constructor(private parent: MainTask) {} + + /** + * Anonymous login. + * + * @returns {Promise>} Authentication data + * @description Authenticates the anonymous user to obtain a JWT + */ + async anon(): Promise> { + const response = await this.parent.run( + "mutation", + this.parent.mutations.jwtAuth.auth, + { + username: Config.anonUser.username, + password: Config.anonUser.password, + } + ); + + return response; + } + + /** + * User login. + * + * @param {string} user A User defined by username and password + * @returns {Promise>} Authentication data. + * @description Authenticates a real user to obtain a JWT + */ + async nonanon(user: User): Promise> { + const response = await this.parent.run( + "mutation", + this.parent.mutations.jwtAuth.auth, + { + username: user.username, + password: user.password, + } + ); + + return response; + } + + /** + * Refresh a token. + * + * @param {string} user A User defined by username and password + * @returns {Promise>} Refresh data + */ + async refresh(): Promise> { + const response = await this.parent.run( + "mutation", + this.parent.mutations.jwtAuth.refresh, + { + refreshToken: this.parent.session.refreshToken, + } + ); + + return response; + } + + /** + * Revoke a token. + * + * @param {string} user A User defined by username and password + * @returns {Promise>} Revoke acknowledgment + */ + async revoke(): Promise> { + const response = await this.parent.run( + "mutation", + this.parent.mutations.jwtAuth.revoke, + { + refreshToken: this.parent.session.refreshToken, + } + ); + + return response; + } +} +//#endregion + +//#region > Exports +export default AuthTask; +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © Simon Prast + */ diff --git a/src/templates/snek/tasks/index.ts b/src/templates/snek/tasks/index.ts new file mode 100644 index 0000000..66c37a7 --- /dev/null +++ b/src/templates/snek/tasks/index.ts @@ -0,0 +1,61 @@ +//#region > Imports +//#PACKAGE "graphql" +// Contains the interface for gql queries, mutations and subscriptions +import { DocumentNode } from "graphql"; + +//> Mutations +import * as mutationsAuth from "../mutations/auth"; +//> Queries +import * as queriesUser from "../queries/user"; +//> Types +// Contains the graphql response types +import { ApolloResult, TaskTypes } from "../types"; +// Contains error handling for tasks +import { TaskError } from "../errors"; +import AuthTask from "./auth"; +import UserTask from "./user"; + +class MainTask extends TaskError { + public mutations: { jwtAuth: typeof mutationsAuth } = { + jwtAuth: require("../mutations/auth"), + }; + public queries: { user: typeof queriesUser } = { + user: require("../queries/user"), + }; + public set = { + auth: new AuthTask(this), + user: new UserTask(this), + }; + + async run( + type: TaskTypes, + query: DocumentNode, + variables: { [key: string]: any } + ): Promise> { + let response: ApolloResult; + + if (type === "query") { + response = await this.session.ep.sendQuery(query, variables); + } else if (type === "mutation") { + response = await this.session.ep.sendMutation(query, variables); + } else { + console.warn( + "No query type specified! Please re-check." + + "Selecting type 'query' as default" + ); + response = await this.session.ep.sendQuery(query, variables); + } + + if (this.handleErrors(response)) { + await this.session.refresh(); + + return this.run(type, query, variables); + } + + return response; + } +} + +//#region > Exports +export default MainTask; +//#endregion diff --git a/src/templates/snek/tasks/user.ts b/src/templates/snek/tasks/user.ts new file mode 100644 index 0000000..e7df478 --- /dev/null +++ b/src/templates/snek/tasks/user.ts @@ -0,0 +1,50 @@ +//#region > Imports +//> Parent Task +// Contains the SNEK parent task +import MainTask from "./index"; +//> Types +// Contains the graphql response types +import { ApolloResult, GraphQLWhoami } from "../types"; +//#endregion + +//#region > Classes +/** @class A set of session aware tasks */ +//#region > Classes +/** @class A set of session aware Tasks */ +class UserTasks { + /** + * Creates an instance of a SessionTasks. + * + * @constructor + * @author Nico Schett + * @param {string} session A session for the tasks + */ + constructor(private parent: MainTask) {} + + /** + * Whoami check + * + * @returns {Promise>} User data. + */ + async whoami(): Promise> { + const response = await this.parent.run( + "query", + this.parent.queries.user.whoami, + { + token: await this.parent.session.upToDateToken(), + } + ); + + return response; + } +} +//#endregion + +//#region > Exports +export default UserTasks; +//#endregion + +/** + * SPDX-License-Identifier: (EUPL-1.2) + * Copyright © Simon Prast + */ diff --git a/src/templates/snek/types.ts b/src/templates/snek/types.ts new file mode 100644 index 0000000..17637e7 --- /dev/null +++ b/src/templates/snek/types.ts @@ -0,0 +1,54 @@ +/** + * All types + */ + +export { ApolloResult } from "../../endpoints/index"; +export { User } from "../../session"; + +export type TaskTypes = "query" | "mutation"; +/** + * All graphql response types for authentication related requests. + */ + +//#region > Interfaces +/** + * @interface GraphQLAuthentication defines the structure of the authentication + * result data. + */ +export interface GraphQLAuthentication { + auth: { + token: string; + refreshToken: string; + user: { + username: string; + }; + }; +} + +/** + * @interface GraphQLRefresh defines the structure of the refresh + * result data. + */ +export interface GraphQLRefresh { + refresh: { + payload: string; + token: string; + refreshToken: string; + }; +} + +/** + * @interface GraphQLRevoke defines the structure of the revoke + * result data. + */ +export interface GraphQLRevoke { + revoke: { + revoked: string; + }; +} + +/** @interface GraphQLWhoami defines the structure of a whoami data. */ +export interface GraphQLWhoami { + whoami: { username: string }; +} +//#endregion From 4de7dcca6b6b64c77ce4d8ce156e20e5a69adb68 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 7 Sep 2020 00:37:47 +0200 Subject: [PATCH 34/50] Support more HTTP methods A new fetch method has been implemented to support more HTTP methods like GET, POST, PUT, PATCH and DELETE. --- src/endpoints/index.ts | 46 ++++++++++++++++++++ src/endpoints/scraper.ts | 93 +++++++++++++++++++++++++++++++++------- 2 files changed, 123 insertions(+), 16 deletions(-) diff --git a/src/endpoints/index.ts b/src/endpoints/index.ts index db52a76..7ab7ee1 100644 --- a/src/endpoints/index.ts +++ b/src/endpoints/index.ts @@ -106,6 +106,52 @@ interface ScraperEndpoint extends Endpoint { | null | undefined ): Promise; + /** + * Send fetch request to a endpoint and get the respective result. + * + * @param {string} path Path to the endpoint. Specify it like "/foo/bar". + * The correct placement of the slashes is essential! + * @param {"GET" | "POST" | "PUT" | "PATCH" | "DELETE"} type HTTP methods + * @param data Data which is filled into the body of a post request + * @returns {Promise} A DOM Document + */ + fetch( + path: string, + type: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", + data?: + | string + | Blob + | ArrayBufferView + | ArrayBuffer + | FormData + | URLSearchParams + | ReadableStream + | null + | undefined + ): Promise; + /** + * Send fetch request to a endpoint and get the respective JSON result. + * + * @param {string} path Path to the endpoint. Specify it like "/foo/bar". + * The correct placement of the slashes is essential! + * @param {"GET" | "POST" | "PUT" | "PATCH" | "DELETE"} type HTTP methods + * @param data Data which is filled into the body of a post request + * @returns {Promise} A DOM Document + */ + fetchJson( + path: string, + type: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", + data?: + | string + | Blob + | ArrayBufferView + | ArrayBuffer + | FormData + | URLSearchParams + | ReadableStream + | null + | undefined + ): Promise; } //#endregion diff --git a/src/endpoints/scraper.ts b/src/endpoints/scraper.ts index c239b70..4162ab9 100644 --- a/src/endpoints/scraper.ts +++ b/src/endpoints/scraper.ts @@ -47,6 +47,7 @@ class Scraper implements ScraperEndpoint { * @returns {T} JSON object passed to given structure */ async getJson(path: string): Promise { + console.log("HEADERS", this.headers); return fetch(this.url + path, { headers: { ...this.headers, @@ -69,22 +70,9 @@ class Scraper implements ScraperEndpoint { * @returns {object} DOM object */ async getDom(path: string): Promise { - return fetch(this.url + path, { - headers: { - ...this.headers, - }, - }) - .then((response) => { - if (!response.ok) { - //#ERROR - throw new Error(response.statusText); - } - - return response.text(); - }) - .then((text) => { - return new DOMParser().parseFromString(text, "text/html"); - }); + const text = await (await this.fetch(path, "GET")).text(); + + return new DOMParser().parseFromString(text, "text/html"); } /** @@ -123,7 +111,80 @@ class Scraper implements ScraperEndpoint { return response.json().then((data) => data as T); }); } + + /** + * Send fetch request to a endpoint and get the respective result. + * + * @param {string} path Path to the endpoint. Specify it like "/foo/bar". + * The correct placement of the slashes is essential! + * @param {"GET" | "POST" | "PUT" | "PATCH" | "DELETE"} type HTTP methods + * @param data Data which is filled into the body of a post request + * @returns {Promise} A DOM Document + */ + async fetch( + path: string, + type: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", + data?: + | string + | Blob + | ArrayBufferView + | ArrayBuffer + | FormData + | URLSearchParams + | ReadableStream + | null + | undefined + ): Promise { + return fetch(this.url + path, { + method: type, + body: data, + headers: { + ...this.headers, + }, + }).then(async (response) => { + if (!response.ok) { + //#ERROR + throw new Error(response.statusText); + } + + return response; + }); + } + + /** + * Send fetch request to a endpoint and get the respective JSON result. + * + * @param {string} path Path to the endpoint. Specify it like "/foo/bar". + * The correct placement of the slashes is essential! + * @param {"GET" | "POST" | "PUT" | "PATCH" | "DELETE"} type HTTP methods + * @param data Data which is filled into the body of a post request + * @returns {Promise} A DOM Document + */ + async fetchJson( + path: string, + type: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", + data?: + | string + | Blob + | ArrayBufferView + | ArrayBuffer + | FormData + | URLSearchParams + | ReadableStream + | null + | undefined + ): Promise { + return this.fetch(path, type, data).then(async (response) => { + if (!response.ok) { + //#ERROR + throw new Error(response.statusText); + } + + return response.json().then((data) => data as T); + }); + } } + //#endregion //#region > Exports From 9d800f2b1ffaea168829a34bd934f6fa8369c999 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 7 Sep 2020 00:44:07 +0200 Subject: [PATCH 35/50] Fix invalid up to date token The method was not correctly awaited and therefore returned a promise instead of a token. Also the handleErrors method lead to a loop, this has been fixed now by only calling this.run() when a token error occurs. --- src/session/sessions.ts | 4 ++-- src/templates/instagram/tasks.ts | 2 +- src/templates/snek/errors.ts | 8 +++++--- src/templates/snek/tasks/index.ts | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/session/sessions.ts b/src/session/sessions.ts index ffaf09a..a1da18a 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -185,8 +185,8 @@ class InstagramSession extends Session { * The runner allows to access every endpoint of the instagram api without * caring about refreshing the access tokens. */ - getRunner() { - this.ep.headers = { Authorization: `Bearer ${this.upToDateToken()}` }; + async getRunner() { + this.ep.headers = { Authorization: `Bearer ${await this.upToDateToken()}` }; return this.ep; } diff --git a/src/templates/instagram/tasks.ts b/src/templates/instagram/tasks.ts index ac2a020..0aec17d 100644 --- a/src/templates/instagram/tasks.ts +++ b/src/templates/instagram/tasks.ts @@ -17,7 +17,7 @@ class InstagramTasks { constructor(public session: InstagramSession) {} async refreshToken() { - const runner = this.session.getRunner(); + const runner = await this.session.getRunner(); const res = await runner.getJson<{ access_token: string }>( paths.TOKEN_REFRESH_PATH diff --git a/src/templates/snek/errors.ts b/src/templates/snek/errors.ts index ce24e25..164b8cc 100644 --- a/src/templates/snek/errors.ts +++ b/src/templates/snek/errors.ts @@ -23,9 +23,11 @@ class TaskError { * Handle specific errors which could occur on SNEK tasks. * * @param {Response} response A SNEK-client graphql response - * @returns {boolean} "false" if an error occurs. Otherwise "true" + * @returns {boolean} "false" if a token error occurs. + * "undefined" if other errors occurs. + * "true" otherwise. */ - handleErrors(response: types.ApolloResult): boolean { + handleErrors(response: types.ApolloResult): boolean | undefined { const errors = response.errors; if (errors && errors.length > 0) { @@ -45,7 +47,7 @@ class TaskError { return false; } else { - return false; + return undefined; } } diff --git a/src/templates/snek/tasks/index.ts b/src/templates/snek/tasks/index.ts index 66c37a7..e0be8d5 100644 --- a/src/templates/snek/tasks/index.ts +++ b/src/templates/snek/tasks/index.ts @@ -46,7 +46,7 @@ class MainTask extends TaskError { response = await this.session.ep.sendQuery(query, variables); } - if (this.handleErrors(response)) { + if (this.handleErrors(response) == false) { await this.session.refresh(); return this.run(type, query, variables); From cee2d6864722468a78e6f8785776f864f1dacd18 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 7 Sep 2020 00:50:19 +0200 Subject: [PATCH 36/50] Improve snek session begin return type The return type of the snek session begin method has been improved. --- src/session/sessions.ts | 6 ++++-- src/session/types.ts | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 src/session/types.ts diff --git a/src/session/sessions.ts b/src/session/sessions.ts index a1da18a..3a2ec30 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -20,6 +20,8 @@ import InstagramTasks from "../templates/instagram/tasks"; import { ApolloEndpoint, ScraperEndpoint } from "../endpoints/index"; // Contains basic session interfaces import { User } from "./index"; +// Contains the session types +import { SNEKAuth } from "./types"; // Contains the snek template types import { TaskTypes } from "../templates/snek/types"; //> Config @@ -251,9 +253,9 @@ class SnekSession extends CookieSession { * Begin session. * * @param {string} user A User defined by username and password - * @returns {Promise} A UserData object + * @returns {Promise} A SNEKAuth object */ - async begin(user?: User): Promise { + async begin(user?: User): Promise { let anonymous = false; if (!user && this.refreshToken) { diff --git a/src/session/types.ts b/src/session/types.ts new file mode 100644 index 0000000..1b585b0 --- /dev/null +++ b/src/session/types.ts @@ -0,0 +1,4 @@ +export interface SNEKAuth { + username?: string; + anonymous: boolean; +} From d81b62c30c602e7c2af0fef5e102ff5b3955e2f3 Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 7 Sep 2020 00:52:40 +0200 Subject: [PATCH 37/50] Improve instagram client defaults The default values and documentation of the instagram client have been improved. --- src/index.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/index.ts b/src/index.ts index c051621..97cbc5f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -124,27 +124,24 @@ class InstagramClient extends Client { * * @constructor * @author Nico Schett - * @param url The base URL the GithubClient should be working on. - * Default: "https://api.github.com/graphql". + * @param url The base URL the InstagramClient should be working on. + * Default: "https://graph.instagram.com" * @param headers A object containing various request headers * @param type A type description to differ between multiple instances */ constructor( - url: string = "https://api.github.com/graphql", - headers: { accessToken: string }, + accessToken: string, + url: string = "https://graph.instagram.com", + headers: {} = {}, type: string = "scraper" ) { super({ type, url, headers }); - this.ep = new Scraper("https://graph.instagram.com", { - headers: { Authorization: `Bearer ${headers.accessToken}` }, + this.ep = new Scraper(url, { + headers: { Authorization: `Bearer ${accessToken}` }, }); - this.session = new InstagramSession( - "instagram", - headers.accessToken, - this.ep - ); + this.session = new InstagramSession("instagram", accessToken, this.ep); } } From d45a4058b94a11504fc82b07eef239b80bec8a94 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 9 Sep 2020 12:07:22 +0200 Subject: [PATCH 38/50] Fix task run error loop The loop which was created when a error had occurred has been fixed now. --- src/session/sessions.ts | 27 ++++++++++++++++++++++++--- src/templates/snek/tasks/index.ts | 6 ------ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/session/sessions.ts b/src/session/sessions.ts index 3a2ec30..a438214 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -17,7 +17,11 @@ import SnekTasks from "../templates/snek/tasks/index"; import InstagramTasks from "../templates/instagram/tasks"; //> Interfaces // Contains the interface for the apollo and scraper endpoint -import { ApolloEndpoint, ScraperEndpoint } from "../endpoints/index"; +import { + ApolloEndpoint, + ScraperEndpoint, + ApolloResult, +} from "../endpoints/index"; // Contains basic session interfaces import { User } from "./index"; // Contains the session types @@ -336,16 +340,33 @@ class SnekSession extends CookieSession { * @param type * @param data * @param variables + * @param {boolean} retry Retry on error * @description Perform a session aware custom task. Token and refreshToken * are set by default! * When no type is specified, query is set as default. */ - async runner(type: TaskTypes, data: DocumentNode, variables: object) { - return this.tasks.run(type, data, { + async runner( + type: TaskTypes, + data: DocumentNode, + variables: object, + retry: boolean = true + ): Promise> { + variables = { ...variables, token: await this.upToDateToken(), refreshToken: this.refreshToken, + }; + + const response = await this.tasks.run(type, data, { + ...variables, }); + + if (this.tasks.handleErrors(response) == false && retry) { + await this.refresh(); + + return this.runner(type, data, variables, false); + } + return response; } } //#endregion diff --git a/src/templates/snek/tasks/index.ts b/src/templates/snek/tasks/index.ts index e0be8d5..c91cc0f 100644 --- a/src/templates/snek/tasks/index.ts +++ b/src/templates/snek/tasks/index.ts @@ -46,12 +46,6 @@ class MainTask extends TaskError { response = await this.session.ep.sendQuery(query, variables); } - if (this.handleErrors(response) == false) { - await this.session.refresh(); - - return this.run(type, query, variables); - } - return response; } } From 21f7fd97bc3229d41c3c98193e4f6e9bc01d7746 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 9 Sep 2020 12:09:57 +0200 Subject: [PATCH 39/50] Add cookie options Secure and sameSite option has been added. --- src/session/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/session/index.ts b/src/session/index.ts index 8808a4a..6799def 100644 --- a/src/session/index.ts +++ b/src/session/index.ts @@ -56,7 +56,7 @@ class Session implements ISession { */ set token(value: string | undefined) { if (value) { - Cookies.set(this.tokenName, value); + Cookies.set(this.tokenName, value, { secure: true, sameSite: "Lax" }); } else { Cookies.remove(this.tokenName); } From 7edb688dc8b14cc1b0b69c37d3ca412d463fce8f Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 10 Sep 2020 04:36:44 +0200 Subject: [PATCH 40/50] Add support for uploading files Now it is possible to upload files via the Apollo-Client. Also Apollo v3 is implemented now. --- package.json | 17 +++++++++++------ src/endpoints/apollo.ts | 39 +++++++++++++-------------------------- src/endpoints/index.ts | 3 +-- tsconfig.json | 6 +++++- 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index f3cf5b6..0815408 100644 --- a/package.json +++ b/package.json @@ -24,17 +24,22 @@ }, "homepage": "https://github.com/snek-at/client#readme", "dependencies": { - "apollo-cache-inmemory": "^1.6.5", - "apollo-client": "^2.6.8", - "apollo-link-http": "^1.5.16", - "graphql": "^14.6.0", + "@apollo/client": "^3.1.5", + "apollo-upload-client": "^14.1.1", + "graphql": "^14.7.0", "graphql-tag": "^2.10.3", - "js-cookie": "^2.2.1" + "js-cookie": "^2.2.1", + "react": "^16.13.1", + "subscriptions-transport-ws": "^0.9.18" }, "devDependencies": { "@babel/core": "^7.9.6", "@babel/plugin-proposal-class-properties": "^7.8.3", + "@types/apollo-upload-client": "^14.1.0", "@types/js-cookie": "^2.2.6", - "typescript": "^3.8.3" + "@types/mocha": "^8.0.3", + "@types/node": "^14.6.4", + "@types/react": "^16.9.49", + "typescript": "^3.9.7" } } diff --git a/src/endpoints/apollo.ts b/src/endpoints/apollo.ts index b263f56..b0e8478 100644 --- a/src/endpoints/apollo.ts +++ b/src/endpoints/apollo.ts @@ -1,20 +1,15 @@ //#region > Imports -//#PACKAGE "apollo-client" -//## npm install "apollo-client"@2.6.8 -// Contains the client for graphql handling -import { ApolloClient } from "apollo-client"; -//#PACKAGE "apollo-link-http" -//## npm install "apollo-link-http"@1.5.16 -// Contains the link for the apollo client -import { HttpLink } from "apollo-link-http"; -//#PACKAGE "apollo-cache-inmemory" -//## npm install "apollo-cache-inmemory"@1.6.5 -// Contains cache handling for apollo +//#PACKAGE "@apollo/client" import { + ApolloClient, + ApolloLink, InMemoryCache, - IntrospectionFragmentMatcher, NormalizedCacheObject, -} from "apollo-cache-inmemory"; + HttpLink, +} from "@apollo/client"; +//#PACKAGE "'apollo-upload-client" +// Contains the link for the apollo client +import { createUploadLink } from "apollo-upload-client"; //#PACKAGE "graphql" //## npm install "graphql"@14.6.0 // Contains the interface for gql queries, mutations and subscriptions @@ -32,7 +27,7 @@ import { ApolloResult } from "./index"; /** @class Apollo client for graphql handling */ class Apollo implements ApolloEndpoint { //> Fields - private link: HttpLink; + private link: ApolloLink; private cache: InMemoryCache; private client: ApolloClient; @@ -49,26 +44,18 @@ class Apollo implements ApolloEndpoint { */ constructor(uri: string, options: Options) { this.headers = options.headers; - const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData: { - __schema: { - types: [], - }, - }, - }); try { - this.cache = new InMemoryCache({ fragmentMatcher }); + this.cache = new InMemoryCache(); } catch { //#ERROR throw new Error("An error occurred while initializing the cache!"); } try { - this.link = new HttpLink({ - uri, - headers: options.headers, - }); + const uploadLink = createUploadLink({ uri, headers: options.headers }); + + this.link = ApolloLink.from([uploadLink]); } catch { //#ERROR throw new Error("An error occurred while initializing the API link!"); diff --git a/src/endpoints/index.ts b/src/endpoints/index.ts index 7ab7ee1..1f720df 100644 --- a/src/endpoints/index.ts +++ b/src/endpoints/index.ts @@ -4,8 +4,7 @@ //## npm install "graphql"@14.6.0 // Contains the interface for gql queries, mutations and subscriptions import { DocumentNode } from "graphql"; -import { FetchResult } from "apollo-link"; -import { ApolloQueryResult } from "apollo-client"; +import { ApolloQueryResult, FetchResult } from "@apollo/client"; //#endregion //#region > Types diff --git a/tsconfig.json b/tsconfig.json index 9666c9b..d3d7b0f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,7 +33,11 @@ /** * Allow json modules. */ - "resolveJsonModule": true + "resolveJsonModule": true, + /** + * Skip type checking of declaration files. + */ + "skipLibCheck": true }, /** * The files to not type check. From 8e3103da2e5722fc03f3d5c9bd2b4e5fe771bb63 Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 10 Sep 2020 18:20:09 +0200 Subject: [PATCH 41/50] Fix token refresh issue with invalid refresh token Now it is possible to refresh a session even when the refresh token is invalid. --- src/templates/snek/tasks/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/templates/snek/tasks/index.ts b/src/templates/snek/tasks/index.ts index c91cc0f..ea0848f 100644 --- a/src/templates/snek/tasks/index.ts +++ b/src/templates/snek/tasks/index.ts @@ -46,6 +46,8 @@ class MainTask extends TaskError { response = await this.session.ep.sendQuery(query, variables); } + this.handleErrors(response); + return response; } } From a03b509d0b935f87828ce9cac619d50076c1e4ce Mon Sep 17 00:00:00 2001 From: schettn Date: Sat, 7 Nov 2020 19:12:29 +0100 Subject: [PATCH 42/50] Cleanup Fix spacing, remove console logs and legacy error log. --- src/endpoints/scraper.ts | 1 - src/templates/snek/errors.ts | 4 ---- src/templates/snek/tasks/user.ts | 2 -- src/templates/snek/types.ts | 10 ++++------ 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/endpoints/scraper.ts b/src/endpoints/scraper.ts index 4162ab9..2b375d6 100644 --- a/src/endpoints/scraper.ts +++ b/src/endpoints/scraper.ts @@ -47,7 +47,6 @@ class Scraper implements ScraperEndpoint { * @returns {T} JSON object passed to given structure */ async getJson(path: string): Promise { - console.log("HEADERS", this.headers); return fetch(this.url + path, { headers: { ...this.headers, diff --git a/src/templates/snek/errors.ts b/src/templates/snek/errors.ts index 164b8cc..21dda3e 100644 --- a/src/templates/snek/errors.ts +++ b/src/templates/snek/errors.ts @@ -31,10 +31,6 @@ class TaskError { const errors = response.errors; if (errors && errors.length > 0) { - //#LEGACY - //#ERROR - console.error("An error occurred" + JSON.stringify(response)); - if (errors[0].message === "Invalid refresh token") { /* Delete token and refresh token if refresh token is invalid */ this.session.token = undefined; diff --git a/src/templates/snek/tasks/user.ts b/src/templates/snek/tasks/user.ts index e7df478..d1ec78e 100644 --- a/src/templates/snek/tasks/user.ts +++ b/src/templates/snek/tasks/user.ts @@ -9,8 +9,6 @@ import { ApolloResult, GraphQLWhoami } from "../types"; //#region > Classes /** @class A set of session aware tasks */ -//#region > Classes -/** @class A set of session aware Tasks */ class UserTasks { /** * Creates an instance of a SessionTasks. diff --git a/src/templates/snek/types.ts b/src/templates/snek/types.ts index 17637e7..2fdb74a 100644 --- a/src/templates/snek/types.ts +++ b/src/templates/snek/types.ts @@ -6,10 +6,10 @@ export { ApolloResult } from "../../endpoints/index"; export { User } from "../../session"; export type TaskTypes = "query" | "mutation"; + /** * All graphql response types for authentication related requests. */ - //#region > Interfaces /** * @interface GraphQLAuthentication defines the structure of the authentication @@ -26,8 +26,7 @@ export interface GraphQLAuthentication { } /** - * @interface GraphQLRefresh defines the structure of the refresh - * result data. + * @interface GraphQLRefresh defines the structure of the refresh result data */ export interface GraphQLRefresh { refresh: { @@ -38,8 +37,7 @@ export interface GraphQLRefresh { } /** - * @interface GraphQLRevoke defines the structure of the revoke - * result data. + * @interface GraphQLRevoke defines the structure of the revoke result data */ export interface GraphQLRevoke { revoke: { @@ -47,7 +45,7 @@ export interface GraphQLRevoke { }; } -/** @interface GraphQLWhoami defines the structure of a whoami data. */ +/** @interface GraphQLWhoami defines the structure of a whoami data */ export interface GraphQLWhoami { whoami: { username: string }; } From b5dfd3ba048a803b433fd01bea73d5ee8374f6c4 Mon Sep 17 00:00:00 2001 From: schettn Date: Sat, 7 Nov 2020 19:14:39 +0100 Subject: [PATCH 43/50] Update package.json Remove several unnecessary packages. --- package.json | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 0815408..bbbae10 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "mocha --require ts-node/register src/test/**/*.ts", "build": "npx tsc" }, "files": [ @@ -28,18 +28,13 @@ "apollo-upload-client": "^14.1.1", "graphql": "^14.7.0", "graphql-tag": "^2.10.3", - "js-cookie": "^2.2.1", - "react": "^16.13.1", - "subscriptions-transport-ws": "^0.9.18" + "js-cookie": "^2.2.1" }, "devDependencies": { "@babel/core": "^7.9.6", "@babel/plugin-proposal-class-properties": "^7.8.3", "@types/apollo-upload-client": "^14.1.0", "@types/js-cookie": "^2.2.6", - "@types/mocha": "^8.0.3", - "@types/node": "^14.6.4", - "@types/react": "^16.9.49", "typescript": "^3.9.7" } } From 18acb6c4fb20d04898631c15b44f0078a2d98b30 Mon Sep 17 00:00:00 2001 From: schettn Date: Sat, 7 Nov 2020 19:33:23 +0100 Subject: [PATCH 44/50] Implement codacy suggestions Now handleErrors return null instead of undefined. Also a missing equal sign has been added. --- src/session/sessions.ts | 2 +- src/templates/snek/errors.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/session/sessions.ts b/src/session/sessions.ts index a438214..36cdee2 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -361,7 +361,7 @@ class SnekSession extends CookieSession { ...variables, }); - if (this.tasks.handleErrors(response) == false && retry) { + if (this.tasks.handleErrors(response) === false && retry) { await this.refresh(); return this.runner(type, data, variables, false); diff --git a/src/templates/snek/errors.ts b/src/templates/snek/errors.ts index 21dda3e..ac9de80 100644 --- a/src/templates/snek/errors.ts +++ b/src/templates/snek/errors.ts @@ -24,10 +24,10 @@ class TaskError { * * @param {Response} response A SNEK-client graphql response * @returns {boolean} "false" if a token error occurs. - * "undefined" if other errors occurs. + * "null" if other errors occurs. * "true" otherwise. */ - handleErrors(response: types.ApolloResult): boolean | undefined { + handleErrors(response: types.ApolloResult): boolean | null { const errors = response.errors; if (errors && errors.length > 0) { @@ -43,7 +43,7 @@ class TaskError { return false; } else { - return undefined; + return null; } } From b85fc7b58cc2934d94a617a232334da437d3e493 Mon Sep 17 00:00:00 2001 From: Schett Nico <52858351+schettn@users.noreply.github.com> Date: Mon, 9 Nov 2020 21:38:29 +0100 Subject: [PATCH 45/50] Apply suggestions from code review Co-authored-by: Pinterics David <55298934+pinterid@users.noreply.github.com> --- src/session/sessions.ts | 1 - src/templates/instagram/tasks.ts | 2 ++ src/templates/snek/tasks/auth.ts | 2 +- src/templates/snek/tasks/index.ts | 3 +++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/session/sessions.ts b/src/session/sessions.ts index 36cdee2..e456f08 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -156,7 +156,6 @@ class InstagramSession extends Session { super(sId); this.tokenName = sId + "-" + this.tokenName; - this.token = token; this.tasks = new InstagramTasks(this); } diff --git a/src/templates/instagram/tasks.ts b/src/templates/instagram/tasks.ts index 0aec17d..4395a82 100644 --- a/src/templates/instagram/tasks.ts +++ b/src/templates/instagram/tasks.ts @@ -1,8 +1,10 @@ +//#region > Imports //> Sessions // Contains the SNEK session import { InstagramSession } from "../../session/sessions"; //> Instagram Endpoint paths import * as paths from "./paths"; +//#endregion //#region > Classes /** @class A Template with initializes all tasks */ diff --git a/src/templates/snek/tasks/auth.ts b/src/templates/snek/tasks/auth.ts index 65f8b83..bdd8bdc 100644 --- a/src/templates/snek/tasks/auth.ts +++ b/src/templates/snek/tasks/auth.ts @@ -50,7 +50,7 @@ class AuthTask { * User login. * * @param {string} user A User defined by username and password - * @returns {Promise>} Authentication data. + * @returns {Promise>} Authentication data * @description Authenticates a real user to obtain a JWT */ async nonanon(user: User): Promise> { diff --git a/src/templates/snek/tasks/index.ts b/src/templates/snek/tasks/index.ts index ea0848f..ce030b8 100644 --- a/src/templates/snek/tasks/index.ts +++ b/src/templates/snek/tasks/index.ts @@ -14,7 +14,9 @@ import { ApolloResult, TaskTypes } from "../types"; import { TaskError } from "../errors"; import AuthTask from "./auth"; import UserTask from "./user"; +//#endregion +//#region > Classes class MainTask extends TaskError { public mutations: { jwtAuth: typeof mutationsAuth } = { jwtAuth: require("../mutations/auth"), @@ -51,6 +53,7 @@ class MainTask extends TaskError { return response; } } +//#endregion //#region > Exports export default MainTask; From 4521d9c2331ad31c2f17f3fe85c3e07412f2d8ac Mon Sep 17 00:00:00 2001 From: schettn Date: Mon, 9 Nov 2020 21:42:31 +0100 Subject: [PATCH 46/50] Improve regions and comments The regions and comments have been improved. --- src/templates/snek/types.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/templates/snek/types.ts b/src/templates/snek/types.ts index 2fdb74a..223cf52 100644 --- a/src/templates/snek/types.ts +++ b/src/templates/snek/types.ts @@ -1,16 +1,11 @@ -/** - * All types - */ - +//#region > General Types export { ApolloResult } from "../../endpoints/index"; export { User } from "../../session"; export type TaskTypes = "query" | "mutation"; +//#endregion -/** - * All graphql response types for authentication related requests. - */ -//#region > Interfaces +//#region > Graphql Response Types for Authentication Related Requests /** * @interface GraphQLAuthentication defines the structure of the authentication * result data. From 5659b2388b81306a1f65cc28cd69f544c38ea733 Mon Sep 17 00:00:00 2001 From: Schett Nico <52858351+schettn@users.noreply.github.com> Date: Wed, 11 Nov 2020 00:45:01 +0100 Subject: [PATCH 47/50] Apply suggestions from code review Co-authored-by: Florian Kleber --- src/endpoints/scraper.ts | 1 - src/session/sessions.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/endpoints/scraper.ts b/src/endpoints/scraper.ts index 2b375d6..89479c6 100644 --- a/src/endpoints/scraper.ts +++ b/src/endpoints/scraper.ts @@ -183,7 +183,6 @@ class Scraper implements ScraperEndpoint { }); } } - //#endregion //#region > Exports diff --git a/src/session/sessions.ts b/src/session/sessions.ts index e456f08..1a74f22 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -269,7 +269,6 @@ class SnekSession extends CookieSession { if (!user) { /* Authenticate anonymous user */ - authData = (await this.tasks.set.auth.anon()).data?.auth; anonymous = true; } else { From a7814ecb45ed00d10a270b8b724ba1fbded007a3 Mon Sep 17 00:00:00 2001 From: schettn Date: Wed, 11 Nov 2020 00:47:50 +0100 Subject: [PATCH 48/50] Improve comments An extremely long region has been decimated. --- src/templates/snek/types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/templates/snek/types.ts b/src/templates/snek/types.ts index 223cf52..443543c 100644 --- a/src/templates/snek/types.ts +++ b/src/templates/snek/types.ts @@ -5,7 +5,8 @@ export { User } from "../../session"; export type TaskTypes = "query" | "mutation"; //#endregion -//#region > Graphql Response Types for Authentication Related Requests +//#region > Graphql Response Types +//> Authentication /** * @interface GraphQLAuthentication defines the structure of the authentication * result data. From 2e5a67d4c02a51be64d34767f5a577d428cc97eb Mon Sep 17 00:00:00 2001 From: schettn Date: Thu, 26 Nov 2020 14:10:42 +0100 Subject: [PATCH 49/50] Hotfix: Change compiler to babel The compiler had to be changed in order to support optional chaining etc. --- .babelrc | 11 +++++ package.json | 17 ++++++-- tsconfig.json | 108 ++++++++++++++++++++++++++++++-------------------- 3 files changed, 90 insertions(+), 46 deletions(-) create mode 100644 .babelrc diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..2475cf6 --- /dev/null +++ b/.babelrc @@ -0,0 +1,11 @@ +{ + "presets": [ + ["@babel/preset-env",{"targets": {"node": "current"}}], + "@babel/preset-typescript" + ], + "plugins": [ + "@babel/plugin-syntax-bigint", + "@babel/plugin-proposal-class-properties", + "@babel/plugin-proposal-optional-chaining" + ] +} diff --git a/package.json b/package.json index bbbae10..e6c02dd 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,11 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { - "test": "mocha --require ts-node/register src/test/**/*.ts", - "build": "npx tsc" + "type-check": "tsc --noEmit", + "type-check:watch": "npm run type-check -- --watch", + "build": "npm run build:types && npm run build:js", + "build:types": "tsc --emitDeclarationOnly", + "build:js": "babel src --out-dir lib --extensions \".ts,.tsx\" --source-maps inline" }, "files": [ "lib", @@ -25,14 +28,20 @@ "homepage": "https://github.com/snek-at/client#readme", "dependencies": { "@apollo/client": "^3.1.5", + "@types/node": "^14.14.10", "apollo-upload-client": "^14.1.1", "graphql": "^14.7.0", "graphql-tag": "^2.10.3", "js-cookie": "^2.2.1" }, "devDependencies": { - "@babel/core": "^7.9.6", - "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/cli": "^7.12.8", + "@babel/core": "^7.12.9", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/preset-env": "^7.12.7", + "@babel/preset-typescript": "^7.12.7", "@types/apollo-upload-client": "^14.1.0", "@types/js-cookie": "^2.2.6", "typescript": "^3.9.7" diff --git a/tsconfig.json b/tsconfig.json index d3d7b0f..8b61f29 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,46 +1,70 @@ { "compilerOptions": { - "target": "ES2020", - /** - * Specify module code generation: 'none', 'commonjs', 'amd', 'system', - * 'umd', 'es2015', 'es2020', or 'ESNext'. - */ - "module": "commonjs", - /** - * Generates corresponding '.d.ts' file. - */ - "declaration": true, - /** - * Redirect output structure to the directory. - */ - "outDir": "lib", - /** - * Do not emit comments to output. - */ - "removeComments": true, - /** Enable all strict type-checking options. */ - "strict": true, - /** - * Enables emit interoperability between CommonJS and ES Modules - * via creation of namespace objects for all imports. - * Implies 'allowSyntheticDefaultImports'. - */ - "esModuleInterop": true, - /** - * Disallow inconsistently-cased references to the same file. - */ - "forceConsistentCasingInFileNames": true, - /** - * Allow json modules. - */ + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "lib", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ "resolveJsonModule": true, - /** - * Skip type checking of declaration files. - */ - "skipLibCheck": true - }, - /** - * The files to not type check. - */ - "exclude": ["node_modules", "build", "lib"] + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } } From b7f7b8664cf4bbde5eff063b3a0ca08546e71f29 Mon Sep 17 00:00:00 2001 From: schettn Date: Fri, 27 Nov 2020 02:14:45 +0100 Subject: [PATCH 50/50] Add support for NodeJS Now cookies are only used if the package is used in browser. --- src/session/index.ts | 32 ++++++++++++++++++++++++++------ src/session/sessions.ts | 34 +++++++++++++++++----------------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/session/index.ts b/src/session/index.ts index 6799def..c9049bd 100644 --- a/src/session/index.ts +++ b/src/session/index.ts @@ -24,6 +24,7 @@ interface ISession { class Session implements ISession { sessions: { [id: string]: ISession } = {}; tokenName: string = "token"; + _token: string | undefined = undefined; /** * Initializes a base Session. @@ -41,9 +42,11 @@ class Session implements ISession { * @returns {string | undefined} A users JWT if set */ get token(): string | undefined { - const token = Cookies.get(this.tokenName); - - return token ? token : undefined; + if (this.checkPlatform() === "WEB") { + return Cookies.get(this.tokenName); + } else { + return this._token; + } } //> Setter @@ -55,14 +58,31 @@ class Session implements ISession { * the cookie will be removed. */ set token(value: string | undefined) { - if (value) { - Cookies.set(this.tokenName, value, { secure: true, sameSite: "Lax" }); + if (this.checkPlatform() === "WEB") { + if (value) { + Cookies.set(this.tokenName, value ? value : "", { + /* Expire time is set to 4 minutes */ + expires: 4 / 1440, + }); + } else { + Cookies.remove(this.tokenName); + } } else { - Cookies.remove(this.tokenName); + this._token = value; } } //> Methods + /** + * Check if snek-client is used by node or web. + */ + checkPlatform() { + if (typeof window === "undefined") { + return "NODE"; + } else { + return "WEB"; + } + } /** * Add a subSession to a session. * diff --git a/src/session/sessions.ts b/src/session/sessions.ts index 1a74f22..3edfa84 100644 --- a/src/session/sessions.ts +++ b/src/session/sessions.ts @@ -66,6 +66,7 @@ class GithubSession extends Session { /** @class CookieSession extends token session handling with cookies */ class CookieSession extends Session { refreshTokenName: string = "refresh"; + _refreshToken: string | undefined = undefined; /** * Initializes a cookie session. @@ -94,9 +95,11 @@ class CookieSession extends Session { * @returns {string | undefined} A users JWT if set */ get refreshToken(): string | undefined { - const token = Cookies.get(this.refreshTokenName); - - return token ? token : undefined; + if (this.checkPlatform() === "WEB") { + return Cookies.get(this.refreshTokenName); + } else { + return this._token; + } } //> Setter @@ -109,14 +112,7 @@ class CookieSession extends Session { * minutes. */ set token(value: string | undefined) { - if (value) { - Cookies.set(this.tokenName, value ? value : "", { - /* Expire time is set to 4 minutes */ - expires: 4 / 1440, - }); - } else { - Cookies.remove(this.tokenName); - } + super.token = value; } /** @@ -128,13 +124,17 @@ class CookieSession extends Session { * set to six days. */ set refreshToken(value: string | undefined) { - if (value) { - Cookies.set(this.refreshTokenName, value, { - /* Expire time is set to 6 days */ - expires: 6, - }); + if (this.checkPlatform() === "WEB") { + if (value) { + Cookies.set(this.refreshTokenName, value ? value : "", { + /* Expire time is set to 6 days */ + expires: 6, + }); + } else { + Cookies.remove(this.refreshTokenName); + } } else { - Cookies.remove(this.refreshTokenName); + this._refreshToken = value; } } }