ソースを参照

:sparkles: validating on record save | sync local and remote | using pouch | including compose ile for remote

tags/0.0.1
TOJ 5年前
コミット
58551ca8b6
9個のファイルの変更2738行の追加402行の削除
  1. 19
    0
      docker-compose.yml
  2. 2626
    360
      package-lock.json
  3. 1
    1
      package.json
  4. 2
    27
      src/App.vue
  5. 31
    9
      src/components/HelloWorld.vue
  6. 2
    2
      src/entities/_modules.js
  7. 3
    3
      src/entities/profile/profile.schema.js
  8. 49
    0
      src/utils/db.js
  9. 5
    0
      src/utils/index.js

+ 19
- 0
docker-compose.yml ファイルの表示

@@ -0,0 +1,19 @@
1
+version: "3"
2
+
3
+services:
4
+    siimee-db:
5
+        image: couchdb:latest
6
+        container_name: siimee-db
7
+        ports:
8
+            - 5984:5984
9
+        environment:
10
+            COUCHDB_USER: admin
11
+            COUCHDB_PASSWORD: couchdb
12
+        volumes:
13
+            - siimee_db:/opt/couchdb/data
14
+
15
+volumes:
16
+    siimee_db:
17
+
18
+networks:
19
+    siimee_net:

+ 2626
- 360
package-lock.json
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 1
- 1
package.json ファイルの表示

@@ -9,7 +9,7 @@
9 9
   "dependencies": {
10 10
     "ajv": "^8.2.0",
11 11
     "events": "^3.3.0",
12
-    "pouchdb": "^7.2.2",
12
+    "pouchdb-browser": "^7.2.2",
13 13
     "process": "^0.11.10",
14 14
     "vue": "^3.0.5"
15 15
   },

+ 2
- 27
src/App.vue ファイルの表示

@@ -1,35 +1,10 @@
1 1
 <template lang="pug">
2 2
 img(alt="Vue logo" src="./assets/logo.png")
3
-HelloWorld(msg="Hello Vue 3 + Vite")
3
+hello-world(msg="Hello Vue 3 + Vite")
4 4
 </template>
5 5
 
6 6
 <script setup>
7
-import PouchDB from 'pouchdb'
8
-
9
-import { Profile } from '@/entities/profile'
10
-
11
-const p = new Profile({
12
-    email: 'donot@disturb.com',
13
-    street: '123 strawberry ln',
14
-    apt: 2,
15
-    city: 'candyland',
16
-    state: 'lollipop',
17
-    zip: 90001
18
-})
19
-/** from ajv schema validation */
20
-if(p.isValid()) {
21
-    console.log('SUCCESS!', p)
22
-} else {
23
-    console.error('error!', p.isValid())
24
-}
25
-
26
-const db = new PouchDB('kittens')
27
-console.log('PouchDB', db)
28
-
29
-import HelloWorld from '@/components/HelloWorld.vue'
30
-
31
-// This starter template is using Vue 3 experimental <script setup> SFCs
32
-// Check out https://github.com/vuejs/rfcs/blob/script-setup-2/active-rfcs/0000-script-setup.md
7
+import helloWorld from '@/components/HelloWorld.vue'
33 8
 </script>
34 9
 
35 10
 <style lang="postcss">

+ 31
- 9
src/components/HelloWorld.vue ファイルの表示

@@ -1,25 +1,47 @@
1 1
 <template lang="pug">
2
-h1 {{ msg }}
2
+.wrapper(v-if="state.loaded")
3
+    h1 {{ msg }}
3 4
 
4
-p
5
-    a(href="https://vitejs.dev/guide/features.html" target="_blank") Vite Documentation | 
6
-    a(href="https://v3.vuejs.org/" target="_blank") Vue 3 Documentation
5
+    p
6
+        a(href="https://vitejs.dev/guide/features.html" target="_blank") Vite Documentation |
7
+        a(href="https://v3.vuejs.org/" target="_blank") Vue 3 Documentation
7 8
 
8
-button(@click="state.count++") count is: {{ state.count }}
9
+    button(@click="state.count++") count is: {{ state.count }}
9 10
 
10
-p Edit
11
-code components/HelloWorld.vue
12
-p to test hot module replacement.
11
+    p Edit
12
+    code components/HelloWorld.vue
13
+    p to test hot module replacement.
13 14
 </template>
14 15
 
15 16
 <script setup>
16 17
 import { defineProps, reactive } from 'vue'
17 18
 
19
+import { api } from '@/utils'
20
+import { Profile } from '@/entities/profile'
21
+
18 22
 defineProps({
19 23
     msg: String
20 24
 })
25
+const state = reactive({
26
+    count: 0,
27
+    loaded: false,
28
+    profile: null
29
+})
21 30
 
22
-const state = reactive({ count: 0 })
31
+state.profile = new Profile({
32
+    email: 'donot@disturb.com',
33
+    street: '123 strawberry ln',
34
+    apt: '2',
35
+    city: 'candyland',
36
+    state: 'lollipop',
37
+    zip: 90002
38
+})
39
+api.removeAll()
40
+api.put(state.profile).then(p => {
41
+    state.loaded = true
42
+    console.log(p)
43
+    api.sync()
44
+})
23 45
 </script>
24 46
 
25 47
 <style lang="postcss">

+ 2
- 2
src/entities/_modules.js ファイルの表示

@@ -12,7 +12,7 @@
12 12
      */
13 13
     constructor() {
14 14
         this.createdAt = new Date().toJSON()
15
-        this._id = Date.now()
15
+        this._id = Date.now().toString()
16 16
         this.lastUpdatedAt = null
17 17
 
18 18
         /** Set in subtype (ticket, user, etc) */
@@ -44,7 +44,7 @@ const allModules = {
44 44
         }
45 45
         return module
46 46
     },
47
-    
47
+
48 48
     /**
49 49
      * Use hourly() for anything that needs to track money * time
50 50
      */

+ 3
- 3
src/entities/profile/profile.schema.js ファイルの表示

@@ -1,8 +1,8 @@
1 1
 /** @module entities/profileSchema */
2 2
 import { allModules } from '..'
3 3
 
4
-/** 
5
- * profile schema object 
4
+/**
5
+ * profile schema object
6 6
  * uses the module system to use common fields
7 7
  * but sets fields with our validation types
8 8
  * @constructor
@@ -12,7 +12,7 @@ const profileSchema = {
12 12
     properties: {
13 13
         /** _baseRecord fields */
14 14
         createdAt: { type: 'string' },
15
-        _id: { type: 'number' },
15
+        _id: { type: 'string' },
16 16
         lastUpdatedAt: { type: 'string' },
17 17
         type: { type: 'string' },
18 18
 

+ 49
- 0
src/utils/db.js ファイルの表示

@@ -0,0 +1,49 @@
1
+import PouchDB from 'pouchdb-browser'
2
+
3
+const domain = 'localhost'
4
+const port = 5984
5
+const remote = `http://${domain}:${port}`
6
+
7
+class Connector {
8
+    constructor(dbName) {
9
+        this.local = new PouchDB(dbName)
10
+        this.db = new PouchDB(`${remote}/${dbName}`)
11
+    }
12
+    async put(entry) {
13
+        /** from ajv schema validation */
14
+        if(entry.isValid()) {
15
+            try {
16
+                const res = await this.local.put(entry)
17
+                if(!res.ok) throw 'put to PouchDB failed'
18
+                return res
19
+            }
20
+            /** valid data but can't save */
21
+            catch (err) {
22
+                console.error('can\'t put', entry)
23
+            }
24
+        }
25
+        else {
26
+            /** not valid data */
27
+            console.error('NOT VALID!', entry.isValid())
28
+        }
29
+    }
30
+    async sync() {
31
+        this.local.sync(this.db).on('complete', () => {
32
+            console.log("sync'd!")
33
+        }).on('error', err => {
34
+            console.error("not sync'd!", err)
35
+        })
36
+    }
37
+    /** !: DEV ONLY */
38
+    async removeAll() {
39
+        const allDocs = await this.local.allDocs({
40
+            include_docs: true,
41
+            deleted: true
42
+        })
43
+        return Promise.all(allDocs.rows.map(row => {
44
+            return this.local.remove(row.id, row.value.rev)
45
+        }))
46
+    }
47
+}
48
+
49
+export { Connector }

+ 5
- 0
src/utils/index.js ファイルの表示

@@ -0,0 +1,5 @@
1
+import { Connector } from './db'
2
+
3
+const api = new Connector('kittens')
4
+
5
+export { api }

読み込み中…
キャンセル
保存