{"id":18630809,"url":"https://github.com/sopamo/double-vue","last_synced_at":"2025-04-11T06:31:22.540Z","repository":{"id":45779130,"uuid":"447528943","full_name":"Sopamo/double-vue","owner":"Sopamo","description":"The missing link between Laravel and Vue","archived":false,"fork":false,"pushed_at":"2022-11-30T15:58:01.000Z","size":841,"stargazers_count":24,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-29T10:46:01.433Z","etag":null,"topics":["api","laravel","vue"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sopamo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-13T08:55:25.000Z","updated_at":"2024-02-21T15:05:18.000Z","dependencies_parsed_at":"2023-01-21T22:15:12.594Z","dependency_job_id":null,"html_url":"https://github.com/Sopamo/double-vue","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sopamo%2Fdouble-vue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sopamo%2Fdouble-vue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sopamo%2Fdouble-vue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sopamo%2Fdouble-vue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sopamo","download_url":"https://codeload.github.com/Sopamo/double-vue/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223460680,"owners_count":17148759,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","laravel","vue"],"created_at":"2024-11-07T05:04:18.350Z","updated_at":"2024-11-07T05:04:30.468Z","avatar_url":"https://github.com/Sopamo.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv id=\"top\"\u003e\u003c/div\u003e\n\n\u003cbr /\u003e\n\u003cdiv align=\"center\"\u003e\n\n  ![double logo](./assets/logo-transparent.png)\n\n  \u003cp align=\"center\"\u003e\n    The missing link between Laravel and Vue.\u003cbr /\u003e\n    \u003cstrong\u003eStatus\u003c/strong\u003e: alpha\u003cbr /\u003e\n    RC planned for Q4 / 2022\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/Sopamo/double-demo\"\u003eTry the demo project\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n## About Double\n\nDouble drastically simplifies writing Vue applications with a Laravel backend. It does so, by removing all of the API boilerplate code you have to write.\n\n![workflow comparison](./assets/double-workflow-explanation.png)\n\n\n### How does it work?\nTraditionally, your API code lives in  `App\\Http\\Controllers\\UsersController`. You also have to create an entry in your routes file, and write some frontend boilerplate code to call that API.\n\nWhen using Double, you place your API code next to your vue store / component files. For example you would have your vue store in `stores/users.ts` and your API code for that store in `stores/users.php`.\n\nThis let's Double automatically associate your API code with your frontend code. By creating *closeness* in the file system, you don't need to manually connect your server-side code with your frontend.\n\n🚀 Double also analyzes your PHP code and intelligently creates TypeScript definitions!\n\n### Why?\n\n* Double removes the need for any API boilerplate code\n* Double automatically gives you TypeScript types for your backend API\n* Double integrates with pinia\n\n\n\u003cdiv align=\"center\"\u003e\n\n[![Watch the introduction video](./assets/introduction-thumbnail.png)](https://youtu.be/Amd0ynVh5Ik)\n[Watch the introduction video](https://youtu.be/Amd0ynVh5Ik)\n\n\u003c/div\u003e\n\n\n## Code says a thousand words\nThe following two files are everything you need for having a vue component which displays all users of your app:\n\n*/double/src/components/users.php*\n```php\n\u003c?php\nreturn new class {\n    public function getUsers()\n    {\n        // We return a static array here, but you can access all \n        // Laravel features here. Something like:\n        //   return User::all();\n        // would work as well.\n        return [\n          [\n            'id' =\u003e 1,\n            'username' =\u003e 'Quentin'\n          ]\n        ];\n    }\n};\n?\u003e\n```\n*/double/src/components/users.vue*\n```vue\n\u003ctemplate\u003e\n    \u003ch2\u003eUsers\u003c/h2\u003e\n    \u003c!--\n      `Double` automatically loads and injects the response\n       from the getUsers method into the users variable\n     --\u003e\n    \u003cdiv v-for=\"user in users\"\u003e\n        \u003cstrong\u003e{{ user.username }}\u003c/strong\u003e #{{ user.id }}\n    \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript lang=\"ts\"\u003e\n    import { defineComponent } from 'vue'\n    import { useDouble } from \"double-vue\";\n\n    export default defineComponent({\n        async setup() {\n            const double = await useDouble('/src/components/users')\n            return {\n                ...double,\n            }\n        },\n    })\n\u003c/script\u003e\n```\n\nYep, that's it! No need to write any API boilerplate code. All methods from the PHP file are intelligently mapped to your frontend code. Read on to discover more complex usage examples.\n\n## Demo\nBefore you start to use double in your own project, you can try out the demo project: \n\n[Open demo repository](https://github.com/Sopamo/double-demo)\n\nThe double demo is a dockerized Laravel application (using Laravel sail), so you can start to play with double in a few minutes.\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n## Installation\n\nThis is an example of how you may give instructions on setting up your project locally.\nTo get a local copy up and running follow these simple example steps.\n\n\n1. Setup a [new Laravel project](https://laravel.com/docs/9.x/installation), or use an existing one\n\n\n### **Vue setup**\n   1. Setup a vue project in the `double` subfolder\n      1. [Install](https://cli.vuejs.org/guide/installation.html) the vue cli\n      2. Go to your laravel installation\n      3. Create a new vue project `vue create double`. Make sure to select \"Manually select features\" and then check \"Typescript\" and \"vue3\".\n   3. Setup double in the new vue project\n      1. `cd double`\n      2. `npm install double-vue`\n      3. In src/main.ts add the following lines before the `createApp(App)` call:\n         ```js\n         import { installDouble } from 'double-vue'\n\n         installDouble('http://localhost/api/double', 'webpack')\n         ``` \n         Make sure to replace `localhost` with the domain that your laravel project is running at\n      4. Add this `vue.config.js` file to the root of the double folder:\n          ```js\n          const { defineConfig } = require('@vue/cli-service')\n          const { doubleWebpackPlugin } = require('double-vue/bundler')\n          const path = require(\"path\")\n\n          module.exports = defineConfig({\n            transpileDependencies: true,\n            configureWebpack: {\n              plugins: [\n                  doubleWebpackPlugin()\n              ]\n            }\n          })\n          ```\n      5. `npm run serve`\n\n### **Laravel setup**\n1. Go back to your laravel installation\n2. `composer require sopamo/double-laravel`\n3. `php artisan vendor:publish --provider=\"Sopamo\\Double\\DoubleServiceProvider\"`\n\n\n### **Use double**\n   1. Create the two example files from above (users.php and users.vue) in the `double/src/components` folder to get a working example of double.\n   2. Use your new users.vue component by embedding it with a `\u003csuspense\u003e` component like so:\n      ```\n      \u003csuspense\u003e\n        \u003cusers /\u003e\n      \u003c/suspense\u003e\n      ```\n### **Questions?**\nIf any of the steps above are unclear, you can have a look at the [demo project](https://github.com/Sopamo/double-demo) or open a [discussion](https://github.com/Sopamo/double-vue/discussions)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n## Usage\n\n### PHP naming conventions\nThe code you write in the PHP files next to your frontend files always have to return a single class:\n\n```php\n\u003c?php\nuse Illuminate\\Http\\Request;\nuse App\\Models\\User;\n\nreturn new class {\n    public function getUsers()\n    {\n      return  Users::all();\n    }\n\n    public function storeUser(Request $request) {\n      $user = new User();\n      $user-\u003eusername = $request-\u003einput('username');\n      $user-\u003esave();\n    }\n};\n?\u003e\n```\n\nDefine the data that you want to receive as *state* with methods starting with `get`, followed by an uppercase letter.\nThis data will automatically be fetched when Double initializes.\n\nAll other public methods are available as actions:\n\n```js\nimport { useDouble } from 'double-vue'\n\nconst double = useDouble('/src/pages/users')\n\n// This will contain the return value of the getUsers method\nconsole.log(double.users)\n\n// This will call the storeUser method\ndouble.storeUser({username: 'Bob Marley'})\n```\n\n### Refreshing the state\nSometimes you want to update the Double state with the latest data from the server. Use the `refresh` method for that:\n\n```js\ndouble.refresh()\n```\n\n### Parameters for state methods\nSometimes you want to configure state fetching methods dynamically, for example if you don't want to return all users, but only users which match a given query:\n\n```js\nimport { useDouble } from 'double-vue'\n\nconst userQuery = ref('Bob')\n\nconst double = useDouble('/src/pages/users', {\n  getUsers: {\n    search: userQuery\n  }\n})\n\n// This will automatically trigger a refresh, then loading all users which match the query \"Johnny\"\nuserQuery.value = 'Johnny'\n```\n\nYou can use the normal Laravel methods to access the search parameter:\n```php\n$request-\u003einput('search') // Contains \"Bob\"\n```\n\n### Sending custom headers\nIf you are not using cookie-based authentication, you will want to set an authorization header in the requests that Double sends:\n\n```js\nimport { setCustomHeader } from 'double-vue'\n\nsetCustomHeader('Authorization', 'Bearer ' + yourToken)\n```\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n## Roadmap\n\n- [ ] PHPStorm setup instructions\n- [x] Create a screencast\n- [x] Finalize readme\n- [x] Add support to configure the data requests in pinia\n- [x] Finalize the example project\n- [x] Unify double between regular usage and pinia\n- [x] Fix HMR breaking in sample project\n- [x] Add support for the refresh method outside of pinia\n- [x] Error handling\n- [x] Ignore private / protected php methods\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\nIf you have a suggestion on how to improve Double, please fork the repo and create a pull request. You can also simply open an issue with any questions or bugs you find.\nDon't forget to give the project a star! Thanks again!\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n## License\n\nDistributed under the MIT License. See `LICENSE.txt` for more information.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsopamo%2Fdouble-vue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsopamo%2Fdouble-vue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsopamo%2Fdouble-vue/lists"}