Просмотр исходного кода

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

tags/0.0.1
TOJ 5 лет назад
Родитель
Сommit
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 Просмотреть файл

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

+ 2
- 27
src/App.vue Просмотреть файл

1
 <template lang="pug">
1
 <template lang="pug">
2
 img(alt="Vue logo" src="./assets/logo.png")
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
 </template>
4
 </template>
5
 
5
 
6
 <script setup>
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
 </script>
8
 </script>
34
 
9
 
35
 <style lang="postcss">
10
 <style lang="postcss">

+ 31
- 9
src/components/HelloWorld.vue Просмотреть файл

1
 <template lang="pug">
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
 </template>
14
 </template>
14
 
15
 
15
 <script setup>
16
 <script setup>
16
 import { defineProps, reactive } from 'vue'
17
 import { defineProps, reactive } from 'vue'
17
 
18
 
19
+import { api } from '@/utils'
20
+import { Profile } from '@/entities/profile'
21
+
18
 defineProps({
22
 defineProps({
19
     msg: String
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
 </script>
45
 </script>
24
 
46
 
25
 <style lang="postcss">
47
 <style lang="postcss">

+ 2
- 2
src/entities/_modules.js Просмотреть файл

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

+ 3
- 3
src/entities/profile/profile.schema.js Просмотреть файл

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

+ 49
- 0
src/utils/db.js Просмотреть файл

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 Просмотреть файл

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

Загрузка…
Отмена
Сохранить