UNPKG

@saleor/app-sdk

Version:

SDK for building great Saleor Apps

239 lines (234 loc) 6.7 kB
import { getOtelTracer } from "../../chunk-4FJHEINB.mjs"; import { createDebug } from "../../chunk-CPDLIPGD.mjs"; // src/APL/dynamodb/dynamodb-apl.ts import { SpanStatusCode } from "@opentelemetry/api"; // src/APL/dynamodb/apl-db-model.ts import { Entity, item, string } from "dynamodb-toolbox"; var AplAccessPattern = class { getPK({ saleorApiUrl }) { return `${saleorApiUrl}`; } /* * APL is singleton, PK will scope to specific installation, * So full path will be like this: * PK: <saleorApiUrl>#<appId> * SK: APL */ getSK() { return "APL"; } }; var AplEntrySchema = item({ PK: string().key(), SK: string().key(), token: string(), saleorApiUrl: string(), appId: string(), jwks: string().optional() }); var createAplEntity = (table) => new Entity({ table, name: "APL", schema: AplEntrySchema, timestamps: { created: { name: "createdAt", savedAs: "createdAt" }, modified: { name: "modifiedAt", savedAs: "modifiedAt" } } }); // src/APL/dynamodb/dynamo-apl-repository.ts import { DeleteItemCommand, GetItemCommand, Parser, PutItemCommand, ScanCommand } from "dynamodb-toolbox"; var DynamoAPLRepository = class { constructor(deps) { this.access = new AplAccessPattern(); this.aplEntity = deps.entity; } async getEntry(args) { const result = await this.aplEntity.build(GetItemCommand).key({ PK: this.access.getPK({ saleorApiUrl: args.saleorApiUrl }), SK: this.access.getSK() }).send(); if (!result.Item) { return null; } const { saleorApiUrl, jwks, token, appId } = AplEntrySchema.build(Parser).parse(result.Item); return { saleorApiUrl, appId, jwks, token }; } async setEntry({ authData }) { await this.aplEntity.build(PutItemCommand).item({ PK: this.access.getPK({ saleorApiUrl: authData.saleorApiUrl }), SK: this.access.getSK(), token: authData.token, saleorApiUrl: authData.saleorApiUrl, appId: authData.appId, jwks: authData.jwks }).send(); return void 0; } async deleteEntry(args) { await this.aplEntity.build(DeleteItemCommand).key({ PK: this.access.getPK({ saleorApiUrl: args.saleorApiUrl }), SK: this.access.getSK() }).send(); return void 0; } async getAllEntries() { const scanEntriesResult = await this.aplEntity.table.build(ScanCommand).entities(this.aplEntity).options({ // keep all the entries in memory - we should introduce pagination in the future maxPages: Infinity }).send(); const possibleItems = scanEntriesResult.Items ?? []; if (possibleItems.length > 0) { return possibleItems.map((item2) => { const { appId, jwks, token, saleorApiUrl } = item2; return { saleorApiUrl, appId, jwks, token }; }); } return null; } }; // src/APL/dynamodb/dynamodb-apl.ts var DynamoAPL = class _DynamoAPL { constructor(deps) { this.tracer = getOtelTracer(); this.debug = createDebug("DynamoAPL"); this.externalLogger = () => { }; this.log = (message, level) => { this.debug(message); this.externalLogger(message, level); }; this.repository = deps.repository; if (deps.externalLogger) { this.externalLogger = deps.externalLogger; } } static create(deps) { return new _DynamoAPL({ repository: new DynamoAPLRepository({ entity: createAplEntity(deps.table) }) }); } async get(saleorApiUrl) { this.log(`get called with saleorApiUrl: ${saleorApiUrl}`, "debug"); return this.tracer.startActiveSpan("DynamoAPL.get", async (span) => { try { const getEntryResult = await this.repository.getEntry({ saleorApiUrl }); span.setStatus({ code: SpanStatusCode.OK }).end(); this.log(`get successful for saleorApiUrl: ${saleorApiUrl}`, "debug"); return getEntryResult ?? void 0; } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR }).end(); this.log( `get error for saleorApiUrl: ${saleorApiUrl}, error: ${JSON.stringify(e)}`, "error" ); throw new Error("GetAuthDataError: Failed to get APL entry", { cause: e }); } }); } async set(authData) { this.log(`set called with authData for saleorApiUrl: ${authData.saleorApiUrl}`, "debug"); return this.tracer.startActiveSpan("DynamoAPL.set", async (span) => { try { await this.repository.setEntry({ authData }); span.setStatus({ code: SpanStatusCode.OK }).end(); this.log(`set successful for saleorApiUrl: ${authData.saleorApiUrl}`, "debug"); } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR }).end(); this.log( `set error for saleorApiUrl: ${authData.saleorApiUrl}, error: ${JSON.stringify(e)}`, "error" ); throw new Error("SetAuthDataError: Failed to set APL entry", { cause: e }); } }); } async delete(saleorApiUrl) { this.log(`delete called with saleorApiUrl: ${saleorApiUrl}`, "debug"); return this.tracer.startActiveSpan("DynamoAPL.delete", async (span) => { try { await this.repository.deleteEntry({ saleorApiUrl }); span.setStatus({ code: SpanStatusCode.OK }).end(); this.log(`delete successful for saleorApiUrl: ${saleorApiUrl}`, "debug"); } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR }).end(); this.log( `delete error for saleorApiUrl: ${saleorApiUrl}, error: ${JSON.stringify(e)}`, "error" ); throw new Error("DeleteAuthDataError: Failed to set APL entry", { cause: e }); } }); } async getAll() { this.log("getAll called", "debug"); return this.tracer.startActiveSpan("DynamoAPL.getAll", async (span) => { try { const getAllEntriesResult = await this.repository.getAllEntries(); span.setStatus({ code: SpanStatusCode.OK }).end(); this.log(`getAll successful, found ${getAllEntriesResult?.length ?? 0} entries`, "debug"); return getAllEntriesResult ?? []; } catch (e) { span.setStatus({ code: SpanStatusCode.ERROR }).end(); this.log(`getAll error: ${JSON.stringify(e)}`, "error"); throw new Error("GetAllAuthDataError: Failed to set APL entry", { cause: e }); } }); } }; export { DynamoAPL };