saleor-app-sdk-REDIS_APL/src/APL/file-apl.ts

132 lines
3.5 KiB
TypeScript
Raw Normal View History

import { promises as fsPromises } from "fs";
import { APL, AplConfiguredResult, AplReadyResult, AuthData } from "./apl";
2022-09-05 09:09:06 +00:00
import { createAPLDebug } from "./apl-debug";
2022-09-05 09:09:06 +00:00
const debug = createAPLDebug("FileAPL");
export type FileAPLConfig = {
fileName?: string;
};
/**
* File APL
*
* The APL store auth data in the json file.
*
* Before using this APL, please take in consideration:
* - only stores single auth data entry (setting up a new one will overwrite previous values)
* - it's not recommended for production use - redeployment of the application will override
* existing values, or data persistence will not be guaranteed at all depending on chosen
* hosting solution
*
*/
export class FileAPL implements APL {
private fileName: string;
constructor(config: FileAPLConfig = {}) {
2022-09-01 16:40:58 +00:00
this.fileName = config?.fileName || ".saleor-app-auth.json";
}
2022-09-02 13:39:15 +00:00
/**
* Load auth data from a file and return it as AuthData format.
* In case of incomplete or invalid data, return `undefined`.
*/
private async loadDataFromFile(): Promise<AuthData | undefined> {
debug(`Will try to load auth data from the ${this.fileName} file`);
2022-09-02 13:39:15 +00:00
let parsedData: Record<string, string> = {};
2022-09-02 13:39:15 +00:00
try {
parsedData = JSON.parse(await fsPromises.readFile(this.fileName, "utf-8"));
debug("%s read successfully", this.fileName);
2022-09-02 13:39:15 +00:00
} catch (err) {
debug(`Could not read auth data from the ${this.fileName} file`, err);
debug(
"Maybe apl.get() was called before app was registered. Returning empty, fallback data (undefined)"
);
return undefined;
2022-09-02 13:39:15 +00:00
}
const { token, domain, apiUrl, appId, jwks } = parsedData;
if (token && domain && apiUrl && appId && jwks) {
debug("Token and domain found, returning values: %s, %s", domain, `${token[0]}***`);
return { token, domain, apiUrl, appId, jwks };
2022-09-02 13:39:15 +00:00
}
2022-09-02 13:39:15 +00:00
return undefined;
}
/**
* Save auth data to file.
* When `authData` argument is empty, will overwrite file with empty values.
*/
private async saveDataToFile(authData?: AuthData) {
debug(`Trying to save auth data to the ${this.fileName} file`);
2022-09-02 13:39:15 +00:00
const newData = authData ? JSON.stringify(authData) : "{}";
2022-09-02 13:39:15 +00:00
try {
await fsPromises.writeFile(this.fileName, newData);
debug("Successfully written file %", this.fileName);
2022-09-02 13:39:15 +00:00
} catch (err) {
debug(`Could not save auth data to the ${this.fileName} file`, err);
throw new Error("File APL was unable to save auth data");
}
}
async get(apiUrl: string) {
2022-09-02 13:39:15 +00:00
const authData = await this.loadDataFromFile();
if (apiUrl === authData?.apiUrl) {
return authData;
}
return undefined;
}
async set(authData: AuthData) {
2022-09-02 13:39:15 +00:00
await this.saveDataToFile(authData);
}
async delete(apiUrl: string) {
2022-09-02 13:39:15 +00:00
const authData = await this.loadDataFromFile();
if (apiUrl === authData?.apiUrl) {
2022-09-02 13:39:15 +00:00
await this.saveDataToFile();
}
}
async getAll() {
2022-09-02 13:39:15 +00:00
const authData = await this.loadDataFromFile();
if (!authData) {
return [];
}
return [authData];
}
// eslint-disable-next-line class-methods-use-this
async isReady(): Promise<AplReadyResult> {
/**
* Assume FileAPL is just ready to use.
* Consider checking if directory is writable
*/
return {
ready: true,
};
}
// eslint-disable-next-line class-methods-use-this
async isConfigured(): Promise<AplConfiguredResult> {
/**
* Assume FileAPL is just ready to use.
* Consider checking if directory is writable
*/
return {
configured: true,
};
}
}