saleor-apps-redis_apl/apps/cms-v2/src/modules/providers/builder.io/builder-io.client.ts

146 lines
4.4 KiB
TypeScript
Raw Normal View History

CMS App v2 (#721) * initial setup * GRaphql setup * [skip ci] * Manifest and register endpoints * Add config schemas * contentful client * contentful client * [skip ci] trpc setup * metadata manager and contentful router * Configuration config * contentful config - adding providers * add provider page * wip contentful form * contentful form * list providrs * edit contentful form * [skip ci] * [skip ci] replace contentful sdk * replace contentful lib * Delete contetnful provider feature * variant created webhook draft * channel provider connection model * Channel connections ui * adding new connection * connections ui (adding) * [skip ci] wip edit conn * removing connection * rebuild modal * refactor providers * implement update product webhook * add deleting product * [skip ci] wip * refactor contentful router * refactor wip * refactor config * webhooks processor * webhook delegations * bulk sync section * bulk sync page * gql for imports * [skip ci] bulk import contentful * temp variant sync list with rate limiters * wip * wip * wip * new frontend for uploading * update zod * print config keys * wip * [skip ci] datocms init * dato add provdier page * dato form skeleton * dato display content type select * full dato form * ButtonsBox extraction * edit dato config form * update product in dato * [skip ci] * extract bulk sync processor * dato bulk update * [skip ci] product updated webhook * product webhook * crud operations router * update cruds * refactor webhook operations * refactors * refactors * helper texts * [skip ci] deps * Init * fix macaw icon * unify app skd * unify nextjs * strapi setup * fix strapi types * strapi upload product * strapi delete product * strapi product updated webhook * processor for bulk sync strapi * shared add provider page * refactors * refactors * wrap providers into folder * refactors * refactors * refactors * pnpm lock * add logs * name configuration mapping name * form configurable side notes * remove commentns * wip providers resolver working * central config for providers resolving * tests wip * remove vscode condig * cleanup * provider meta extract * some tests for contentufl * contentful client test * more tests for contentful * strapi helper texts * builderio setup * builderio form * builderio client draft * validate connection modal * Add sending product to builderio * rename builder field * add public api key for read access * update products * Builder.io - bulk sync * Fix manifest * cr fixes * Make strapi to work with multiple products * Github actions
2023-07-18 08:19:21 +00:00
import { BuilderIoProviderConfig } from "@/modules/configuration";
import { WebhookProductVariantFragment } from "../../../../generated/graphql";
import { createLogger } from "@saleor/apps-shared";
import { FieldsMapper } from "../fields-mapper";
CMS App v2 (#721) * initial setup * GRaphql setup * [skip ci] * Manifest and register endpoints * Add config schemas * contentful client * contentful client * [skip ci] trpc setup * metadata manager and contentful router * Configuration config * contentful config - adding providers * add provider page * wip contentful form * contentful form * list providrs * edit contentful form * [skip ci] * [skip ci] replace contentful sdk * replace contentful lib * Delete contetnful provider feature * variant created webhook draft * channel provider connection model * Channel connections ui * adding new connection * connections ui (adding) * [skip ci] wip edit conn * removing connection * rebuild modal * refactor providers * implement update product webhook * add deleting product * [skip ci] wip * refactor contentful router * refactor wip * refactor config * webhooks processor * webhook delegations * bulk sync section * bulk sync page * gql for imports * [skip ci] bulk import contentful * temp variant sync list with rate limiters * wip * wip * wip * new frontend for uploading * update zod * print config keys * wip * [skip ci] datocms init * dato add provdier page * dato form skeleton * dato display content type select * full dato form * ButtonsBox extraction * edit dato config form * update product in dato * [skip ci] * extract bulk sync processor * dato bulk update * [skip ci] product updated webhook * product webhook * crud operations router * update cruds * refactor webhook operations * refactors * refactors * helper texts * [skip ci] deps * Init * fix macaw icon * unify app skd * unify nextjs * strapi setup * fix strapi types * strapi upload product * strapi delete product * strapi product updated webhook * processor for bulk sync strapi * shared add provider page * refactors * refactors * wrap providers into folder * refactors * refactors * refactors * pnpm lock * add logs * name configuration mapping name * form configurable side notes * remove commentns * wip providers resolver working * central config for providers resolving * tests wip * remove vscode condig * cleanup * provider meta extract * some tests for contentufl * contentful client test * more tests for contentful * strapi helper texts * builderio setup * builderio form * builderio client draft * validate connection modal * Add sending product to builderio * rename builder field * add public api key for read access * update products * Builder.io - bulk sync * Fix manifest * cr fixes * Make strapi to work with multiple products * Github actions
2023-07-18 08:19:21 +00:00
// https://www.builder.io/c/docs/write-api
export class BuilderIoClient {
private endpoint: string;
private logger = createLogger({ name: "BuilderIoClient" });
constructor(private config: BuilderIoProviderConfig.FullShape) {
this.endpoint = `https://builder.io/api/v1/write/${config.modelName}`;
}
private mapVariantToFields(variant: WebhookProductVariantFragment) {
return FieldsMapper.mapProductVariantToConfigurationFields({
variant,
configMapping: this.config.productVariantFieldsMapping,
});
CMS App v2 (#721) * initial setup * GRaphql setup * [skip ci] * Manifest and register endpoints * Add config schemas * contentful client * contentful client * [skip ci] trpc setup * metadata manager and contentful router * Configuration config * contentful config - adding providers * add provider page * wip contentful form * contentful form * list providrs * edit contentful form * [skip ci] * [skip ci] replace contentful sdk * replace contentful lib * Delete contetnful provider feature * variant created webhook draft * channel provider connection model * Channel connections ui * adding new connection * connections ui (adding) * [skip ci] wip edit conn * removing connection * rebuild modal * refactor providers * implement update product webhook * add deleting product * [skip ci] wip * refactor contentful router * refactor wip * refactor config * webhooks processor * webhook delegations * bulk sync section * bulk sync page * gql for imports * [skip ci] bulk import contentful * temp variant sync list with rate limiters * wip * wip * wip * new frontend for uploading * update zod * print config keys * wip * [skip ci] datocms init * dato add provdier page * dato form skeleton * dato display content type select * full dato form * ButtonsBox extraction * edit dato config form * update product in dato * [skip ci] * extract bulk sync processor * dato bulk update * [skip ci] product updated webhook * product webhook * crud operations router * update cruds * refactor webhook operations * refactors * refactors * helper texts * [skip ci] deps * Init * fix macaw icon * unify app skd * unify nextjs * strapi setup * fix strapi types * strapi upload product * strapi delete product * strapi product updated webhook * processor for bulk sync strapi * shared add provider page * refactors * refactors * wrap providers into folder * refactors * refactors * refactors * pnpm lock * add logs * name configuration mapping name * form configurable side notes * remove commentns * wip providers resolver working * central config for providers resolving * tests wip * remove vscode condig * cleanup * provider meta extract * some tests for contentufl * contentful client test * more tests for contentful * strapi helper texts * builderio setup * builderio form * builderio client draft * validate connection modal * Add sending product to builderio * rename builder field * add public api key for read access * update products * Builder.io - bulk sync * Fix manifest * cr fixes * Make strapi to work with multiple products * Github actions
2023-07-18 08:19:21 +00:00
}
async uploadProductVariant(variant: WebhookProductVariantFragment) {
this.logger.debug({ variantId: variant.id }, "uploadProductVariant called");
try {
const response = await fetch(this.endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this.config.privateApiKey}`,
},
body: JSON.stringify({
data: this.mapVariantToFields(variant),
published: "published",
}),
});
} catch (err) {
this.logger.error(err, "Failed to upload product variant");
throw err;
}
}
private async updateProductVariantCall(
builderIoEntryId: string,
variant: WebhookProductVariantFragment
) {
try {
const response = await fetch(this.endpoint + `/${builderIoEntryId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this.config.privateApiKey}`,
},
body: JSON.stringify({
data: this.mapVariantToFields(variant),
published: "published",
}),
});
} catch (err) {
this.logger.error(err, "Failed to upload product variant");
throw err;
}
}
async updateProductVariant(variant: WebhookProductVariantFragment) {
const entriesToUpdate = await this.fetchBuilderIoEntryIds(variant.id);
this.logger.debug(
{
entriesToUpdate,
},
"Trying to update variants in builder.io with following IDs"
);
return Promise.all(
entriesToUpdate.map((id) => {
return this.updateProductVariantCall(id, variant);
})
);
}
async upsertProductVariant(variant: WebhookProductVariantFragment) {
const entriesToUpdate = await this.fetchBuilderIoEntryIds(variant.id);
if (entriesToUpdate.length === 0) {
this.logger.debug("Didnt find any entries to update, will upload new variant");
return this.uploadProductVariant(variant);
} else {
this.logger.debug({ entriesToUpdate }, "Found entries in builder.io, will update them");
return Promise.all(
entriesToUpdate.map((id) => {
return this.updateProductVariantCall(id, variant);
})
);
}
}
async deleteProductVariant(variantId: string) {
const idsToDelete = await this.fetchBuilderIoEntryIds(variantId);
this.logger.debug({ ids: idsToDelete }, "Will try to delete items in Builder.io");
return Promise.all(
idsToDelete.map((id) =>
fetch(this.endpoint + `/${id}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this.config.privateApiKey}`,
},
})
)
);
}
/**
* Can return more than 1. Builder doesnt have unique fields.
*/
private fetchBuilderIoEntryIds(variantId: string): Promise<string[]> {
this.logger.trace(
{
modelName: this.config.modelName,
variantID: variantId,
variantFieldMapping: this.config.productVariantFieldsMapping.variantId,
},
"Trying to fetch variant from Builder.io"
);
return fetch(
`https://cdn.builder.io/api/v3/content/${this.config.modelName}?apiKey=${this.config.publicApiKey}&query.data.${this.config.productVariantFieldsMapping.variantId}.$eq=${variantId}&limit=10&includeUnpublished=false&cacheSeconds=0`
)
.then((res) => res.json())
.then((data) => {
return data.results.map((result: any) => result.id) as string[];
})
.catch((err) => {
this.logger.error(err, "Failed to fetch builder.io entry id");
throw err;
});
}
}