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>
    )
}