Back to projects
Mar 20, 2024
4 min read

Translator

Utilized Microsoft Azure AI Services to detect, translate and pronounce text in multiple languages.
demo

Created edge functions using Hono RPC Stack.

Server

import { Hono } from 'hono'
import example from 'routes/example'

const app = new Hono()
.basePath('/api')
.route('/example', example)
.route('/...', ...)

export type AppType = app

[[route.ts]]

import { Hono } from "hono";
import { z } from "zod";
import { zValidator } from "@hono/zod-validator";
import { db } from "../db";

const schema = z.object({
  id: z.string(),
  title: z.string(),
});

const test = new Hono()
  .post("/", zValidator("form", schema), async (c) => {
    const todo = c.req.valid("form");
    await db.test.create({ data: todo });
    return c.json({
      todo,
    });
  })
  .get("/", async (c) => {
    const todos = await db.test.findMany();
    return c.json({
      todos,
    });
  });

export default test;

/routes/example.ts

Client

import { AppType } from "./server";
import { hc } from "hono/client";

const client = hc<AppType>("/api");
const res = await client.todo.$get();
const post = await client.todo.$post({
  form: {
    id: "12309",
    title: "example",
  },
});

Cloudflare Workers

wrangler for dev

{
  "scripts": {
    "dev": "wrangler pages dev --compatibility-flags=nodejs_compat --compatibility-date=2024-03-15 -- vite"
  }
}

Compatibility flags

Environment variables

using wrangler.toml
[vars]

KEY = "..."
using .dev.vars

similar to a regular .env

KEY=...

Handled Client State with Zustand

import { create } from 'zustand'

type exampleStore = {
    allExamples: string[]
    addExample: (example:string) => void
    isExample: boolean
    toggleExample: () => void
}

export const useExampleStore = create<exampleStore>((set) => ({
    allExamples: [],
    addExample: (example) => set((state) => ({ allExamples: [...state.allExamples, example] }))
    isExample: false,
    toggleExample: () => set((state) => ({ isExample: !state.isExample }))
}))

stores/example.ts

import { useExampleStore } from '@/stores/example'

const App = () => {
    const { allExamples } = useExampleStore()
    return (
        // ...
        {allExamples.map((example) => (
            <div key={example.id}>
                {example.title}
            </div>
        ))}
    )
}

Created a deployment pipeline using GitHub Actions.

Serve and Test (start-server-and-test)

> start-server-and-test prod http://localhost:8788 'npx playwright test'

1: starting server using command "npm run prod"
and when url "[ 'http://localhost:8788' ]" is responding with HTTP status code 200
running tests using command "npx playwright test"

env variables (stackoverflow)

paste your entire env file in one secret named ENV_FILE and the just do echo "${{ secrets.ENV_FILE }}" > .env

- name: Create env file
  run: echo "${{ secrets.ENV_FILE }}" > .env

Skipping workflow

add if statement before steps to check if commit msgs for a skip flag (in this case ‘#skip’)

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'push' && !contains(join(github.event.commits.*.message, ''), '#skip') }}

Tested the application using Playwright.

npx playwright test
import { test, expect } from '@playwright/test`

test.beforeEach(async ({ page }) => {
    await page.goto('...')
})

test.describe('example', () => {
    test('display a todo', async ({ page }) => {
        const newTodo = page.getByPlaceholder('Add a todo')
        await newTodo.fill('a todo')
        await newTodo.press('Enter')

        await expect(page.getByTestId('todo')).toHaveText('a todo')
    })
})

/test/main.spec.ts

const App = () => {
  return (
    //...
    <div data-testid="todo">{todo}</div>
  );
};