-
-
Notifications
You must be signed in to change notification settings - Fork 270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@casl/vue - Vue 3 support #396
Comments
Cool. From the history point of view, there were almost no changes in package as soon as it was finished. thats why I think there is no need to support both versions simultaneously. Let’s just change the code and release a new major version. For Vue2, people will need to use previous version |
Sounds like a plan! I should be able to get started next week. |
Cool @rak-phillip looking forward to your PR! |
@stalniy I'm still trying to wrap my head around TypeScript and Vue 3 🤔🤔🤔 Seeing if I can't figure out how to update The good news is that I was able to work through the plugin fairly easily, but we won't know how successful it is until we can run tests. |
Check how they did this for vue-router - https://github.com/vuejs/vue-router-next/blob/master/src/globalExtensions.ts |
That was a really good find. Thanks for pointing me in the right direction, I think I'm getting it 😁😁😁 This is taking a lot longer than expected 😤. I hope to have a PR in the coming week, barring any other unexpected developments. |
Waiting for it :) If you have any other blockers let me know and I'll try to help |
Hi @rak-phillip Do you have any news or blockers on your side? |
Here is my rough implementation of casl for vue 3 waiting for official package release [plugin.ts]
[types.d.ts]
|
@stalniy time commitment is my biggest blocker at this point. I've pushed my changes to the vue-3 branch in my fork of the project if you would like to reference. I last left off seeing if we could implement a setup function for After the can component is finished, we need to update tests and documentation. |
I see, thanks for the update and reference to the branch. I'll take a look as soon as I finish with docs for v5. What I have in mind for this integration is:
app.config.globalProperties.$can = ability.can.bind(ability); what do you think? PROS:
Update: I also think whether it make sense to keep |
I think everything that you propose sounds great and more like idiomatic Vue 3, but I realize that I'm over complicating things after typing my original response 🦆. Just because render functions no longer receive arguments doesn't mean that they don't have access to |
Pushed more changes to the forked project. Only a few type errors to work through at this point. |
@stalniy I'm able to generate a working demo after upgrading CASL Vue todo to Vue 3. Moving onto unit tests. |
@rak-phillip how do you run tests? What package manager do u use? According to the deps babel-jest is in dev deps, so everything should be fine. Wh P.s.: |
@stalniy thanks for pointing me to the correct guidelines, I was originally using npm and switching to
Which might make sense because the contribution guidelines mention that I should be able to run all test suites with |
@rak-phillip thanks for following. This showed the missed parts in guidelines! So, you need to run |
That does the trick, thanks for working through that with me!!! |
Do we have any new updates for this issue? Looking forward for Vue 3 support and updated docs. 🙂 |
I picked up the work in a separate branch and finalizing tests. So, very soon I’ll release a new version |
Fixes #396 BREAKING CHANGE: refactor to use Vue 3 what introduces a bunch of breaking changes: * `Ability` instance is not a required plugin parameter. Previously, we could decide whether to pass ability as plugin parameter or as root component option. Now, the only way is to pass it in plugin: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); new Vue({ ability }).$mount('#app') ``` **After** ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; createApp() .use(abilitiesPlugin, ability) .mount('#app'); ``` * `abilitiesPlugin` no more define global `$ability` and `$can` properties, instead a recommended way to get `AppAbility` instance is by injecting it through [provide/inject API](https://v3.vuejs.org/guide/component-provide-inject.html). To get previous behavior, pass `useGlobalProperties: true` option: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); const root = new Vue({ ability }).$mount('#app') console.log(root.$ability) ``` **After** Recommended way: ```js import { abilitiesPlugin, ABILITY_TOKEN } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const App = { name: 'App', inject: { $ability: { from: ABILITY_TOKEN } } }; const root = createApp(App) .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` Backward compatible way: ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const root = createApp() .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` * `AllCanProps<TAbility>` type was renamed to `CanProps<TAbility>` * `@casl/vue` no more augment vue types, so if you decide to use global properties, you will need to augment types by yourself **Before** @casl/vue augments type of `$ability` to `AnyAbility` and `$can` to `typeof $ability['can']` **After** create a separate file `src/ability-shim.d.ts` with the next content: ```ts import { AppAbility } from './AppAbility' declare module 'vue' { interface ComponentCustomProperties { $ability: AppAbility; $can(this: this, ...args: Parameters<this['$ability']['can']>): boolean; } } ```
Fixes #396 BREAKING CHANGE: refactor to use Vue 3 what introduces a bunch of breaking changes: * `Ability` instance is not a required plugin parameter. Previously, we could decide whether to pass ability as plugin parameter or as root component option. Now, the only way is to pass it in plugin: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); new Vue({ ability }).$mount('#app') ``` **After** ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; createApp() .use(abilitiesPlugin, ability) .mount('#app'); ``` * `abilitiesPlugin` no more define global `$ability` and `$can` properties, instead a recommended way to get `AppAbility` instance is by injecting it through [provide/inject API](https://v3.vuejs.org/guide/component-provide-inject.html). To get previous behavior, pass `useGlobalProperties: true` option: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); const root = new Vue({ ability }).$mount('#app') console.log(root.$ability) ``` **After** Recommended way: ```js import { abilitiesPlugin, ABILITY_TOKEN } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const App = { name: 'App', inject: { $ability: { from: ABILITY_TOKEN } } }; const root = createApp(App) .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` Backward compatible way: ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const root = createApp() .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` * `AllCanProps<TAbility>` type was renamed to `CanProps<TAbility>` * `@casl/vue` no more augment vue types, so if you decide to use global properties, you will need to augment types by yourself **Before** @casl/vue augments type of `$ability` to `AnyAbility` and `$can` to `typeof $ability['can']` **After** create a separate file `src/ability-shim.d.ts` with the next content: ```ts import { AppAbility } from './AppAbility' declare module 'vue' { interface ComponentCustomProperties { $ability: AppAbility; $can(this: this, ...args: Parameters<this['$ability']['can']>): boolean; } } ```
Fixes #396 BREAKING CHANGE: refactor to use Vue 3 what introduces a bunch of breaking changes: * `Ability` instance is not a required plugin parameter. Previously, we could decide whether to pass ability as plugin parameter or as root component option. Now, the only way is to pass it in plugin: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); new Vue({ ability }).$mount('#app') ``` **After** ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; createApp() .use(abilitiesPlugin, ability) .mount('#app'); ``` * `abilitiesPlugin` no more define global `$ability` and `$can` properties, instead a recommended way to get `AppAbility` instance is by injecting it through [provide/inject API](https://v3.vuejs.org/guide/component-provide-inject.html). To get previous behavior, pass `useGlobalProperties: true` option: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); const root = new Vue({ ability }).$mount('#app') console.log(root.$ability) ``` **After** Recommended way: ```js import { abilitiesPlugin, ABILITY_TOKEN } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const App = { name: 'App', inject: { $ability: { from: ABILITY_TOKEN } } }; const root = createApp(App) .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` Backward compatible way: ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const root = createApp() .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` * `AllCanProps<TAbility>` type was renamed to `CanProps<TAbility>` * `@casl/vue` no more augment vue types, so if you decide to use global properties, you will need to augment types by yourself **Before** @casl/vue augments type of `$ability` to `AnyAbility` and `$can` to `typeof $ability['can']` **After** create a separate file `src/ability-shim.d.ts` with the next content: ```ts import { AppAbility } from './AppAbility' declare module 'vue' { interface ComponentCustomProperties { $ability: AppAbility; $can(this: this, ...args: Parameters<this['$ability']['can']>): boolean; } } ```
Fixes #396 BREAKING CHANGE: refactor to use Vue 3 what introduces a bunch of breaking changes: * `Ability` instance is not a required plugin parameter. Previously, we could decide whether to pass ability as plugin parameter or as root component option. Now, the only way is to pass it in plugin: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); new Vue({ ability }).$mount('#app') ``` **After** ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; createApp() .use(abilitiesPlugin, ability) .mount('#app'); ``` * `abilitiesPlugin` no more define global `$ability` and `$can` properties, instead a recommended way to get `AppAbility` instance is by injecting it through [provide/inject API](https://v3.vuejs.org/guide/component-provide-inject.html). To get previous behavior, pass `useGlobalProperties: true` option: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); const root = new Vue({ ability }).$mount('#app') console.log(root.$ability) ``` **After** Recommended way: ```js import { abilitiesPlugin, ABILITY_TOKEN } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const App = { name: 'App', inject: { $ability: { from: ABILITY_TOKEN } } }; const root = createApp(App) .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` Backward compatible way: ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const root = createApp() .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` * `AllCanProps<TAbility>` type was renamed to `CanProps<TAbility>` * `@casl/vue` no more augment vue types, so if you decide to use global properties, you will need to augment types by yourself **Before** @casl/vue augments type of `$ability` to `AnyAbility` and `$can` to `typeof $ability['can']` **After** create a separate file `src/ability-shim.d.ts` with the next content: ```ts import { AppAbility } from './AppAbility' declare module 'vue' { interface ComponentCustomProperties { $ability: AppAbility; $can(this: this, ...args: Parameters<this['$ability']['can']>): boolean; } } ```
Fixes #396 BREAKING CHANGE: refactor to use Vue 3 what introduces a bunch of breaking changes: * `Ability` instance is not a required plugin parameter. Previously, we could decide whether to pass ability as plugin parameter or as root component option. Now, the only way is to pass it in plugin: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); new Vue({ ability }).$mount('#app') ``` **After** ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; createApp() .use(abilitiesPlugin, ability) .mount('#app'); ``` * `abilitiesPlugin` no more define global `$ability` and `$can` properties, instead a recommended way to get `AppAbility` instance is by injecting it through [provide/inject API](https://v3.vuejs.org/guide/component-provide-inject.html). To get previous behavior, pass `useGlobalProperties: true` option: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); const root = new Vue({ ability }).$mount('#app') console.log(root.$ability) ``` **After** Recommended way: ```js import { abilitiesPlugin, ABILITY_TOKEN } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const App = { name: 'App', inject: { $ability: { from: ABILITY_TOKEN } } }; const root = createApp(App) .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` Backward compatible way: ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const root = createApp() .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` * `AllCanProps<TAbility>` type was renamed to `CanProps<TAbility>` * `@casl/vue` no more augment vue types, so if you decide to use global properties, you will need to augment types by yourself **Before** @casl/vue augments type of `$ability` to `AnyAbility` and `$can` to `typeof $ability['can']` **After** create a separate file `src/ability-shim.d.ts` with the next content: ```ts import { AppAbility } from './AppAbility' declare module 'vue' { interface ComponentCustomProperties { $ability: AppAbility; $can(this: this, ...args: Parameters<this['$ability']['can']>): boolean; } } ```
Fixes #396 BREAKING CHANGE: refactor to use Vue 3 what introduces a bunch of breaking changes: * `Ability` instance is not a required plugin parameter. Previously, we could decide whether to pass ability as plugin parameter or as root component option. Now, the only way is to pass it in plugin: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); new Vue({ ability }).$mount('#app') ``` **After** ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; createApp() .use(abilitiesPlugin, ability) .mount('#app'); ``` * `abilitiesPlugin` no more define global `$ability` and `$can` properties, instead a recommended way to get `AppAbility` instance is by injecting it through [provide/inject API](https://v3.vuejs.org/guide/component-provide-inject.html). To get previous behavior, pass `useGlobalProperties: true` option: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); const root = new Vue({ ability }).$mount('#app') console.log(root.$ability) ``` **After** Recommended way: ```js import { abilitiesPlugin, ABILITY_TOKEN } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const App = { name: 'App', inject: { $ability: { from: ABILITY_TOKEN } } }; const root = createApp(App) .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` Backward compatible way: ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const root = createApp() .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` * `AllCanProps<TAbility>` type was renamed to `CanProps<TAbility>` * `@casl/vue` no more augment vue types, so if you decide to use global properties, you will need to augment types by yourself **Before** @casl/vue augments type of `$ability` to `AnyAbility` and `$can` to `typeof $ability['can']` **After** create a separate file `src/ability-shim.d.ts` with the next content: ```ts import { AppAbility } from './AppAbility' declare module 'vue' { interface ComponentCustomProperties { $ability: AppAbility; $can(this: this, ...args: Parameters<this['$ability']['can']>): boolean; } } ```
Fixes #396 BREAKING CHANGE: refactor to use Vue 3 what introduces a bunch of breaking changes: * `Ability` instance is not a required plugin parameter. Previously, we could decide whether to pass ability as plugin parameter or as root component option. Now, the only way is to pass it in plugin: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); new Vue({ ability }).$mount('#app') ``` **After** ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; createApp() .use(abilitiesPlugin, ability) .mount('#app'); ``` * `abilitiesPlugin` no more define global `$ability` and `$can` properties, instead a recommended way to get `AppAbility` instance is by injecting it through [provide/inject API](https://v3.vuejs.org/guide/component-provide-inject.html). To get previous behavior, pass `useGlobalProperties: true` option: **Before** ```js import { abilitiesPlugin } from '@casl/vue'; import Vue from 'vue'; import { ability } from './services/AppAbility'; Vue.use(abilitiesPlugin); const root = new Vue({ ability }).$mount('#app') console.log(root.$ability) ``` **After** Recommended way: ```js import { abilitiesPlugin, ABILITY_TOKEN } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const App = { name: 'App', inject: { $ability: { from: ABILITY_TOKEN } } }; const root = createApp(App) .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` Backward compatible way: ```js import { abilitiesPlugin } from '@casl/vue'; import { createApp } from 'vue'; import { ability } from './services/AppAbility'; const root = createApp() .use(abilitiesPlugin, ability, { useGlobalProperties: true }) .mount('#app'); console.log(root.$ability) ``` * `AllCanProps<TAbility>` type was renamed to `CanProps<TAbility>` * `@casl/vue` no more augment vue types, so if you decide to use global properties, you will need to augment types by yourself **Before** @casl/vue augments type of `$ability` to `AnyAbility` and `$can` to `typeof $ability['can']` **After** create a separate file `src/ability-shim.d.ts` with the next content: ```ts import { AppAbility } from './AppAbility' declare module 'vue' { interface ComponentCustomProperties { $ability: AppAbility; $can(this: this, ...args: Parameters<this['$ability']['can']>): boolean; } } ```
🎉 This issue has been resolved in version 2.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
breaking changes can be found in related changelog |
Is your feature request related to a problem? Please describe.
Our team is migrating our projects to Vue 3 and I would like to migrate @casl/vue to Vue 3 as well 😁.
Describe the solution you'd like
There aren't many changes that would need to be made, but they would break backwards compatibility:
createComponent
(detailed under Vue 3 TypeScript support)beforeCreate
tosetup
(detailed under lifecycle hooks)I'm thinking that we might need to create a new branch to support Vue 3 and maintain compatibility with Vue 2 and am open to ideas about how the project would best support this change.
The text was updated successfully, but these errors were encountered: