From b289c7b4c8d673f473c16f3d813d76e884de8943 Mon Sep 17 00:00:00 2001 From: Maxime Lambotin Date: Thu, 1 Feb 2024 17:55:50 +0100 Subject: [PATCH 1/6] fix: use vue2 set and delete to update store state with reactivity --- packages/pinia-orm/package.json | 4 +- .../src/composables/useStoreActions.ts | 39 ++++++++++++++++--- pnpm-lock.yaml | 25 ++---------- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/packages/pinia-orm/package.json b/packages/pinia-orm/package.json index 4605e25b7..bcdca6935 100644 --- a/packages/pinia-orm/package.json +++ b/packages/pinia-orm/package.json @@ -59,7 +59,8 @@ "pinia": "^2.1.6" }, "dependencies": { - "@pinia-orm/normalizr": ">=1.7.0" + "@pinia-orm/normalizr": ">=1.7.0", + "vue-demi": "^0.14.6" }, "devDependencies": { "@nuxtjs/eslint-config-typescript": "^12.1.0", @@ -90,7 +91,6 @@ "vite": "^5.0.0", "vitest": "^1.0.0", "vue": "^3.3.4", - "vue-demi": "^0.14.6", "vue2": "npm:vue@^2.7.3" }, "size-limit": [ diff --git a/packages/pinia-orm/src/composables/useStoreActions.ts b/packages/pinia-orm/src/composables/useStoreActions.ts index 6c0021b77..8751c3add 100644 --- a/packages/pinia-orm/src/composables/useStoreActions.ts +++ b/packages/pinia-orm/src/composables/useStoreActions.ts @@ -1,3 +1,4 @@ +import { Vue2, isVue2 } from 'vue-demi' import type { Elements } from '../data/Data' import type { Query } from '../query/Query' import type { DataStore } from './useDataStore' @@ -5,17 +6,29 @@ import type { DataStore } from './useDataStore' export function useStoreActions (query?: Query) { return { save (this: DataStore, records: Elements, triggerQueryAction = true) { - Object.assign(this.data, records) + if (isVue2) { + Vue2.set(this, 'data', records) + } else { + Object.assign(this.data, records) + } if (triggerQueryAction && query) { query.newQuery(this.$id).save(Object.values(records)) } }, insert (this: DataStore, records: Elements, triggerQueryAction = true) { - Object.assign(this.data, records) + if (isVue2) { + Vue2.set(this, 'data', records) + } else { + Object.assign(this.data, records) + } if (triggerQueryAction && query) { query.newQuery(this.$id).insert(Object.values(records)) } }, update (this: DataStore, records: Elements, triggerQueryAction = true) { - Object.assign(this.data, records) + if (isVue2) { + Vue2.set(this, 'data', records); + } else { + Object.assign(this.data, records) + } if (triggerQueryAction && query) { query.newQuery(this.$id).update(Object.values(records)) } }, @@ -27,7 +40,15 @@ export function useStoreActions (query?: Query) { destroy (this: DataStore, ids: (string | number)[], triggerQueryAction = true): void { if (triggerQueryAction && query) { query.newQuery(this.$id).newQuery(this.$id).destroy(ids) - } else { ids.forEach(id => delete this.data[id]) } + } else { + ids.forEach(id => { + if (isVue2) { + Vue2.delete(this.data, id); + } else { + delete this.data[id] + } + }) + } }, /** * Commit `delete` change to the store. @@ -35,7 +56,15 @@ export function useStoreActions (query?: Query) { delete (this: DataStore, ids: (string | number)[], triggerQueryAction = true): void { if (triggerQueryAction && query) { query.whereId(ids).delete() - } else { ids.forEach(id => delete this.data[id]) } + } else { + ids.forEach(id => { + if (isVue2) { + Vue2.delete(this.data, id); + } else { + delete this.data[id] + } + }) + } }, flush (this: DataStore, _records?: Elements, triggerQueryAction = true): void { this.data = {} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91df1da11..d3640ec7d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -200,6 +200,9 @@ importers: '@pinia-orm/normalizr': specifier: '>=1.7.0' version: link:../normalizr + vue-demi: + specifier: ^0.14.6 + version: 0.14.6(@vue/composition-api@1.7.2)(vue@3.3.4) devDependencies: '@nuxtjs/eslint-config-typescript': specifier: ^12.1.0 @@ -285,9 +288,6 @@ importers: vue: specifier: ^3.3.4 version: 3.3.4 - vue-demi: - specifier: ^0.14.6 - version: 0.14.6(@vue/composition-api@1.7.2)(vue@3.3.4) vue2: specifier: npm:vue@^2.7.3 version: /vue@2.7.3 @@ -681,7 +681,6 @@ packages: hasBin: true dependencies: '@babel/types': 7.23.0 - dev: true /@babel/parser@7.23.5: resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==} @@ -878,7 +877,6 @@ packages: '@babel/helper-string-parser': 7.23.4 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: true /@babel/types@7.23.5: resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==} @@ -3382,14 +3380,12 @@ packages: '@vue/shared': 3.3.4 estree-walker: 2.0.2 source-map-js: 1.0.2 - dev: true /@vue/compiler-dom@3.3.4: resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} dependencies: '@vue/compiler-core': 3.3.4 '@vue/shared': 3.3.4 - dev: true /@vue/compiler-sfc@2.7.3: resolution: {integrity: sha512-/9SO6KeR1ljo+j4Tdkl9zsFG2yY4NQ9p3GKdPVCU99bmkNkTW8g9Tq8SMEvhOfo+RhBC0PdDAOmibl+N37f5YA==} @@ -3412,14 +3408,12 @@ packages: magic-string: 0.30.5 postcss: 8.4.31 source-map-js: 1.0.2 - dev: true /@vue/compiler-ssr@3.3.4: resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} dependencies: '@vue/compiler-dom': 3.3.4 '@vue/shared': 3.3.4 - dev: true /@vue/composition-api@1.7.2(vue@3.3.4): resolution: {integrity: sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==} @@ -3427,7 +3421,6 @@ packages: vue: '>= 2.5 < 2.7 || 3' dependencies: vue: 3.3.4 - dev: true /@vue/devtools-api@6.5.0: resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} @@ -3441,20 +3434,17 @@ packages: '@vue/shared': 3.3.4 estree-walker: 2.0.2 magic-string: 0.30.5 - dev: true /@vue/reactivity@3.3.4: resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} dependencies: '@vue/shared': 3.3.4 - dev: true /@vue/runtime-core@3.3.4: resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} dependencies: '@vue/reactivity': 3.3.4 '@vue/shared': 3.3.4 - dev: true /@vue/runtime-dom@3.3.4: resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} @@ -3462,7 +3452,6 @@ packages: '@vue/runtime-core': 3.3.4 '@vue/shared': 3.3.4 csstype: 3.1.2 - dev: true /@vue/server-renderer@3.3.4(vue@3.3.4): resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} @@ -3472,11 +3461,9 @@ packages: '@vue/compiler-ssr': 3.3.4 '@vue/shared': 3.3.4 vue: 3.3.4 - dev: true /@vue/shared@3.3.4: resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} - dev: true /@vue/test-utils@2.4.1(vue@3.3.4): resolution: {integrity: sha512-VO8nragneNzUZUah6kOjiFmD/gwRjUauG9DROh6oaOeFwX1cZRUNHhdeogE8635cISigXFTtGLUQWx5KCb0xeg==} @@ -4800,7 +4787,6 @@ packages: /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - dev: true /cuint@0.2.2: resolution: {integrity: sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==} @@ -8023,7 +8009,6 @@ packages: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: true /nanoid@4.0.2: resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} @@ -9372,7 +9357,6 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true /prebuild-install@7.1.1: resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} @@ -10202,7 +10186,6 @@ packages: /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: true /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -11666,7 +11649,6 @@ packages: dependencies: '@vue/composition-api': 1.7.2(vue@3.3.4) vue: 3.3.4 - dev: true /vue-devtools-stub@0.1.0: resolution: {integrity: sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==} @@ -11715,7 +11697,6 @@ packages: '@vue/runtime-dom': 3.3.4 '@vue/server-renderer': 3.3.4(vue@3.3.4) '@vue/shared': 3.3.4 - dev: true /wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} From 94dd3d459fb4f0c7ba81817a41e49a3ced744c22 Mon Sep 17 00:00:00 2001 From: Maxime Lambotin Date: Fri, 2 Feb 2024 17:06:03 +0100 Subject: [PATCH 2/6] chore: fix lint --- .../pinia-orm/src/composables/useStoreActions.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pinia-orm/src/composables/useStoreActions.ts b/packages/pinia-orm/src/composables/useStoreActions.ts index 8751c3add..11b4a9fcd 100644 --- a/packages/pinia-orm/src/composables/useStoreActions.ts +++ b/packages/pinia-orm/src/composables/useStoreActions.ts @@ -1,4 +1,4 @@ -import { Vue2, isVue2 } from 'vue-demi' +import { Vue2, isVue2 } from 'vue-demi' import type { Elements } from '../data/Data' import type { Query } from '../query/Query' import type { DataStore } from './useDataStore' @@ -25,7 +25,7 @@ export function useStoreActions (query?: Query) { }, update (this: DataStore, records: Elements, triggerQueryAction = true) { if (isVue2) { - Vue2.set(this, 'data', records); + Vue2.set(this, 'data', records) } else { Object.assign(this.data, records) } @@ -41,9 +41,9 @@ export function useStoreActions (query?: Query) { if (triggerQueryAction && query) { query.newQuery(this.$id).newQuery(this.$id).destroy(ids) } else { - ids.forEach(id => { + ids.forEach((id) => { if (isVue2) { - Vue2.delete(this.data, id); + Vue2.delete(this.data, id) } else { delete this.data[id] } @@ -57,9 +57,9 @@ export function useStoreActions (query?: Query) { if (triggerQueryAction && query) { query.whereId(ids).delete() } else { - ids.forEach(id => { + ids.forEach((id) => { if (isVue2) { - Vue2.delete(this.data, id); + Vue2.delete(this.data, id) } else { delete this.data[id] } From 8aee9b7516fba33732a5ebce09e400ab438a1b84 Mon Sep 17 00:00:00 2001 From: Maxime Lambotin Date: Wed, 7 Feb 2024 10:55:15 +0100 Subject: [PATCH 3/6] feat: move vue-demi to dev deps and update perf test --- packages/pinia-orm/package.json | 4 +- .../src/composables/useStoreActions.ts | 31 +++---------- ...event_rerender_of_child_components.spec.ts | 45 ++++++++++--------- pnpm-lock.yaml | 44 +++++++++--------- 4 files changed, 53 insertions(+), 71 deletions(-) diff --git a/packages/pinia-orm/package.json b/packages/pinia-orm/package.json index bcdca6935..4605e25b7 100644 --- a/packages/pinia-orm/package.json +++ b/packages/pinia-orm/package.json @@ -59,8 +59,7 @@ "pinia": "^2.1.6" }, "dependencies": { - "@pinia-orm/normalizr": ">=1.7.0", - "vue-demi": "^0.14.6" + "@pinia-orm/normalizr": ">=1.7.0" }, "devDependencies": { "@nuxtjs/eslint-config-typescript": "^12.1.0", @@ -91,6 +90,7 @@ "vite": "^5.0.0", "vitest": "^1.0.0", "vue": "^3.3.4", + "vue-demi": "^0.14.6", "vue2": "npm:vue@^2.7.3" }, "size-limit": [ diff --git a/packages/pinia-orm/src/composables/useStoreActions.ts b/packages/pinia-orm/src/composables/useStoreActions.ts index 11b4a9fcd..f69cc74e3 100644 --- a/packages/pinia-orm/src/composables/useStoreActions.ts +++ b/packages/pinia-orm/src/composables/useStoreActions.ts @@ -1,4 +1,3 @@ -import { Vue2, isVue2 } from 'vue-demi' import type { Elements } from '../data/Data' import type { Query } from '../query/Query' import type { DataStore } from './useDataStore' @@ -6,29 +5,17 @@ import type { DataStore } from './useDataStore' export function useStoreActions (query?: Query) { return { save (this: DataStore, records: Elements, triggerQueryAction = true) { - if (isVue2) { - Vue2.set(this, 'data', records) - } else { - Object.assign(this.data, records) - } + this.data = Object.assign({}, this.data, records) if (triggerQueryAction && query) { query.newQuery(this.$id).save(Object.values(records)) } }, insert (this: DataStore, records: Elements, triggerQueryAction = true) { - if (isVue2) { - Vue2.set(this, 'data', records) - } else { - Object.assign(this.data, records) - } + this.data = Object.assign({}, this.data, records) if (triggerQueryAction && query) { query.newQuery(this.$id).insert(Object.values(records)) } }, update (this: DataStore, records: Elements, triggerQueryAction = true) { - if (isVue2) { - Vue2.set(this, 'data', records) - } else { - Object.assign(this.data, records) - } + this.data = Object.assign({}, this.data, records) if (triggerQueryAction && query) { query.newQuery(this.$id).update(Object.values(records)) } }, @@ -42,11 +29,7 @@ export function useStoreActions (query?: Query) { query.newQuery(this.$id).newQuery(this.$id).destroy(ids) } else { ids.forEach((id) => { - if (isVue2) { - Vue2.delete(this.data, id) - } else { - delete this.data[id] - } + delete this.data[id] }) } }, @@ -58,11 +41,7 @@ export function useStoreActions (query?: Query) { query.whereId(ids).delete() } else { ids.forEach((id) => { - if (isVue2) { - Vue2.delete(this.data, id) - } else { - delete this.data[id] - } + delete this.data[id] }) } }, diff --git a/packages/pinia-orm/tests/performance/prevent_rerender_of_child_components.spec.ts b/packages/pinia-orm/tests/performance/prevent_rerender_of_child_components.spec.ts index 2728edb3c..2955c25c8 100644 --- a/packages/pinia-orm/tests/performance/prevent_rerender_of_child_components.spec.ts +++ b/packages/pinia-orm/tests/performance/prevent_rerender_of_child_components.spec.ts @@ -1,13 +1,13 @@ import { describe, expect, it, vi } from 'vitest' import { mount } from '@vue/test-utils' import { createTestingPinia } from '@pinia/testing' -import { computed, defineComponent, nextTick, onUpdated } from 'vue-demi' +import { defineComponent, nextTick } from 'vue-demi' -import { Model, useRepo } from '../../src' +import { Model, mapRepos } from '../../src' import { Num, Str } from '../../src/decorators' /* eslint-disable vue/one-component-per-file */ -describe.skip('performance/prevent_rerender_of_child_components', () => { +describe('performance/prevent_rerender_of_child_components', () => { class Post extends Model { static entity = 'posts' @@ -22,10 +22,8 @@ describe.skip('performance/prevent_rerender_of_child_components', () => { required: true } }, - setup () { - onUpdated(() => { - console.warn(' Updated') - }) + updated () { + console.warn(' Updated') }, template: `
{{ post.title }}
@@ -34,22 +32,25 @@ describe.skip('performance/prevent_rerender_of_child_components', () => { const MainComponent = defineComponent({ components: { PostComponent }, - setup () { - const postRepo = useRepo(Post) - - const posts = computed(() => postRepo.all()) - let counter = 10 - - const addPost = () => { - postRepo.insert({ - id: counter++, - title: `Test ${counter}` - }) - } - + data () { return { - posts, - addPost + counter: 10 + } + }, + computed: { + ...mapRepos({ + postRepo: Post + }), + posts () { + return this.postRepo.all() + } + }, + methods: { + addPost () { + this.postRepo.insert({ + id: this.counter++, + title: `Test ${this.counter}` + }) } }, template: ` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d3640ec7d..47cedde91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -200,9 +200,6 @@ importers: '@pinia-orm/normalizr': specifier: '>=1.7.0' version: link:../normalizr - vue-demi: - specifier: ^0.14.6 - version: 0.14.6(@vue/composition-api@1.7.2)(vue@3.3.4) devDependencies: '@nuxtjs/eslint-config-typescript': specifier: ^12.1.0 @@ -288,6 +285,9 @@ importers: vue: specifier: ^3.3.4 version: 3.3.4 + vue-demi: + specifier: ^0.14.6 + version: 0.14.6(@vue/composition-api@1.7.2)(vue@3.3.4) vue2: specifier: npm:vue@^2.7.3 version: /vue@2.7.3 @@ -675,13 +675,6 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser@7.23.0: - resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.23.0 - /@babel/parser@7.23.5: resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==} engines: {node: '>=6.0.0'} @@ -870,14 +863,6 @@ packages: - supports-color dev: true - /@babel/types@7.23.0: - resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.23.4 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - /@babel/types@7.23.5: resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==} engines: {node: '>=6.9.0'} @@ -3376,16 +3361,18 @@ packages: /@vue/compiler-core@3.3.4: resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} dependencies: - '@babel/parser': 7.23.0 + '@babel/parser': 7.23.5 '@vue/shared': 3.3.4 estree-walker: 2.0.2 source-map-js: 1.0.2 + dev: true /@vue/compiler-dom@3.3.4: resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} dependencies: '@vue/compiler-core': 3.3.4 '@vue/shared': 3.3.4 + dev: true /@vue/compiler-sfc@2.7.3: resolution: {integrity: sha512-/9SO6KeR1ljo+j4Tdkl9zsFG2yY4NQ9p3GKdPVCU99bmkNkTW8g9Tq8SMEvhOfo+RhBC0PdDAOmibl+N37f5YA==} @@ -3398,7 +3385,7 @@ packages: /@vue/compiler-sfc@3.3.4: resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} dependencies: - '@babel/parser': 7.23.0 + '@babel/parser': 7.23.5 '@vue/compiler-core': 3.3.4 '@vue/compiler-dom': 3.3.4 '@vue/compiler-ssr': 3.3.4 @@ -3408,12 +3395,14 @@ packages: magic-string: 0.30.5 postcss: 8.4.31 source-map-js: 1.0.2 + dev: true /@vue/compiler-ssr@3.3.4: resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} dependencies: '@vue/compiler-dom': 3.3.4 '@vue/shared': 3.3.4 + dev: true /@vue/composition-api@1.7.2(vue@3.3.4): resolution: {integrity: sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==} @@ -3421,6 +3410,7 @@ packages: vue: '>= 2.5 < 2.7 || 3' dependencies: vue: 3.3.4 + dev: true /@vue/devtools-api@6.5.0: resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} @@ -3429,22 +3419,25 @@ packages: /@vue/reactivity-transform@3.3.4: resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} dependencies: - '@babel/parser': 7.23.0 + '@babel/parser': 7.23.5 '@vue/compiler-core': 3.3.4 '@vue/shared': 3.3.4 estree-walker: 2.0.2 magic-string: 0.30.5 + dev: true /@vue/reactivity@3.3.4: resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} dependencies: '@vue/shared': 3.3.4 + dev: true /@vue/runtime-core@3.3.4: resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} dependencies: '@vue/reactivity': 3.3.4 '@vue/shared': 3.3.4 + dev: true /@vue/runtime-dom@3.3.4: resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} @@ -3452,6 +3445,7 @@ packages: '@vue/runtime-core': 3.3.4 '@vue/shared': 3.3.4 csstype: 3.1.2 + dev: true /@vue/server-renderer@3.3.4(vue@3.3.4): resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} @@ -3461,9 +3455,11 @@ packages: '@vue/compiler-ssr': 3.3.4 '@vue/shared': 3.3.4 vue: 3.3.4 + dev: true /@vue/shared@3.3.4: resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + dev: true /@vue/test-utils@2.4.1(vue@3.3.4): resolution: {integrity: sha512-VO8nragneNzUZUah6kOjiFmD/gwRjUauG9DROh6oaOeFwX1cZRUNHhdeogE8635cISigXFTtGLUQWx5KCb0xeg==} @@ -4787,6 +4783,7 @@ packages: /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + dev: true /cuint@0.2.2: resolution: {integrity: sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==} @@ -8009,6 +8006,7 @@ packages: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + dev: true /nanoid@4.0.2: resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} @@ -9357,6 +9355,7 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 + dev: true /prebuild-install@7.1.1: resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} @@ -10186,6 +10185,7 @@ packages: /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + dev: true /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -11649,6 +11649,7 @@ packages: dependencies: '@vue/composition-api': 1.7.2(vue@3.3.4) vue: 3.3.4 + dev: true /vue-devtools-stub@0.1.0: resolution: {integrity: sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==} @@ -11697,6 +11698,7 @@ packages: '@vue/runtime-dom': 3.3.4 '@vue/server-renderer': 3.3.4(vue@3.3.4) '@vue/shared': 3.3.4 + dev: true /wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} From c78ee11465028df7581f26a55bf9297048f1bec2 Mon Sep 17 00:00:00 2001 From: Maxime Lambotin Date: Fri, 9 Feb 2024 10:36:36 +0100 Subject: [PATCH 4/6] fix: update vue 2 reactivity --- .../src/composables/useStoreActions.ts | 16 ++++--- ...event_rerender_of_child_components.spec.ts | 45 +++++++++---------- pnpm-lock.yaml | 23 ++++++++-- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/packages/pinia-orm/src/composables/useStoreActions.ts b/packages/pinia-orm/src/composables/useStoreActions.ts index f69cc74e3..e3693f726 100644 --- a/packages/pinia-orm/src/composables/useStoreActions.ts +++ b/packages/pinia-orm/src/composables/useStoreActions.ts @@ -28,9 +28,11 @@ export function useStoreActions (query?: Query) { if (triggerQueryAction && query) { query.newQuery(this.$id).newQuery(this.$id).destroy(ids) } else { - ids.forEach((id) => { - delete this.data[id] - }) + ids.forEach(id => delete this.data[id]) + // Trigger Vue 2 reactivity + if (this.data.__ob__) { + this.data.__ob__.dep.notify() + } } }, /** @@ -40,9 +42,11 @@ export function useStoreActions (query?: Query) { if (triggerQueryAction && query) { query.whereId(ids).delete() } else { - ids.forEach((id) => { - delete this.data[id] - }) + ids.forEach(id => delete this.data[id]) + // Trigger Vue 2 reactivity + if (this.data.__ob__) { + this.data.__ob__.dep.notify() + } } }, flush (this: DataStore, _records?: Elements, triggerQueryAction = true): void { diff --git a/packages/pinia-orm/tests/performance/prevent_rerender_of_child_components.spec.ts b/packages/pinia-orm/tests/performance/prevent_rerender_of_child_components.spec.ts index 2955c25c8..2728edb3c 100644 --- a/packages/pinia-orm/tests/performance/prevent_rerender_of_child_components.spec.ts +++ b/packages/pinia-orm/tests/performance/prevent_rerender_of_child_components.spec.ts @@ -1,13 +1,13 @@ import { describe, expect, it, vi } from 'vitest' import { mount } from '@vue/test-utils' import { createTestingPinia } from '@pinia/testing' -import { defineComponent, nextTick } from 'vue-demi' +import { computed, defineComponent, nextTick, onUpdated } from 'vue-demi' -import { Model, mapRepos } from '../../src' +import { Model, useRepo } from '../../src' import { Num, Str } from '../../src/decorators' /* eslint-disable vue/one-component-per-file */ -describe('performance/prevent_rerender_of_child_components', () => { +describe.skip('performance/prevent_rerender_of_child_components', () => { class Post extends Model { static entity = 'posts' @@ -22,8 +22,10 @@ describe('performance/prevent_rerender_of_child_components', () => { required: true } }, - updated () { - console.warn(' Updated') + setup () { + onUpdated(() => { + console.warn(' Updated') + }) }, template: `
{{ post.title }}
@@ -32,26 +34,23 @@ describe('performance/prevent_rerender_of_child_components', () => { const MainComponent = defineComponent({ components: { PostComponent }, - data () { - return { - counter: 10 - } - }, - computed: { - ...mapRepos({ - postRepo: Post - }), - posts () { - return this.postRepo.all() - } - }, - methods: { - addPost () { - this.postRepo.insert({ - id: this.counter++, - title: `Test ${this.counter}` + setup () { + const postRepo = useRepo(Post) + + const posts = computed(() => postRepo.all()) + let counter = 10 + + const addPost = () => { + postRepo.insert({ + id: counter++, + title: `Test ${counter}` }) } + + return { + posts, + addPost + } }, template: `
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47cedde91..91df1da11 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -675,6 +675,14 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 + /@babel/parser@7.23.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.0 + dev: true + /@babel/parser@7.23.5: resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==} engines: {node: '>=6.0.0'} @@ -863,6 +871,15 @@ packages: - supports-color dev: true + /@babel/types@7.23.0: + resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.23.4 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + /@babel/types@7.23.5: resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==} engines: {node: '>=6.9.0'} @@ -3361,7 +3378,7 @@ packages: /@vue/compiler-core@3.3.4: resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} dependencies: - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.0 '@vue/shared': 3.3.4 estree-walker: 2.0.2 source-map-js: 1.0.2 @@ -3385,7 +3402,7 @@ packages: /@vue/compiler-sfc@3.3.4: resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} dependencies: - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.0 '@vue/compiler-core': 3.3.4 '@vue/compiler-dom': 3.3.4 '@vue/compiler-ssr': 3.3.4 @@ -3419,7 +3436,7 @@ packages: /@vue/reactivity-transform@3.3.4: resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} dependencies: - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.0 '@vue/compiler-core': 3.3.4 '@vue/shared': 3.3.4 estree-walker: 2.0.2 From eea490eec027f5e5189671e8553afbd8cabbedf2 Mon Sep 17 00:00:00 2001 From: Maxime Lambotin Date: Fri, 9 Feb 2024 11:48:26 +0100 Subject: [PATCH 5/6] feat: add reactivity tests --- .../feature/reactivity/reactivity.spec.ts | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 packages/pinia-orm/tests/feature/reactivity/reactivity.spec.ts diff --git a/packages/pinia-orm/tests/feature/reactivity/reactivity.spec.ts b/packages/pinia-orm/tests/feature/reactivity/reactivity.spec.ts new file mode 100644 index 000000000..85ff8ae28 --- /dev/null +++ b/packages/pinia-orm/tests/feature/reactivity/reactivity.spec.ts @@ -0,0 +1,129 @@ +import { describe, expect, it } from 'vitest' +import { computed } from 'vue-demi' + +import { Model, useRepo } from '../../../src' +import { Attr, Str } from '../../../src/decorators' +import { fillState } from '../../helpers' + +describe('feature/reactivity/reactivity', () => { + class User extends Model { + static entity = 'users' + + @Attr() id!: any + @Str('') name!: string + } + + it('check save reactivity', () => { + const userRepo = useRepo(User) + + const allUsers = computed(() => userRepo.all()) + + expect(allUsers.value).toEqual([]) + + userRepo.save([ + { id: 1, name: 'John Doe' }, + { id: 2, name: 'Jane Doe' }, + { id: 3, name: 'Johnny Doe' } + ]) + + expect(allUsers.value).toEqual([ + { id: 1, name: 'John Doe' }, + { id: 2, name: 'Jane Doe' }, + { id: 3, name: 'Johnny Doe' } + ]) + }) + + it('check insert reactivity', () => { + const userRepo = useRepo(User) + + const allUsers = computed(() => userRepo.all()) + + expect(allUsers.value).toEqual([]) + + userRepo.insert({ id: 1, name: 'John Doe' }) + + expect(allUsers.value).toEqual([ + { id: 1, name: 'John Doe' } + ]) + }) + + it('check update reactivity', () => { + const userRepo = useRepo(User) + + fillState({ + users: { + 1: { id: 1, name: 'John Doe' }, + 2: { id: 2, name: 'Jane Doe' }, + 3: { id: 3, name: 'Johnny Doe' } + } + }) + + const allUsers = computed(() => userRepo.all()) + + expect(allUsers.value).toEqual([ + { id: 1, name: 'John Doe' }, + { id: 2, name: 'Jane Doe' }, + { id: 3, name: 'Johnny Doe' } + ]) + + userRepo.where('name', 'Jane Doe').update({ name: 'Jane Doe Updated' }) + + expect(allUsers.value).toEqual([ + { id: 1, name: 'John Doe' }, + { id: 2, name: 'Jane Doe Updated' }, + { id: 3, name: 'Johnny Doe' } + ]) + }) + + it('check destroy reactivity', () => { + const userRepo = useRepo(User) + + fillState({ + users: { + 1: { id: 1, name: 'John Doe' }, + 2: { id: 2, name: 'Jane Doe' }, + 3: { id: 3, name: 'Johnny Doe' } + } + }) + + const allUsers = computed(() => userRepo.all()) + + expect(allUsers.value).toEqual([ + { id: 1, name: 'John Doe' }, + { id: 2, name: 'Jane Doe' }, + { id: 3, name: 'Johnny Doe' } + ]) + + userRepo.destroy([2, 3]) + + expect(allUsers.value).toEqual([ + { id: 1, name: 'John Doe' } + ]) + }) + + it('check delete reactivity', () => { + const userRepo = useRepo(User) + + fillState({ + users: { + 1: { id: 1, name: 'John Doe' }, + 2: { id: 2, name: 'Jane Doe' }, + 3: { id: 3, name: 'Johnny Doe' } + } + }) + + const allUsers = computed(() => userRepo.all()) + + expect(allUsers.value).toEqual([ + { id: 1, name: 'John Doe' }, + { id: 2, name: 'Jane Doe' }, + { id: 3, name: 'Johnny Doe' } + ]) + + userRepo.where('name', 'Jane Doe').orWhere('name', 'Johnny Doe').delete() + + expect(allUsers.value).toEqual([ + { id: 1, name: 'John Doe' } + ]) + }) +}) From 4e7be488cc01717cdb5dae8a9b6a5f8cbc0abf1b Mon Sep 17 00:00:00 2001 From: Maxime Lambotin Date: Fri, 9 Feb 2024 12:24:58 +0100 Subject: [PATCH 6/6] chore: add v8 ignore to vue 2 specific code --- packages/pinia-orm/src/composables/useStoreActions.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/pinia-orm/src/composables/useStoreActions.ts b/packages/pinia-orm/src/composables/useStoreActions.ts index e3693f726..eae8cb327 100644 --- a/packages/pinia-orm/src/composables/useStoreActions.ts +++ b/packages/pinia-orm/src/composables/useStoreActions.ts @@ -30,6 +30,7 @@ export function useStoreActions (query?: Query) { } else { ids.forEach(id => delete this.data[id]) // Trigger Vue 2 reactivity + /* v8 ignore next 3 */ if (this.data.__ob__) { this.data.__ob__.dep.notify() } @@ -44,6 +45,7 @@ export function useStoreActions (query?: Query) { } else { ids.forEach(id => delete this.data[id]) // Trigger Vue 2 reactivity + /* v8 ignore next 3 */ if (this.data.__ob__) { this.data.__ob__.dep.notify() }