stripe-astro-loader
Version:
Load Stripe data in Astro.
127 lines (123 loc) • 3.59 kB
JavaScript
// src/utils.ts
import { z } from "astro/zod";
import { AstroError } from "astro/errors";
import Stripe from "stripe";
function stripeTsToZod() {
return z.custom(() => true);
}
async function paginateStripeAPI(listFunction, options, context, metaKey, renderItem) {
const { logger, parseData, store, meta, generateDigest } = context;
const { limit = Infinity, ...queryParams } = options;
let allItems = [];
let hasMore = true;
let lastId;
const lastUpdated = meta.get(metaKey);
if (lastUpdated) {
queryParams.created = { gt: parseInt(lastUpdated) };
}
while (hasMore && allItems.length < limit) {
const params = {
...queryParams,
limit: Math.min(100, limit - allItems.length),
starting_after: lastId
};
try {
const response = await listFunction(params);
for (const item of response.data) {
if (allItems.length >= limit) break;
const data = await parseData({ id: item.id, data: item });
const digest = generateDigest(data);
const storeItem = {
id: item.id,
data,
digest
};
if (renderItem) {
const renderedHtml = renderItem(item);
if (renderedHtml) {
storeItem.rendered = { html: renderedHtml };
}
}
const changed = store.set(storeItem);
if (changed) {
logger.debug(`Updated item: ${item.id}`);
}
allItems.push(item);
}
hasMore = response.has_more && allItems.length < limit;
lastId = response.data[response.data.length - 1]?.id;
if (response.data.length > 0) {
const latestUpdated = Math.max(
...response.data.map((item) => item.created)
);
meta.set(metaKey, latestUpdated.toString());
}
} catch (error) {
if (error instanceof Stripe.errors.StripeError) {
throw new AstroError(`Stripe API error: ${error.message}`);
}
throw error;
}
logger.info(`Loaded ${allItems.length} items from Stripe so far`);
}
logger.info(`Finished loading ${allItems.length} items from Stripe`);
return allItems;
}
// src/product-loader.ts
import "stripe";
var zodSchemaFromStripeProducts = stripeTsToZod();
function stripeProductLoader(stripe, options = {}) {
return {
name: "stripe-product-loader",
load: async (context) => {
await paginateStripeAPI(
stripe.products.list.bind(stripe.products),
options,
context,
"stripe-products-last-updated",
(product) => product.description || null
);
},
schema: zodSchemaFromStripeProducts
};
}
// src/price-loader.ts
import "stripe";
var zodSchemaFromStripePrices = stripeTsToZod();
function stripePriceLoader(stripe, options = {}) {
return {
name: "stripe-price-loader",
load: async (context) => {
await paginateStripeAPI(
stripe.prices.list.bind(stripe.prices),
options,
context,
"stripe-prices-last-updated"
);
},
schema: zodSchemaFromStripePrices
};
}
// src/plan-loader.ts
import "stripe";
var zodSchemaFromStripePlans = stripeTsToZod();
function stripePlanLoader(stripe, options = {}) {
return {
name: "stripe-plan-loader",
load: async (context) => {
await paginateStripeAPI(
stripe.plans.list.bind(stripe.plans),
options,
context,
"stripe-plans-last-updated",
(plan) => plan.nickname || null
);
},
schema: zodSchemaFromStripePlans
};
}
export {
stripePlanLoader,
stripePriceLoader,
stripeProductLoader
};