Closed1

Vue 3 + Vite + Turso + zodスタックのメモ

knaka Tech-Blogknaka Tech-Blog

概要

Vueで Turso (DB) 使う例になります。

  • zodの form検証を使います。
  • テストは、vercelに設置する例です。

[ 公開: 2024/04/21 ]


環境

  • Vue :3.4.21
  • Vite: 5.2.6
  • zod
  • express
  • vercel

作成したコード

https://github.com/kuc-arc-f/express_44vue/tree/main/sample/turso_test


  • client/TursoTest.vue
  • let items = ref([]) で。行の値を設定。
TursoTest.vue

<script setup lang="ts">
import { ref, reactive } from 'vue';

import Crud from './Zod/Crud';
import Validate from './Zod/Validate';
import CrudIndex from './TursoTest/CrudIndex';
//
let items = ref([]);
const errors = reactive({
  title: "",
  content: "",
})
const resetErrors = function(){
  const keys = Object.keys(errors);
  keys.forEach((key) => { errors[key] = ""; });
}
//
const testProc = async function(){
  resetErrors();
  const input = Crud.getInputValues();
  const formErrors = Validate.formValidate(input);
console.log(formErrors);
  if(formErrors.title){
    errors.title = formErrors.title;
  }
  if(formErrors.content){
    errors.content = formErrors.content;
  }
console.log("errors.title=", errors.title);
console.log(errors);
  const keys = Object.keys(errors);
  if(!errors.title && !errors.content) {
    console.log("no, errors");
    await CrudIndex.addItem(); 
    location.reload();
  }
}
/**
 * getList
 * @param
 *
 * @return
 */
const getList = async function() {
  try{
console.log("#getList");
    const data = await CrudIndex.getList();
console.log(data);
    items.value = data;
  } catch (e) {
    console.error(e);
  } 
}
getList();

</script>

<!-- template -->
<template>
  <div class="container mx-auto my-2 px-8 bg-white">
    <h1 class="text-4xl text-gray-700 font-bold my-2">TursoTest.vue! </h1>
    <hr class="my-2" />
    <label>Title:
      <input type="text" id="title" 
      class="border border-gray-400 rounded-md px-3 py-2 w-full focus:outline-none focus:border-blue-500"
      />    
    </label>
    <span v-if="errors.title">
      <em class="error_message">{{errors.title}}</em>
    </span>
    <hr class="my-2" />
    <label>Content:
    <input type="text" id="content" 
    class="border border-gray-400 rounded-md px-3 py-2 w-full focus:outline-none focus:border-blue-500"
    />    
    </label>    
    <span v-if="errors.content">
      <em class="error_message">{{errors.content}}</em>
    </span>
    <hr class="my-2" />
    <button @click="testProc" class="btn-purple">Add</button>
    <hr class="my-2" />
    <ul>
      <li v-for="item in items" :key="item.id">
        <h3 class="text-3xl font-bold">{{ item.title }}</h3>
        <span>ID: {{ item.id }}, {{ item.createdAt }}</span>
        <router-link :to="'/tursotestshow?id=' + item.id" 
        class="btn-outline-purple ms-2">Show
        </router-link>
        <hr class="my-2" />
      </li>
    </ul>
  </div>
</template>

<!-- style -->
<style scoped>
</style>


  • routes/tursoTodoRouter.ts
  • 内部API、指定エンドポイントから、 Turso連携します。
tursoTodoRouter.ts
router.post('/get_list', async function(req: any, res: any) {
  try {
    const retObj = {ret: "NG", data: [], message: ""};
    if(req.body){
      const client = await LibTurso.getClient();
      const sql = `SELECT * FROM todos ORDER BY id DESC LIMIT 100;`;
console.log(sql);
      const resulte = await client.execute(sql);
      retObj.ret = "OK";
      //@ts-ignore
      retObj.data = resulte.rows;
      return res.json(retObj);
    }
    return res.json(retObj);
  } catch (error) {
    console.error(error);
    res.sendStatus(500);
  }
});

このスクラップは13日前にクローズされました