breakout into monorepo

This commit is contained in:
Dominic Ferrando
2026-03-02 13:39:47 -05:00
parent 6421f6527f
commit 45acec2cfd
90 changed files with 12179 additions and 2987 deletions
@@ -0,0 +1,11 @@
import { PrintfulService, WebflowService } from "@blade-and-brawn/commerce";
import type { PageServerLoad } from "./$types";
export const load = async ({ }: Parameters<PageServerLoad>[0]) => {
return {
products: {
printful: PrintfulService.Products.getAll(),
webflow: WebflowService.Products.getAll(),
},
};
};
@@ -0,0 +1,131 @@
<script lang="ts">
import type { Printful } from "@blade-and-brawn/commerce";
import { onMount } from "svelte";
const { data } = $props();
const apiUrl = "http://localhost:3000";
const synchronizer = $state({
isSyncing: false,
syncingIds: [] as number[],
poll: async function () {
const res = (await (
await fetch(`${apiUrl}/products/sync`)
).json()) as any;
if (res.data) {
synchronizer.isSyncing = res.data.isSyncing;
synchronizer.syncingIds = res.data.syncingIds;
}
},
startPolling: () => {
const intervalId = setInterval(async () => {
await synchronizer.poll();
if (!synchronizer.isSyncing) clearInterval(intervalId);
}, 100);
},
syncAll: async () => {
synchronizer.startPolling();
await fetch(`${apiUrl}/products/sync`, { method: "POST" });
},
sync: async (printfulProductId: number) => {
synchronizer.startPolling();
await fetch(`${apiUrl}/products/sync/${printfulProductId}`, {
method: "POST",
});
},
});
onMount(async () => {
await synchronizer.poll();
if (synchronizer.isSyncing) {
synchronizer.startPolling();
}
});
const isProductSynced = async (
printfulProduct: Printful.Products.SyncProduct,
) => {
const webflowProducts = await data.products.webflow;
return webflowProducts.some(
(p) => p.product.id === printfulProduct.external_id.split("-")[0],
);
};
</script>
{#await data.products.printful}
<p>Loading...</p>
{:then printfulProducts}
<button
disabled={synchronizer.isSyncing}
onclick={() => synchronizer.syncAll()}
class="btn btn-xl mb-5"
>
{#if synchronizer.isSyncing}
Syncing...
{:else}
Sync all
{/if}
</button>
<div class="w-full overflow-x-auto">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Status</th>
<th>Sync</th>
</tr>
</thead>
<tbody>
{#each printfulProducts as printfulProduct}
<tr class="hover:bg-base-300">
<td
><button
onclick={async () => {
const productData = (await (
await fetch(
`${apiUrl}/products/${printfulProduct.id}`,
)
).json()) as any;
console.log(productData);
}}
class="cursor-pointer underline"
>
{printfulProduct.name}
</button></td
>
<td>
{#await isProductSynced(printfulProduct) then isSynced}
{#if synchronizer.syncingIds.includes(printfulProduct.id)}
<div class="badge badge-warning">
Syncing...
</div>
{:else if isSynced}
<div class="badge badge-success">
Synced
</div>
{:else}
<div class="badge badge-error">
Desynced
</div>
{/if}
{/await}
</td>
<td>
<button
disabled={synchronizer.isSyncing}
onclick={() =>
synchronizer.sync(printfulProduct.id)}
class="btn"
>
Sync
</button>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{:catch error}
<p>Something went wrong: {error.message}</p>
{/await}