Skip to content

Commit 60f2c15

Browse files
Shywimalanpoulain
authored andcommitted
feat: add mercure to vue.js template
1 parent b9555f7 commit 60f2c15

File tree

32 files changed

+289
-76
lines changed

32 files changed

+289
-76
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ jobs:
2727
- run: yarn test-gen
2828
- run: yarn test-next-app
2929
- run: yarn test-react-app
30+
- run: yarn test-vue-app
3031
- run: yarn test-gen-env
3132
- run: yarn test-gen-openapi3
3233
- run: yarn check

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@
6565
"test-gen-custom": "rm -rf ./tmp && yarn build && babel src/generators/ReactGenerator.js src/generators/BaseGenerator.js -d ./tmp/gens && cp -r ./templates/react ./templates/react-common ./templates/entrypoint.js ./tmp/gens && ./lib/index.js https://demo.api-platform.com ./tmp/react-custom -g \"$(pwd)/tmp/gens/ReactGenerator.js\" -t ./tmp/gens",
6666
"test-gen-env": "rm -rf ./tmp && yarn build && API_PLATFORM_CLIENT_GENERATOR_ENTRYPOINT=https://demo.api-platform.com API_PLATFORM_CLIENT_GENERATOR_OUTPUT=./tmp ./lib/index.js",
6767
"test-react-app": "rm -rf ./tmp/app && mkdir -p ./tmp/app && yarn create react-app ./tmp/app/reactapp && yarn --cwd ./tmp/app/reactapp add react-router-dom@5 redux redux-thunk react-redux redux-form connected-react-router && cp -R ./tmp/react/* ./tmp/app/reactapp/src && cp ./templates/react/index.js ./tmp/app/reactapp/src && start-server-and-test 'BROWSER=none yarn --cwd ./tmp/app/reactapp start' http://127.0.0.1:3000/books/ 'yarn playwright test'",
68-
"test-next-app": "rm -rf ./tmp/app && mkdir -p ./tmp/app && yarn create next-app --typescript ./tmp/app/next && yarn --cwd ./tmp/app/next add isomorphic-unfetch formik react-query && cp -R ./tmp/next/* ./tmp/app/next && rm ./tmp/app/next/pages/index.tsx && rm -rf ./tmp/app/next/pages/api && yarn --cwd ./tmp/app/next build && start-server-and-test 'yarn --cwd ./tmp/app/next start' http://127.0.0.1:3000/books/ 'yarn playwright test'"
68+
"test-next-app": "rm -rf ./tmp/app && mkdir -p ./tmp/app && yarn create next-app --typescript ./tmp/app/next && yarn --cwd ./tmp/app/next add isomorphic-unfetch formik react-query && cp -R ./tmp/next/* ./tmp/app/next && rm ./tmp/app/next/pages/index.tsx && rm -rf ./tmp/app/next/pages/api && yarn --cwd ./tmp/app/next build && start-server-and-test 'yarn --cwd ./tmp/app/next start' http://127.0.0.1:3000/books/ 'yarn playwright test'",
69+
"test-vue-app": "rm -rf ./tmp/app && mkdir -p ./tmp/app && cd ./tmp/app && npm init -y vue@2 -- --router vue && cd ../.. && yarn --cwd ./tmp/app/vue add vuex@3 vuex-map-fields lodash && cp -R ./tmp/vue/* ./tmp/app/vue/src && cp ./templates/vue/main.js ./tmp/app/vue/src && yarn --cwd ./tmp/app/vue build && start-server-and-test 'yarn --cwd ./tmp/app/vue vite preview --host 127.0.0.1 --port 3000' http://127.0.0.1:3000/books/ 'yarn playwright test'"
6970
},
7071
"lint-staged": {
7172
"src/**/*.js": "yarn lint --fix"

src/generators/ReactGenerator.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ export default class extends BaseGenerator {
55
constructor(params) {
66
super(params);
77

8+
this.registerTemplates("common/", [
9+
// utils
10+
"utils/mercure.js",
11+
]);
12+
813
this.registerTemplates("react-common/", [
914
// actions
1015
"actions/foo/create.js",
@@ -130,6 +135,7 @@ combineReducers({ ${titleLc},/* ... */ }),
130135
context,
131136
false
132137
);
138+
this.createFile("utils/mercure.js", `${dir}/utils/mercure.js`);
133139

134140
this.createEntrypoint(api.entrypoint, `${dir}/config/entrypoint.js`);
135141
}

src/generators/ReactNativeGenerator.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export default class extends BaseGenerator {
1313
return options.inverse(this);
1414
});
1515

16+
this.registerTemplates("common/", [
17+
// utils
18+
"utils/mercure.js",
19+
]);
20+
1621
this.registerTemplates(`react-common/`, [
1722
// actions
1823
"actions/foo/create.js",
@@ -133,6 +138,7 @@ combineReducers({ ${titleLc}, /* ... */ }),
133138

134139
[
135140
"utils/dataAccess.js",
141+
"utils/mercure.js",
136142
"utils/helpers.js",
137143
"components/Spinner.js",
138144
"components/Confirm.js",

src/generators/VueGenerator.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ export default class extends BaseGenerator {
55
constructor(params) {
66
super(params);
77

8+
this.registerTemplates("common/", [
9+
// utils
10+
"utils/mercure.js",
11+
]);
12+
813
this.registerTemplates(`vue/`, [
914
// modules
1015
"store/modules/foo/index.js",
@@ -36,6 +41,10 @@ export default class extends BaseGenerator {
3641
"components/foo/Update.vue",
3742
"components/foo/Show.vue",
3843

44+
// mixins
45+
"mixins/ItemWatcher.js",
46+
"mixins/ListWatcher.js",
47+
3948
// routes
4049
"router/foo.js",
4150

@@ -102,9 +111,13 @@ export const store = new Vuex.Store({
102111

103112
// Create directories
104113
// These directories may already exist
105-
[`${dir}/config`, `${dir}/error`, `${dir}/router`, `${dir}/utils`].forEach(
106-
(dir) => this.createDir(dir, false)
107-
);
114+
[
115+
`${dir}/config`,
116+
`${dir}/error`,
117+
`${dir}/mixins`,
118+
`${dir}/router`,
119+
`${dir}/utils`,
120+
].forEach((dir) => this.createDir(dir, false));
108121

109122
[
110123
`${dir}/store/modules/${lc}`,
@@ -153,6 +166,10 @@ export const store = new Vuex.Store({
153166
this.createFileFromPattern(pattern, dir, lc, context)
154167
);
155168

169+
for (const file of ["mixins/ItemWatcher.js", "mixins/ListWatcher.js"]) {
170+
this.createFile(file, `${dir}/${file}`);
171+
}
172+
156173
// error
157174
this.createFile(
158175
"error/SubmissionError.js",
@@ -174,5 +191,6 @@ export const store = new Vuex.Store({
174191
{ hydraPrefix: this.hydraPrefix },
175192
false
176193
);
194+
this.createFile("utils/mercure.js", `${dir}/utils/mercure.js`);
177195
}
178196
}

templates/common/utils/mercure.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ENTRYPOINT } from "../config/entrypoint";
2+
3+
export const mercureSubscribe = (hubURL, topics, setData) => {
4+
const url = new URL(hubURL, ENTRYPOINT);
5+
topics.forEach(topic =>
6+
url.searchParams.append("topic", (new URL(topic, ENTRYPOINT)).toString())
7+
);
8+
const eventSource = new EventSource(url.toString());
9+
eventSource.addEventListener("message", (event) => setData(JSON.parse(event.data)));
10+
11+
return eventSource;
12+
}
13+
14+
export const extractHubURL = (response) => {
15+
const linkHeader = response.headers.get('Link');
16+
if (!linkHeader) return null;
17+
18+
const matches = linkHeader.match(
19+
/<([^>]+)>;\s+rel=(?:mercure|"[^"]*mercure[^"]*")/
20+
);
21+
22+
return matches && matches[1] ? new URL(matches[1], ENTRYPOINT) : null;
23+
}

templates/react-common/actions/foo/list.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import {
2-
fetch,
3-
normalize,
4-
extractHubURL,
5-
mercureSubscribe as subscribe
6-
} from '../../utils/dataAccess';
1+
import { fetch, normalize } from '../../utils/dataAccess';
2+
import { extractHubURL, mercureSubscribe as subscribe } from "../../utils/mercure";
73
import { success as deleteSuccess } from './delete';
84

95
export function error(error) {
@@ -61,11 +57,9 @@ export function reset(eventSource) {
6157

6258
export function mercureSubscribe(hubURL, topics) {
6359
return dispatch => {
64-
const eventSource = subscribe(hubURL, topics);
60+
const eventSource = subscribe(hubURL, topics, data =>
61+
dispatch(mercureMessage(normalize(data))));
6562
dispatch(mercureOpen(eventSource));
66-
eventSource.addEventListener('message', event =>
67-
dispatch(mercureMessage(normalize(JSON.parse(event.data))))
68-
);
6963
};
7064
}
7165

templates/react-common/actions/foo/show.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import {
2-
fetch,
3-
extractHubURL,
4-
normalize,
5-
mercureSubscribe as subscribe
6-
} from '../../utils/dataAccess';
1+
import { fetch, normalize } from '../../utils/dataAccess';
2+
import { extractHubURL, mercureSubscribe as subscribe } from "../../utils/mercure";
73

84
export function error(error) {
95
return { type: '{{{uc}}}_SHOW_ERROR', error };
@@ -54,11 +50,9 @@ export function reset(eventSource) {
5450

5551
export function mercureSubscribe(hubURL, topic) {
5652
return dispatch => {
57-
const eventSource = subscribe(hubURL, [topic]);
53+
const eventSource = subscribe(hubURL, [topic], data =>
54+
dispatch(mercureMessage(normalize(data))));
5855
dispatch(mercureOpen(eventSource));
59-
eventSource.addEventListener('message', event =>
60-
dispatch(mercureMessage(normalize(JSON.parse(event.data))))
61-
);
6256
};
6357
}
6458

templates/react-common/actions/foo/update.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import { SubmissionError } from 'redux-form';
2-
import {
3-
fetch,
4-
extractHubURL,
5-
normalize,
6-
mercureSubscribe as subscribe
7-
} from '../../utils/dataAccess';
2+
import { fetch, normalize } from '../../utils/dataAccess';
3+
import { extractHubURL, mercureSubscribe as subscribe } from "../../utils/mercure";
84
import { success as createSuccess } from './create';
95
import { loading, error } from './delete';
106

@@ -107,11 +103,9 @@ export function reset(eventSource) {
107103

108104
export function mercureSubscribe(hubURL, topic) {
109105
return dispatch => {
110-
const eventSource = subscribe(hubURL, [topic]);
106+
const eventSource = subscribe(hubURL, [topic], data =>
107+
dispatch(mercureMessage(normalize(data))));
111108
dispatch(mercureOpen(eventSource));
112-
eventSource.addEventListener('message', event =>
113-
dispatch(mercureMessage(normalize(JSON.parse(event.data))))
114-
);
115109
};
116110
}
117111

templates/react-common/utils/dataAccess.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,6 @@ export function fetch(id, options = {}) {
4646
});
4747
}
4848

49-
export function mercureSubscribe(url, topics) {
50-
topics.forEach(topic =>
51-
url.searchParams.append('topic', new URL(topic, ENTRYPOINT))
52-
);
53-
54-
return new EventSource(url.toString());
55-
}
56-
5749
export function normalize(data) {
5850
if (has(data, 'hydra:member')) {
5951
// Normalize items in collections
@@ -70,14 +62,3 @@ export function normalize(data) {
7062
: get(value, '@id', value)
7163
);
7264
}
73-
74-
export function extractHubURL(response) {
75-
const linkHeader = response.headers.get('Link');
76-
if (!linkHeader) return null;
77-
78-
const matches = linkHeader.match(
79-
/<([^>]+)>;\s+rel=(?:mercure|"[^"]*mercure[^"]*")/
80-
);
81-
82-
return matches && matches[1] ? new URL(matches[1], ENTRYPOINT) : null;
83-
}

templates/vue/components/foo/Create.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div>
3-
<h1>New {{{title}}}</h1>
3+
<h1>Create {{{title}}}</h1>
44

55
<div
66
v-if="isLoading"
@@ -29,7 +29,7 @@
2929
<script>
3030
import { createHelpers } from 'vuex-map-fields';
3131
import { mapActions } from 'vuex';
32-
import {{{titleUcFirst}}}Form from './Form';
32+
import {{{titleUcFirst}}}Form from './Form.vue';
3333
3434
const { mapFields } = createHelpers({
3535
getterType: '{{{lc}}}/create/getField',

templates/vue/components/foo/List.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<table class="table table-responsive table-striped table-hover">
2222
<thead>
2323
<tr>
24-
<th>Id</th>
24+
<th>id</th>
2525
{{#each fields}}
2626
<th>{{name}}</th>
2727
{{/each }}
@@ -119,18 +119,23 @@
119119
<script>
120120
import { mapActions } from 'vuex';
121121
import { mapFields } from 'vuex-map-fields';
122+
import ListWatcher from '../../mixins/ListWatcher';
123+
import * as types from '../../store/modules/{{{lc}}}/list/mutation_types'
122124
123125
export default {
126+
mixins: [ListWatcher],
124127
computed: {
125128
...mapFields('{{{lc}}}/del', {
126129
deletedItem: 'deleted',
127130
}),
128131
...mapFields('{{{lc}}}/list', {
129132
error: 'error',
130133
items: 'items',
134+
hubUrl: 'hubUrl',
131135
isLoading: 'isLoading',
132136
view: 'view',
133137
}),
138+
itemUpdatedAction: () => `{{{lc}}}/list/${types.UPDATE_ITEM}`,
134139
},
135140
136141
mounted() {

templates/vue/components/foo/Show.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div>
3-
<h1>Show \{{ item && item['@id'] }}</h1>
3+
<h1>Show Book \{{ item && item['@id'] }}</h1>
44

55
<div
66
v-if="isLoading"
@@ -63,8 +63,12 @@
6363
<script>
6464
import { mapActions } from 'vuex';
6565
import { mapFields } from 'vuex-map-fields';
66+
import ItemWatcher from '../../mixins/ItemWatcher';
67+
import * as types from '../../store/modules/{{{lc}}}/show/mutation_types';
68+
6669
6770
export default {
71+
mixins: [ItemWatcher],
6872
computed: {
6973
...mapFields('{{{lc}}}/del', {
7074
deleteError: 'error',
@@ -73,7 +77,9 @@ export default {
7377
error: 'error',
7478
isLoading: 'isLoading',
7579
item: 'retrieved',
80+
hubUrl: 'hubUrl',
7681
}),
82+
itemUpdatedAction: () =>`{{{lc}}}/show/${types.{{{uc}}}_SHOW_SET_RETRIEVED}`,
7783
},
7884
7985
beforeDestroy () {

0 commit comments

Comments
 (0)