@saleor/app-sdk
Version:
SDK for building great Saleor Apps
168 lines (166 loc) • 5.29 kB
JavaScript
import {
OTEL_APL_SERVICE_NAME,
getOtelTracer
} from "../../chunk-UCTHLSSD.mjs";
import {
createAPLDebug
} from "../../chunk-ORQVZRNL.mjs";
import "../../chunk-CPDLIPGD.mjs";
// src/APL/vercel-kv/vercel-kv-apl.ts
import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
import { SemanticAttributes } from "@opentelemetry/semantic-conventions";
import { kv } from "@vercel/kv";
var VercelKvApl = class {
constructor(options) {
this.debug = createAPLDebug("VercelKvApl");
this.tracer = getOtelTracer();
/**
* Store all items inside hash collection, to enable read ALL items when needed.
* Otherwise, multiple redis calls will be needed to iterate over every key.
*
* To allow connecting many apps to single KV storage, we need to use different hash collection key for each app.
*/
this.hashCollectionKey = process.env.KV_STORAGE_NAMESPACE;
if (!this.envVariablesRequiredByKvExist()) {
throw new Error("Missing KV env variables, please link KV storage to your project");
}
this.hashCollectionKey = options?.hashCollectionKey ?? this.hashCollectionKey;
}
async get(saleorApiUrl) {
this.debug("Will call Vercel KV to get auth data for %s", saleorApiUrl);
return this.tracer.startActiveSpan(
"VercelKvApl.get",
{
attributes: {
saleorApiUrl,
[SemanticAttributes.PEER_SERVICE]: OTEL_APL_SERVICE_NAME
},
kind: SpanKind.CLIENT
},
async (span) => {
try {
const authData = await kv.hget(this.hashCollectionKey, saleorApiUrl);
this.debug("Received response from VercelKV");
if (!authData) {
this.debug("AuthData is empty for %s", saleorApiUrl);
}
span.setStatus({
code: SpanStatusCode.OK,
message: "Received response from VercelKV"
}).end();
return authData ?? void 0;
} catch (e) {
this.debug("Failed to get auth data from Vercel KV");
this.debug(e);
span.recordException("Failed to get auth data from Vercel KV");
span.setStatus({
code: SpanStatusCode.ERROR,
message: "Failed to get auth data from Vercel KV"
}).end();
throw e;
}
}
);
}
async set(authData) {
this.debug("Will call Vercel KV to set auth data for %s", authData.saleorApiUrl);
return this.tracer.startActiveSpan(
"VercelKvApl.set",
{
attributes: {
saleorApiUrl: authData.saleorApiUrl,
appId: authData.appId,
[SemanticAttributes.PEER_SERVICE]: OTEL_APL_SERVICE_NAME
},
kind: SpanKind.CLIENT
},
async (span) => {
try {
await kv.hset(this.hashCollectionKey, {
[authData.saleorApiUrl]: authData
});
span.setStatus({
code: SpanStatusCode.OK,
message: "Successfully written auth data to VercelKV"
}).end();
} catch (e) {
this.debug("Failed to set auth data in Vercel KV");
this.debug(e);
span.recordException("Failed to set auth data in Vercel KV");
span.setStatus({
code: SpanStatusCode.ERROR
}).end();
throw e;
}
}
);
}
async delete(saleorApiUrl) {
this.debug("Will call Vercel KV to delete auth data for %s", saleorApiUrl);
return this.tracer.startActiveSpan(
"VercelKvApl.delete",
{
attributes: {
saleorApiUrl,
[SemanticAttributes.PEER_SERVICE]: OTEL_APL_SERVICE_NAME
},
kind: SpanKind.CLIENT
},
async (span) => {
try {
await kv.hdel(this.hashCollectionKey, saleorApiUrl);
span.setStatus({
code: SpanStatusCode.OK,
message: "Successfully deleted auth data to VercelKV"
}).end();
} catch (e) {
this.debug("Failed to delete auth data from Vercel KV");
this.debug(e);
span.recordException("Failed to delete auth data from Vercel KV");
span.setStatus({
code: SpanStatusCode.ERROR
}).end();
throw e;
}
}
);
}
async getAll() {
const results = await kv.hgetall(this.hashCollectionKey);
if (results === null) {
throw new Error("Missing KV collection, data was never written");
}
return Object.values(results);
}
async isReady() {
const ready = this.envVariablesRequiredByKvExist();
return ready ? {
ready: true
} : {
ready: false,
error: new Error("Missing KV env variables, please link KV storage to your project")
};
}
async isConfigured() {
const configured = this.envVariablesRequiredByKvExist();
return configured ? {
configured: true
} : {
configured: false,
error: new Error("Missing KV env variables, please link KV storage to your project")
};
}
envVariablesRequiredByKvExist() {
const variables = [
"KV_REST_API_URL",
"KV_REST_API_TOKEN",
"KV_REST_API_READ_ONLY_TOKEN",
"KV_STORAGE_NAMESPACE",
"KV_URL"
];
return variables.every((variable) => !!process.env[variable]);
}
};
export {
VercelKvApl
};