vue-class-to-composition can convert Vue Class components to Composition API syntax. It also supports custom plugins.
- [x] Convert Vue Class component files to Composition API syntax
- [x] Handles both single files and entire directories
- [x] Supports custom plugins
name | Support |
---|---|
@Component |
✅ |
@Props |
✅ |
@PropSync |
❌️ |
@Emit |
❌️ |
@Provice |
❌️ |
@Inject |
❌️ |
@Ref |
❌️ |
@VModel |
❌️ |
@Model |
❌️ |
@ModelSynch |
❌️ |
@ProvideReactive |
❌️ |
@InjectReactive |
❌️ |
@Watch |
✅ |
name | Support | Description |
---|---|---|
Data | ✅ | |
Methods | ✅ | |
Computed Properties | ✅ | |
Hooks | ✅ | |
Hooks | ✅ | |
Other Options | ✅ | |
Custom Decorators | @Validate |
|
Extends | extends Popup<Type> |
|
Mixins | ❌️ | Future |
$refs |
Parse from this.$refs
|
- Node.js > 18
- Valid Vue file written in Typescript (
.vue
extension)
The vue-class-to-composition project has CLI and API
Install locally or global
# npm
npm i vue-class-to-composition
To convert a single .vue file, run:
# npm
# convert single vue file
npx vue-class-to-composition single [cliOptions] <vue file path>
-v, --view Preview changes in the editor
-p --pluginsDir <DIR_PATH> Path to directory with plugins
-h, --help display help for command
Example:
# npm
# convert single vue file
npx vue-class-to-composition single "src/components/HelloWorld.vue"
Example output
✔ Successfully converted file: src/components/HelloWorld.vue
To convert all .vue files in a specified directory, run:
# npm
# convert folder
npx vue-class-to-composition folder <folder dir path>
-v, --view Preview changes in the editor
-p --pluginsDir <DIR_PATH> Path to directory with plugins
-h, --help display help for command
import {convertSingleFile, type TransformPlugin, convert, convertFolder} from 'vue-class-to-composition'
// See plugins section for example plugin
const serverClientPlugin: TransformPlugin = ({ast, t, store, traverse}) => {};
const code = `
<template><div></div></template>
<script lang="ts">
@Component({ i18n, components: { NotificationTemplate, MdButton } })
export default class LanguageSelector extends Popup<IJobModelForCustomer> {}
</script>
`
const convertAll = async () => {
// Convert content code and get result
const result = await convert(code, {
plugins: [serverClientPlugin],
// Prettier config
prettierConfig: {}
})
console.log(result)
// Convert file
await convertSingleFile('./vcc.vue', {
// Don't write file, just preview
view: true,
convertOptions: {
plugins: [serverClientPlugin],
// Prettier config
prettierConfig: {}
}
})
// Convert folder
await convertFolder('./dir', {
view: true,
convertOptions: {
plugins: [serverClientPlugin]
}
})
}
convertAll();
name | Description |
---|---|
i18n | Add const {t} = useI18n(i18n)
|
popup | Add props from extends Popup<boolean>
|
serverClient | Replace inject(SomeClient) to useServerClient(SomeClient)
|
useRouter | Add composables useRoute, useRouter
|
validate | Parse custom validator @Validate
|
You can create custom plugin
export interface PluginParams {
// AST tree from @babel/parser
ast: ParseResult<t.File>;
// @babel/types for creating AST
t: typeof t;
// @babel/traverse for traversing AST
traverse: typeof traverse;
// Conversion store
store: typeof ConversionStore;
}
declare const ConversionStore: {
addPropName: (propName: string) => void;
hasPropName: (propName: string) => boolean;
setFlag: (flagName: string, value: boolean) => void;
getFlag: (flagName: string) => boolean | undefined;
clear: () => void;
printStore: () => void;
addImport: (source: string, key: string, isDefault?: boolean) => void;
getImports: () => Map<string, Map<string, {
value: string;
isDefault: boolean;
}>>;
addBeforeSetupStatement: (node: t.Statement) => void;
getBeforeSetupStatements: () => Set<t.Statement>;
addSetupContextKey: (name: string) => void;
getSetupContextKeys: () => Set<string>;
addAfterSetupStatement: (node: t.Statement) => void;
getAfterSetupStatements: () => Set<t.Statement>;
addReturnStatement: (name: string, node: t.ObjectMethod | t.ObjectProperty | t.SpreadElement) => void;
getReturnStatement: () => Map<string, t.ObjectMethod | t.ObjectProperty | t.SpreadElement>;
addRef: (name: string) => void;
hasRefName: (name: string) => boolean;
addShortReturnStatementByName: (name: string) => void;
addExcludeRef: (name: string) => void;
hasExcludeRefsName: (name: string) => boolean;
registerPlugin: (name: string, plugin: TransformPlugin) => void;
getPlugins: () => TransformPlugin[];
addProp: (propName: string, node: t.ObjectProperty) => void;
getProps: () => Map<string, t.ObjectProperty>;
addExcludesNamesImportSpecifier: (name: string) => void;
getExcludesNamesImportSpecifier: () => Set<string>;
};
export default ConversionStore;
Create folder for plugins
src/
├── plugins/ # Directory to hold all plugin files
│ ├── serverClientPlugin.js # Example plugin file
│ ├── otherPlugin.js # Additional plugin file
Write plugin. Example plugin
const serverClientPlugin = ({ ast, t, store, traverse }) => {
traverse(ast, {
CallExpression: (path) => {
if (!path.node.arguments) {
return;
}
const arg = path.node?.arguments[0];
if (!arg) {
return;
}
if (!t.isIdentifier(arg)) {
return;
}
const name = arg.name;
if (!name.endsWith('Client')) {
return;
}
const newExpression = t.callExpression(t.identifier('useServerClient'), [arg]);
store.addImport('composables/use-server-client', 'useServerClient', true);
path.replaceWith(newExpression);
path.skip();
if (!Array.isArray(path.container) && t.isClassProperty(path.container)) {
if (t.isIdentifier(path.container.key)) {
store.addExcludeRef(path.container.key.name);
}
}
},
});
};
module.exports = serverClientPlugin
# npm
# convert single file with plugins dir
npx vue-class-to-composition single "<full_path>/vcc.vue" -v --pluginsDir "<full_path>/plugins"
import {convertSingleFile, type TransformPlugin, convert, convertFolder} from 'vue-class-to-composition'
const serverClientPlugin: TransformPlugin = ({ast, t, store, traverse}) => {
traverse(ast, {
CallExpression: (path) => {
if (!path.node.arguments) {
return;
}
const arg = path.node?.arguments[0];
if (!arg) {
return;
}
if (!t.isIdentifier(arg)) {
return;
}
const name = arg.name;
if (!name.endsWith('Client')) {
return;
}
const newExpression = t.callExpression(t.identifier('useSServerClient'), [arg]);
store.addImport('composables/use-server-client', 'useServerClient', true);
path.replaceWith(newExpression);
path.skip();
if (!Array.isArray(path.container) && t.isClassProperty(path.container)) {
if (t.isIdentifier(path.container.key)) {
store.addExcludeRef(path.container.key.name);
}
}
},
});
};
// Convert content code and get result
const result = await convert(code, {plugins: [serverClientPlugin],})
// Get file and write file
await convertSingleFile('./vcc.vue', {convertOptions: {plugins: [serverClientPlugin],}})
// Convert folder
await convertFolder('./dir', {convertOptions: {plugins: [serverClientPlugin]}})
This project is licensed under the MIT License. See the LICENSE file for details.
This README provides a comprehensive overview of your project, explaining how to install, use, and understand its functionality. You can customize the repository link and other specifics as needed.