@saleor/app-sdk
Version:
SDK for building great Saleor Apps
239 lines (234 loc) • 6.7 kB
JavaScript
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
};