diff --git a/package.json b/package.json index a16d6fc..5383eb2 100644 --- a/package.json +++ b/package.json @@ -22,11 +22,13 @@ "fast-glob": "^3.2.11", "graphql": "^16.5.0", "jose": "^4.8.3", + "node-fetch": "^3.2.10", "retes": "^0.32.0", "uuid": "^8.3.2" }, "devDependencies": { "release-it": "^15.4.1", + "@types/node-fetch": "^2.6.2", "@testing-library/dom": "^8.17.1", "@types/debug": "^4.1.7", "@types/node": "^18.6.5", @@ -102,4 +104,4 @@ "url": "https://github.com/saleor/saleor-app-sdk/issues" }, "homepage": "https://github.com/saleor/saleor-app-sdk#readme" -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c905d8..4f8666b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,7 @@ specifiers: '@testing-library/dom': ^8.17.1 '@types/debug': ^4.1.7 '@types/node': ^18.6.5 + '@types/node-fetch': ^2.6.2 '@types/uuid': ^8.3.4 '@typescript-eslint/eslint-plugin': ^5.33.0 '@typescript-eslint/parser': ^5.33.0 @@ -24,6 +25,7 @@ specifiers: husky: ^8.0.1 jose: ^4.8.3 jsdom: ^20.0.0 + node-fetch: ^3.2.10 prettier: 2.7.1 release-it: ^15.4.1 retes: ^0.32.0 @@ -40,6 +42,7 @@ dependencies: fast-glob: 3.2.11 graphql: 16.5.0 jose: 4.8.3 + node-fetch: 3.2.10 retes: 0.32.0 uuid: 8.3.2 @@ -47,6 +50,7 @@ devDependencies: '@testing-library/dom': 8.17.1 '@types/debug': 4.1.7 '@types/node': 18.7.1 + '@types/node-fetch': 2.6.2 '@types/uuid': 8.3.4 '@typescript-eslint/eslint-plugin': 5.33.0_njno5y7ry2l2lcmiu4tywxkwnq '@typescript-eslint/parser': 5.33.0_qugx7qdu5zevzvxaiqyxfiwquq @@ -686,6 +690,13 @@ packages: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} dev: true + /@types/node-fetch/2.6.2: + resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} + dependencies: + '@types/node': 18.7.1 + form-data: 3.0.1 + dev: true + /@types/node/18.7.1: resolution: {integrity: sha512-GKX1Qnqxo4S+Z/+Z8KKPLpH282LD7jLHWJcVryOflnsnH+BtSDfieR6ObwBMwpnNws0bUK8GI7z0unQf9bARNQ==} dev: true @@ -1446,7 +1457,6 @@ packages: /data-uri-to-buffer/4.0.0: resolution: {integrity: sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==} engines: {node: '>= 12'} - dev: true /data-urls/3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} @@ -2358,7 +2368,6 @@ packages: dependencies: node-domexception: 1.0.0 web-streams-polyfill: 3.2.1 - dev: true /figures/4.0.1: resolution: {integrity: sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w==} @@ -2418,6 +2427,15 @@ packages: engines: {node: '>= 14.17'} dev: true + /form-data/3.0.1: + resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + /form-data/4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -2432,7 +2450,6 @@ packages: engines: {node: '>=12.20.0'} dependencies: fetch-blob: 3.2.0 - dev: true /fs-extra/8.1.0: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} @@ -3494,7 +3511,6 @@ packages: /node-domexception/1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} - dev: true /node-fetch/2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} @@ -3515,7 +3531,6 @@ packages: data-uri-to-buffer: 4.0.0 fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 - dev: true /node-releases/2.0.6: resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} @@ -4899,7 +4914,6 @@ packages: /web-streams-polyfill/3.2.1: resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} engines: {node: '>= 8'} - dev: true /webidl-conversions/3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} diff --git a/src/APL/environmentVariablesAPL.ts b/src/APL/environmentVariablesAPL.ts new file mode 100644 index 0000000..73119aa --- /dev/null +++ b/src/APL/environmentVariablesAPL.ts @@ -0,0 +1,121 @@ +import { promises as fsPromises } from "fs"; +import fetch from "node-fetch"; + +import { APL, AuthData } from "./apl"; + +interface IEnvVar { + key: string; + value: string; +} + +const ENV_FILE_NAME = ".envfile"; + +const saveDataToFile = async (variables: IEnvVar[]) => { + let currentEnvVars; + try { + await fsPromises.access(ENV_FILE_NAME); + currentEnvVars = JSON.parse(await fsPromises.readFile(ENV_FILE_NAME, "utf-8")); + } catch { + currentEnvVars = {}; + } + + await fsPromises.writeFile( + ENV_FILE_NAME, + JSON.stringify({ + ...currentEnvVars, + ...variables.reduce((acc, cur) => ({ ...acc, [cur.key]: cur.value }), {}), + }) + ); +}; + +const loadDataFromFile = async () => { + try { + await fsPromises.access(ENV_FILE_NAME); + return JSON.parse(await fsPromises.readFile(ENV_FILE_NAME, "utf-8")); + } catch { + return {}; + } +}; + +const saveDataToVercel = async (variables: IEnvVar[]) => { + await fetch(process.env.SALEOR_REGISTER_APP_URL as string, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + token: process.env.SALEOR_DEPLOYMENT_TOKEN, + envs: variables.map(({ key, value }) => ({ key, value })), + }), + }); +}; + +const loadDataFromVercel = () => process.env; + +export const getEnvVars = async () => { + if (process.env.VERCEL === "1") { + return loadDataFromVercel(); + } + return loadDataFromFile(); +}; + +export const setEnvVars = async (variables: IEnvVar[]) => { + console.debug("Setting environment variables: ", variables); + + if (process.env.VERCEL === "1") { + await saveDataToVercel(variables); + } else { + await saveDataToFile(variables); + } +}; + +export const environmentVariablesAPL: APL = { + get: async (domain) => { + const env = await getEnvVars(); + if (domain !== env.SALEOR_DOMAIN || !env.SALEOR_AUTH_TOKEN) { + return undefined; + } + return { + token: env.SALEOR_AUTH_TOKEN, + domain: env.SALEOR_DOMAIN, + }; + }, + set: async (authData: AuthData) => { + await setEnvVars([ + { + key: "SALEOR_AUTH_TOKEN", + value: authData.token, + }, + { + key: "SALEOR_DOMAIN", + value: authData.domain, + }, + ]); + }, + delete: async (domain: string) => { + const env = await getEnvVars(); + + if (domain !== env.SALEOR_DOMAIN) { + return; + } + await setEnvVars([ + { + key: "SALEOR_AUTH_TOKEN", + value: "", + }, + { + key: "SALEOR_DOMAIN", + value: "", + }, + ]); + }, + getAll: async () => { + const env = await getEnvVars(); + if (!env.SALEOR_DOMAIN || !env.SALEOR_AUTH_TOKEN) { + return []; + } + const authData = { + token: env.SALEOR_AUTH_TOKEN, + domain: env.SALEOR_DOMAIN, + }; + return [authData]; + }, +}; diff --git a/src/APL/index.ts b/src/APL/index.ts index 3831bbc..43122ba 100644 --- a/src/APL/index.ts +++ b/src/APL/index.ts @@ -1 +1,2 @@ export * from "./apl"; +export * from "./environmentVariablesAPL";