vue-class-to-composition
v1.1.9
Published
Convert Vue files written using the old syntax Vue Class Components into Vue composition API syntax
Downloads
566
Maintainers
Readme
vue-class-to-composition
vue-class-to-composition can convert Vue Class components to Composition API syntax. It also supports custom plugins.
Features
- [x] Convert Vue Class component files to Composition API syntax
- [x] Handles both single files and entire directories
- [x] Supports custom plugins
Supported features
vue-property-decorator
| name | Support |
|--------------------|---------|
| @Component
| ✅ |
| @Props
| ✅ |
| @PropSync
| ❌️ |
| @Emit
| ❌️ |
| @Provice
| ❌️ |
| @Inject
| ❌️ |
| @Ref
| ❌️ |
| @VModel
| ❌️ |
| @Model
| ❌️ |
| @ModelSynch
| ❌️ |
| @ProvideReactive
| ❌️ |
| @InjectReactive
| ❌️ |
| @Watch
| ✅ |
vue-class-component
| 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
|
Requirements
- Node.js > 18
- Valid Vue file written in Typescript (
.vue
extension)
Usage
The vue-class-to-composition project has CLI and API
Install locally or global
# npm
npm i vue-class-to-composition
CLI
Convert a Single File
To convert a single .vue file, run:
# npm
# convert single vue file
npx vue-class-to-composition single [cliOptions] <vue file path>
Options
-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
Convert All Files in a Directory
To convert all .vue files in a specified directory, run:
# npm
# convert folder
npx vue-class-to-composition folder <folder dir path>
Options
-v, --view Preview changes in the editor
-p --pluginsDir <DIR_PATH> Path to directory with plugins
-h, --help display help for command
API
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();
Plugins
Default plugins for (SC company)
| 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
|
Example plugin
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;
CLI
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"
API
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]}})
Useful Links
- https://lihautan.com/babel-ast-explorer/
License
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.