fake.ts

4.1 kB · typescript · 107 lines

1import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";2import { join, resolve } from "node:path";3import site from "../site.json";45const org = resolve(import.meta.dir, "..");6const shop = resolve(org, "../shop");7const data = join(org, "data");8const DESIGNS = Number(process.env.FAKE_DESIGNS ?? 2);9const HOUR = 60 * 60 * 1000;10const CDN = "https://cdn.shopify.com/s/files/1/0000/0001/files";1112let state = 20260906;1314function next() {15  state = (state * 1103515245 + 12345) % 2147483648;16  return state / 2147483648;17}1819const hex = () => Array.from({ length: 8 }, () => "0123456789abcdef"[Math.floor(next() * 16)]).join("");2021const read = (path: string) => JSON.parse(readFileSync(path, "utf8"));2223const write = (path: string, body: unknown) => {24  mkdirSync(join(path, ".."), { recursive: true });25  writeFileSync(path, JSON.stringify(body, null, 2) + "\n");26};2728const STUB = {29  variants: [30    { id: 1, size: "S", cost: "24.00" },31    { id: 2, size: "M", cost: "24.00" },32    { id: 3, size: "L", cost: "24.00" },33  ],34  mockups: [35    { id: 1, category: "Flat", title: "Front" },36    { id: 2, category: "Lifestyle", title: "Worn" },37  ],38  placements: [{ width: 20, height: 20, dpi: 300 }],39};4041const catalog = read(join(shop, "files", "catalog.json")) as { id: number; live: boolean; category: string; title: string }[];42const products: unknown[] = [];43let stamp = Date.now();4445for (const entry of catalog) {46  const file = join(shop, "data", "products", `${entry.id}.json`);47  if (!existsSync(file) && !entry.live) continue;48  const source = existsSync(file) ? read(file) : STUB;49  const live = (source.variants ?? []).filter((v: { is_ignored: boolean }) => !v.is_ignored);50  const variants = (live.length ? live : source.variants ?? []).filter(51    (v: { size: string }, i: number, all: { size: string }[]) => all.findIndex((o) => o.size === v.size) === i,52  );53  const mockups = (source.mockups ?? []).filter((m: { is_ignored: boolean }) => !m.is_ignored);54  const placements = new Map<string, { width: number; height: number; dpi: number }>();55  for (const place of source.placements ?? []) {56    const id = `${Math.round(place.width * 100)}-${Math.round(place.height * 100)}-${Math.round(place.dpi)}`;57    if (!placements.has(id)) placements.set(id, place);58  }59  if (!variants.length || !mockups.length) {60    console.warn(`fake: ${entry.id} has no live variants or mockups, skipped`);61    continue;62  }63  for (let n = 0; n < DESIGNS; n++) {64    const key = hex();65    stamp -= HOUR;66    const created = new Date(stamp).toISOString();67    const files = [...placements.keys()].map((id) => ({ id, key: hex(), name: "", url: "" }));68    for (const [i, one] of files.entries()) {69      one.name = files.length === 1 ? "printfile" : `printfile-${i + 1}`;70      one.url = `${site.root}/cdn/printful/${key}/${one.name}.png`;71    }72    products.push({73      key,74      type: String(entry.id),75      created,76      available: true,77      variants: variants.map((v: { id: number; size: string; cost: string }) => ({78        id: String(4000000000000 + Math.floor(next() * 1000000000)),79        size: v.size,80        price: Number(v.cost || "20").toFixed(2),81        available: true,82      })),83      images: mockups.map((m: { id: number; category: string; title: string }) => {84        const name = `${key}-${hex()}`;85        return { url: `${CDN}/${name}.png?v=1`, alt: `${m.id} - ${m.category} - ${m.title}`, style: String(m.id) };86      }),87      files: files.map((one) => one.name),88    });89    write(join(data, "tasks", key, `${key}.json`), {90      key,91      step: "ARCHIVE",92      seed: Math.floor(next() * 1000000),93      created_at: stamp,94      updated_at: stamp,95      product: { id: entry.id, category: entry.category, title: entry.title },96      variation: {},97      printfiles: files.map((one) => ({ ...one, width: 20, height: 20, dpi: 300 })),98      placements: [...placements.values()],99      variants: [],100      mockups: [],101      metadata: {},102    });103  }104}105106write(join(data, "shop.json"), { at: Date.now(), products });107console.log(`fake: ${products.length} products from ${catalog.length} catalog rows into data/shop.json`);