برنامه نویسی

ساخت یک آنالایزر رفتار مالی با قدرت AI با NodeJS ، Python ، Sveltekit و Tailwindcs – قسمت 4

مقدمه

قسمت 5 در حال حاضر در حال حاضر است: https://johnowolabiidogun.dev/blog/asynchronous-server-building-and-rigorously-testing-a-websocket-and-http-server-3918df/67b0ab3c7a900ac23e502c51

در این بخش از این سریال ، ما کنترل کننده WebSocket سرویس پس زمینه خود را پیاده سازی خواهیم کرد و ساخت جلوی آن را شروع می کنیم. این امر باعث می شود تا ارتباطات در زمان واقعی بین پس زمینه و جبهه امکان پذیر باشد و به ما امکان می دهد تا در صورت دسترسی ، نتایج تجزیه و تحلیل را نمایش دهیم.

پیش نیاز

پیش نیاز اصلی این است که شما مقالات قبلی را در این سری طی کرده اید. این تضمین می کند که زمینه و محیط لازم را تنظیم کنید.

رمز منبع

آنالایزر و مشاور رفتار مالی با هوش مصنوعی که در پایتون (AIOHTTP) و TypeScript نوشته شده است (Expressjs & Sveltekit با Svelte 5)

اجرای

مرحله: کنترل کننده WebSocket

برای ارائه به روزرسانی های زمان واقعی برای تجزیه و تحلیل داده های مالی و خلاصه ها ، ما به جای درخواست های سنتی HTTP که نیاز به طراوت مداوم دارند ، از WebSockets ، یک پروتکل ارتباطی دو طرفه استفاده می کنیم. در TransactionWebSocketHandler عملکرد اتصالات WebSocket را مدیریت می کند:

import { WebSocket } from "ws";
import { TransactionService } from "$services/transaction.service.js";
import { baseConfig } from "$config/base.config.js";
import mongoose from "mongoose";
import { sendError } from "$utils/error.utils.js";

export function TransactionWebSocketHandler(ws: WebSocket): void {
  ws.on("message", async (message: string) => {
    try {
      const actions = JSON.parse(message);

      if (!Array.isArray(actions)) {
        sendError(ws, "Invalid message format. Expected an array.");
        return;
      }

      for (const actionObj of actions) {
        if (!actionObj.action || !actionObj.userId) {
          sendError(
            ws,
            "Invalid action format. Each action requires 'action' and 'userId'."
          );
          return;
        }

        const { action, userId } = actionObj;

        if (!mongoose.Types.ObjectId.isValid(userId)) {
          sendError(ws, "Invalid userId format.");
          return;
        }

        switch (action) {
          case "analyze":
          case "summary":
            await handleAction(ws, new mongoose.Types.ObjectId(userId), action);
            break;
          default:
            sendError(ws, `Unknown action: ${action}`);
        }
      }
    } catch (error) {
      baseConfig.logger.error(
        `Error processing message: ${
          error instanceof Error ? error.message : error
        }`
      );
      sendError(
        ws,
        `Failed to process message: ${
          error instanceof Error ? error.message : error
        }`
      );
    }
  });

  ws.on("close", () => {
    baseConfig.logger.info("Frontend WebSocket connection closed");
  });

  ws.on("error", (error) => {
    baseConfig.logger.error(`WebSocket error: ${error.message}`);
  });
}

async function handleAction(
  frontendWs: WebSocket,
  userId: mongoose.Types.ObjectId,
  action: string
) {
  try {
    const transactions = await TransactionService.findTransactionsByUserId(
      userId,
      -1,
      -1
    );

    if (!transactions) {
      sendError(
        frontendWs,
        `No transactions found for userId: ${userId}`,
        action
      );
      return;
    }

    await TransactionService.connectToUtilityServer(
      action,
      transactions.transactions,
      frontendWs
    );
  } catch (error) {
    baseConfig.logger.error(
      `Error handling action: ${error instanceof Error ? error.message : error}`
    );
    sendError(
      frontendWs,
      `Failed to handle action: ${
        error instanceof Error ? error.message : error
      }`
    );
  }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

با استفاده از ws ماژول (در مقاله قبلی نصب شده است) ، این عملکرد اتصال WebSocket را تنظیم می کند و برای پیام های ورودی ، اتصال نزدیک و خطاها ، دستگیرندگان را تعریف می کند. به محض دریافت پیام ، پاسخ به تماس برای message شنونده رویداد اخراج می شود و به شرح زیر است:

  • پیام های دریافتی به عنوان JSON ، انتظار مجموعه ای از اقدامات را دارند.
  • فرمت هر عمل را تأیید می کند ، و از آن اطمینان حاصل می کند action وت userIdبشر
  • تأیید می کند userId برای اطمینان از این که یک ObjectId معتبر Mongoose است.
  • از a استفاده می کند switch جمله ای برای رسیدگی به اقدامات مختلف (analyze وت summary)) ، و
  • تماس handleAction عملکرد برای پردازش هر عمل معتبر.

در handleAction اقدامات خاص درخواست شده توسط مشتری را با بازیابی معاملات برای مشخص شده انجام می دهد userId با استفاده از TransactionService.findTransactionsByUserId روش استاتیک در مقاله قبلی مورد بحث قرار گرفته است. هرگونه معاملات بازیابی شده از طریق ارسال می شود TransactionService.connectToUtilityServer روش به سرور ابزار برای تجزیه و تحلیل یا خلاصه.

بیایید این کنترل کننده را در برنامه ما ثبت کنیم:

...
import { WebSocketServer } from "ws";
...
import { TransactionWebSocketHandler } from "$websockets/transaction.websocket.js";
...
const startServer = async () => {
  try {
    const server: HttpServer = createServer(app);
    const wss = new WebSocketServer({ server, path: "/ws" });

    // 5. Setup WebSocket handlers
    wss.on("connection", (ws) => {
      TransactionWebSocketHandler(ws);
    });

    // 6. Connect to MongoDB
    baseConfig.logger.info("Connecting to MongoDB cluster...");
    const db = await connectToCluster();

    ...
  } catch (error) {
    baseConfig.logger.error("Error starting server:", error);
    process.exit(1);
  }
};
startServer();
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

با این کار ، ما سرویس باطن را نتیجه می گیریم. اکنون وقت آن رسیده است که Sveltekit را با Tailwindcss تنظیم کنید.

مرحله 2: sveltekit با tailwindcss

برای راه اندازی یک پروژه Sveltekit با Tailwindcss ، ما با برخی از اصلاحات از راهنمای مهاجرت که قبلاً نوشتم ، به راهنمای رسمی Tailwindcss مراجعه خواهیم کرد.

ابتدا یک پروژه جدید Sveltekit را از طریق Svelte 5 ایجاد کنید sv CLI:

$ npx sv create interface # modify the name as you please
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

از شما خواسته می شود نصب کنید sv که باید به آن لهجه کنید. تعامل شما با CLI باید به این شکل باشد:

projects npx sv create interface
Need to install the following packages:
sv@0.6.18
Ok to proceed? (y) y

┌  Welcome to the Svelte CLI! (v0.6.18)
│
◇  Which template would you like?
│  SvelteKit minimal
│
◇  Add type checking with Typescript?
│  Yes, using Typescript syntax
│
◆  Project created
│
◇  What would you like to add to your project? (use arrow keys / space bar)
│  prettier, eslint, vitest, tailwindcss, sveltekit-adapter
│
◇  tailwindcss: Which plugins would you like to add?
│  typography, forms
│
◇  sveltekit-adapter: Which SvelteKit adapter would you like to use?
│  node
│
◇  Which package manager do you want to install dependencies with?
│  npm
│
◆  Successfully setup add-ons
│
◆  Successfully installed dependencies
│
◇  Successfully formatted modified files
│
◇  Project next steps ─────────────────────────────────────────────────────╮
│                                                                          │
│  1: cd interface                                                         │
│  2: git init && git add -A && git commit -m "Initial commit" (optional)  │
│  3: npm run dev -- --open                                                │
│                                                                          │
│  To close the dev server, hit Ctrl-C                                     │
│                                                                          │
│  Stuck? Visit us at https://svelte.dev/chat                              │
│                                                                          │
├──────────────────────────────────────────────────────────────────────────╯
│
└  You're all set!
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

در صورت تمایل می توانید هر یک از مراحل را همانطور که دوست دارید اصلاح کنید. می توانید فهرست را به پروژه تازه ایجاد شده تغییر داده و وابستگی ها را نصب کنید.

به دلایلی ، tailwindcss نصب شده توسط sv نسخه بود 3.4.17بشر با این حال ، در زمان نوشتن این ، Tailwindcss در حال حاضر در نسخه است 4.0.2بشر بنابراین ما باید مهاجرت کنیم. برای جلوگیری از مراحل مهاجرت ، این دستور را اجرا کنید:

interface$ npx @tailwindcss/upgrade@next
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

شما باید چیزی شبیه به این را بدست آورید:

interface$ npx @tailwindcss/upgrade@next
Need to install the following packages:
@tailwindcss/upgrade@4.0.2
Ok to proceed? (y) y

≈ tailwindcss v4.0.2

fatal: not a git repository (or any of the parent directories): .git
│ Searching for CSS files in the current
│ directory and its subdirectories…

│ ↳ Linked `./tailwind.config.ts` to
│   `./src/app.css`

│ Migrating JavaScript configuration files…

│ ↳ Migrated configuration file:
│   `./tailwind.config.ts`

│ Migrating templates…

│ ↳ Migrated templates for configuration file:
│   `./tailwind.config.ts`

│ Migrating stylesheets…

│ ↳ Migrated stylesheet: `./src/app.css`

│ Migrating PostCSS configuration…

│ ↳ Installed package: `@tailwindcss/postcss`

│ ↳ Removed package: `autoprefixer`

│ ↳ Migrated PostCSS configuration:
│   `./postcss.config.js`

│ Updating dependencies…

│ ↳ Updated package:
│   `prettier-plugin-tailwindcss`

│ ↳ Updated package: `tailwindcss`

fatal: not a git repository (or any of the parent directories): .git
│ No changes were made to your repository.

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این جادویی شما را اصلاح می کند src/app.css به نظر می رسد:

@import "tailwindcss";

@plugin '@tailwindcss/typography';
@plugin '@tailwindcss/forms';

/*
  The default border color has changed to `currentColor` in Tailwind CSS v4,
  so we've added these compatibility styles to make sure everything still
  looks the same as it did with Tailwind CSS v3.

  If we ever want to remove these styles, we need to add an explicit border
  color utility to any element that depends on these defaults.
*/
@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-gray-200, currentColor);
  }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

tailwind.config.ts حذف خواهد شد و postcss.config.js اصلاح خواهد شد ما باید تغییر جزئی ایجاد کنیم src/app.css وت vite.config.js:

@import "tailwindcss";

@plugin '@tailwindcss/typography';
@plugin '@tailwindcss/forms';

@custom-variant dark (&:where(.dark, .dark *));

@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-gray-200, currentColor);
  }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ما به خط 6 احتیاج داریم تا بتوانیم از کلاسها استفاده کنیم (و بعداً ، prefers-color-scheme) برای تغییر پویا مضامین.

بعدی است vite.config.js:

import { defineConfig } from "vitest/config";
import { sveltekit } from "@sveltejs/kit/vite";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [tailwindcss(), sveltekit()],

  test: {
    include: ["src/**/*.{test,spec}.{js,ts}"],
  },
});
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این نتیجه گیری اولیه را نتیجه می گیرد.

مرحله 3: اهرم prefers-color-scheme در تغییر تم

بسیاری از سیستم عامل های مدرن (OS) حالت تاریک را به ویژگی درجه یک تبدیل کرده اند و تنظیم برنامه وب خود برای احترام به اولویت موضوع سیستم عامل کاربر ، تجربه کاربری بهتری را فراهم می کند. CSS prefers-color-scheme ویژگی رسانه ای این کار را آسان می کند. در اینجا نحوه استفاده از آن آورده شده است:


 lang="en">
  
     charset="utf-8" />
     name="language" content="en" />
    
    
      name="theme-color"
      content="#ffffff"
      media="(prefers-color-scheme: light)"
    />
    
      name="theme-color"
      content="#111827"
      media="(prefers-color-scheme: dark)"
    />
     name="viewport" content="width=device-width, initial-scale=1" />
     rel="preconnect" href="https://fonts.googleapis.com" />
     rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    
      href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=Fira+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
      rel="stylesheet"
    />
    ... %sveltekit.head%
    "ts">
  import Moon from "$lib/components/icons/Moon.svelte";
  import Sun from "$lib/components/icons/Sun.svelte";

  let { ...props } = $props();

  let isDark = $state(false);

  $effect(() => {
    isDark = document.documentElement.classList.contains("dark");
  });

  function toggleTheme() {
    isDark = !isDark;
    localStorage.setItem("theme", isDark ? "dark" : "light");
    document.documentElement.classList.toggle("dark", isDark);
  }



حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

از آنجا که این برنامه کاملاً از Svelte 5 استفاده می شود ، ما از آن استفاده می کنیم $props() RUNE برای پذیرش هیچ ویژگی های منتقل شده به مؤلفه به عنوان غرفه ها ، و اپراتور گسترش به گسترش این ویژگی ها کمک می کند. ما همچنین یک متغیر واکنشی را با $state Rune ، و در آن به روز می شود $effect رون و در toggleTheme عملکرد. در $effect Rune یک بار در ابتدای مؤلفه اجرا می شود و هر زمان که وابستگی های آن تغییر می کند. در این حالت ، بررسی می کند که آیا dark کلاس در element and updates the isDark بر این اساس بیان کنید. این تضمین می کند که حالت اولیه مؤلفه با موضوع فعلی مطابقت دارد. در مورد toggleTheme عملکرد ، هنگامی که دکمه کلیک می شود و آن را تغییر می دهد isDark حالت ، موضوع انتخاب شده (“تاریک” یا “نور”) را ذخیره می کند localStorage، و dark کلاس در element. The

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا