view design_system/main.c @ 255:5ec271d612ae

[dowa] Enforce arena ownership Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Tue, 04 Aug 2026 15:12:18 -0700
parents 2b6e732087ff
children 60a876c4587a
line wrap: on
line source

#include "seobeo/seobeo.h"

#include <stdlib.h>
#include <string.h>

static const char *const COMPONENT_PATHS[] = {
    "/components/accordion",
    "/components/alert",
    "/components/alert-dialog",
    "/components/aspect-ratio",
    "/components/attachment",
    "/components/avatar",
    "/components/badge",
    "/components/breadcrumb",
    "/components/bubble",
    "/components/button",
    "/components/button-group",
    "/components/calendar",
    "/components/card",
    "/components/carousel",
    "/components/chart",
    "/components/checkbox",
    "/components/collapsible",
    "/components/combobox",
    "/components/command",
    "/components/context-menu",
    "/components/data-table",
    "/components/date-picker",
    "/components/dialog",
    "/components/direction",
    "/components/drawer",
    "/components/dropdown-menu",
    "/components/empty",
    "/components/field",
    "/components/form",
    "/components/hover-card",
    "/components/input",
    "/components/input-group",
    "/components/input-otp",
    "/components/item",
    "/components/kbd",
    "/components/label",
    "/components/marker",
    "/components/menubar",
    "/components/message",
    "/components/message-scroller",
    "/components/native-select",
    "/components/navigation-menu",
    "/components/notifications",
    "/components/pagination",
    "/components/popover",
    "/components/progress",
    "/components/radio-group",
    "/components/resizable",
    "/components/scroll-area",
    "/components/select",
    "/components/separator",
    "/components/sheet",
    "/components/sidebar",
    "/components/skeleton",
    "/components/slider",
    "/components/sonner",
    "/components/spinner",
    "/components/stack",
    "/components/switch",
    "/components/table",
    "/components/tabs",
    "/components/textarea",
    "/components/toast",
    "/components/toggle",
    "/components/toggle-group",
    "/components/tooltip",
    "/components/typography",
};

static Seobeo_Request_Entry *Get_Component_Catalog(
    Seobeo_Request_Entry *request,
    Dowa_Arena *arena)
{
  (void)request;
  size_t file_size = 0;
  char *source = Seobeo_Web_LoadFile("/index.html", &file_size);
  if (!source)
  {
    Seobeo_Request_Entry *response = NULL;
    Dowa_HashMap_Push_Arena(response, "status", "500", arena);
    Dowa_HashMap_Push_Arena(
        response,
        "content-type",
        "text/plain; charset=utf-8",
        arena);
    Dowa_HashMap_Push_Arena(
        response,
        "body",
        "Component catalog is unavailable.",
        arena);
    return response;
  }

  char *body = Dowa_Arena_Allocate(arena, file_size + 1);
  if (!body)
  {
    free(source);
    return NULL;
  }
  memcpy(body, source, file_size + 1);
  free(source);

  char *content_length = Dowa_Arena_Allocate(arena, 32);
  snprintf(content_length, 32, "%zu", file_size);
  Seobeo_Request_Entry *response = NULL;
  Dowa_HashMap_Push_Arena(response, "status", "200", arena);
  Dowa_HashMap_Push_Arena(
      response,
      "content-type",
      "text/html; charset=utf-8",
      arena);
  Dowa_HashMap_Push_Arena(
      response,
      "content-length",
      content_length,
      arena);
  Dowa_HashMap_Push_Arena(response, "body", body, arena);
  return response;
}

static boolean Port_Is_Valid(const char *port)
{
  if (!port || port[0] == '\0')
    return FALSE;
  char *end = NULL;
  long value = strtol(port, &end, 10);
  return end != port &&
      *end == '\0' &&
      value > 0 &&
      value <= 65535;
}

int main(void)
{
  Seobeo_Router_Init();
  Seobeo_Router_Register("GET", "/", Get_Component_Catalog);
  Seobeo_Router_Register("GET", "/tokens", Get_Component_Catalog);
  Seobeo_Router_Register("GET", "/icons", Get_Component_Catalog);
  Seobeo_Router_Register("GET", "/components", Get_Component_Catalog);
  for (size_t i = 0;
       i < sizeof(COMPONENT_PATHS) / sizeof(COMPONENT_PATHS[0]);
       i++)
  {
    Seobeo_Router_Register(
        "GET",
        COMPONENT_PATHS[i],
        Get_Component_Catalog);
  }

  const char *port = getenv("DESIGN_SYSTEM_PORT");
  if (!port || port[0] == '\0')
    port = "6980";
  if (!Port_Is_Valid(port))
  {
    Seobeo_Log(SEOBEO_ERROR, "Invalid design-system port: %s\n", port);
    Seobeo_Router_Destroy();
    return 1;
  }
  int result = Seobeo_Web_Server_Start_On(
      "127.0.0.1",
      "design_system/src",
      port,
      SEOBEO_MODE_EDGE,
      2);
  Seobeo_Router_Destroy();
  return result;
}