This commit is contained in:
jackbeeby
2024-12-05 18:20:27 +11:00
parent b8de0556ec
commit dc5eea1ad0
288 changed files with 101937 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
import {
EncryptedMetadataManager,
type MetadataEntry,
MetadataManager,
type MutateMetadataCallback,
} from "@saleor/app-sdk/settings-manager";
import { type Client } from "urql";
import {
FetchAppDetailsDocument,
type FetchAppDetailsQuery,
UpdateAppMetadataDocument,
UpdatePublicMetadataDocument,
} from "../../../generated/graphql";
import { env } from "@/lib/env.mjs";
export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]> {
const { error, data } = await client
.query<FetchAppDetailsQuery>(FetchAppDetailsDocument, {})
.toPromise();
if (error) {
return [];
}
const combinedMetadata = [...(data?.app?.metadata || []), ...(data?.app?.privateMetadata || [])];
return combinedMetadata.map((md) => ({ key: md.key, value: md.value }));
}
async function getAppId(client: Client) {
const { error: idQueryError, data: idQueryData } = await client
.query(FetchAppDetailsDocument, {})
.toPromise();
if (idQueryError) {
throw new Error(
"Could not fetch the app id. Please check if auth data for the client are valid.",
);
}
const appId = idQueryData?.app?.id;
if (!appId) {
throw new Error("Could not fetch the app ID");
}
return appId;
}
export async function mutatePrivateMetadata(client: Client, metadata: MetadataEntry[]) {
// to update the metadata, ID is required
const appId = await getAppId(client);
const { error: mutationError, data: mutationData } = await client
.mutation(UpdateAppMetadataDocument, {
id: appId,
input: metadata,
})
.toPromise();
if (mutationError) {
throw new Error(`Mutation error: ${mutationError.message}`);
}
return (
mutationData?.updatePrivateMetadata?.item?.privateMetadata.map((md) => ({
key: md.key,
value: md.value,
})) || []
);
}
export async function mutatePublicMetadata(client: Client, metadata: MetadataEntry[]) {
// to update the metadata, ID is required
const appId = await getAppId(client);
const { error: mutationError, data: mutationData } = await client
.mutation(UpdatePublicMetadataDocument, {
id: appId,
input: metadata,
})
.toPromise();
if (mutationError) {
throw new Error(`Mutation error: ${mutationError.message}`);
}
return (
mutationData?.updateMetadata?.item?.metadata.map((md) => ({
key: md.key,
value: md.value,
})) || []
);
}
// branded types are used to prevent using wrong manager for wrong metadata
type Brand<K, T> = K & { __brand: T };
export type BrandedEncryptedMetadataManager = Brand<
EncryptedMetadataManager,
"EncryptedMetadataManager"
>;
export type BrandedMetadataManager = Brand<MetadataManager, "MetadataManager">;
export const createPrivateSettingsManager = (client: Client) => {
// EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory.
// We recommend it for production, because all values are encrypted.
// If your use case require plain text values, you can use MetadataManager.
return new EncryptedMetadataManager({
// Secret key should be randomly created for production and set as environment variable
encryptionKey: env.SECRET_KEY,
fetchMetadata: () => fetchAllMetadata(client),
mutateMetadata: (metadata) => mutatePrivateMetadata(client, metadata),
}) as BrandedEncryptedMetadataManager;
};
export const createPublicSettingsManager = (client: Client) => {
return new MetadataManager({
fetchMetadata: () => fetchAllMetadata(client),
mutateMetadata: (metadata) => mutatePublicMetadata(client, metadata),
}) as BrandedMetadataManager;
};
export const createWebhookPrivateSettingsManager = (
data: MetadataEntry[],
onUpdate?: MutateMetadataCallback,
) => {
return new EncryptedMetadataManager({
encryptionKey: env.SECRET_KEY,
fetchMetadata: () => Promise.resolve(data),
mutateMetadata: onUpdate ?? (() => Promise.resolve([])),
}) as BrandedEncryptedMetadataManager;
};
export const createWebhookPublicSettingsManager = (
data: MetadataEntry[],
onUpdate?: MutateMetadataCallback,
) => {
return new MetadataManager({
fetchMetadata: () => Promise.resolve(data),
mutateMetadata: onUpdate ?? (() => Promise.resolve([])),
}) as BrandedMetadataManager;
};