Skip to content

Commit 6db2876

Browse files
committed
Monitor for injected vuex data in the Inertia props
1 parent 0bfa4a2 commit 6db2876

File tree

4 files changed

+122
-10
lines changed

4 files changed

+122
-10
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Front end package for capturing backend vuex injection that works with InertiaJS
2+
3+
### Update your Vue instance
4+
```
5+
createInertiaApp({
6+
resolve: name => {
7+
const page = require(`./pages/${name}`).default;
8+
page.layout = MainLayout;
9+
return page;
10+
},
11+
setup({ el, App, props, plugin }) {
12+
Vue.use(plugin);
13+
14+
new Vue({
15+
modals,
16+
store,
17+
mounted() {
18+
hydrateWatch(this, store);
19+
},
20+
render: h => h(App, props)
21+
}).$mount(el);
22+
},
23+
});
24+
```
25+
The `mounted()` event is where it all happens - it calls the hydration method to monitor for inertia props.
26+
27+
### How to inject vuex data in your render calls
28+
```
29+
Vuex::load('user', 'profile');
30+
31+
return Inertia::render('Page/Example', [
32+
'$vuex' => Vuex::toJson()
33+
]);
34+
```

packages/@pderas/state/lib/committer.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const VuexcellentAutoCommitter = (
88
) => {
99
const { axios, logger } = options
1010
if (!axios) {
11-
logger.warning("[Phase] Axios not found, skipping API auto mutation Vuex Plugin");
11+
logger.warning("[VuexHydrate] Axios not found, skipping API auto mutation Vuex Plugin");
1212
return [];
1313
}
1414

@@ -31,7 +31,7 @@ export const VuexcellentAutoCommitter = (
3131
*
3232
* @param {Object} data_2 server supplied state for mutations
3333
*/
34-
const autoCommitData = (
34+
export const autoCommitData = (
3535
{ store, _state, mutator }: { store: InitializedVuexStore; _state: VuexModule; mutator: (key: string, ns?: string | null) => string; },
3636
{ state = {}, modules = {} }: VuexModule,
3737
logger: IPhaseLogger
@@ -113,11 +113,11 @@ const autoMutateInterceptor = (
113113
*/
114114
(response: AxiosResponse) => {
115115
if (!response.data.$vuex) {
116-
logger.debug("[Phase] no vuex data detected. Skipping auto mutations.")
116+
logger.debug("[VuexHydrate] no vuex data detected. Skipping auto mutations.")
117117
return response;
118118
}
119119

120-
logger.debug("[Phase] vuex data detected, attempting to auto-commit")
120+
logger.debug("[VuexHydrate] vuex data detected, attempting to auto-commit")
121121

122122
try {
123123
// grab state & modules, if existing & auto-commit
@@ -140,4 +140,4 @@ const autoMutateInterceptor = (
140140
}
141141

142142
return response;
143-
};
143+
};

packages/@pderas/state/lib/index.ts

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { VuexcellentOptions, VuexStore, VuexModule } from "@pderas/vuex-hydrate-state";
1+
import { InitializedVuexStore, VuexcellentOptions, VuexStore, VuexModule, IPhaseLogger } from "@pderas/vuex-hydrate-state";
22
import { loggingMerge, objectMerge } from "./objectMerge";
33
import { mutantGenerator } from "./mutations";
4-
import { VuexcellentAutoCommitter } from "./committer";
4+
import { VuexcellentAutoCommitter, autoCommitData } from "./committer";
55
import { AxiosInstance } from "axios";
66
import { createLogger } from './logger'
77

@@ -30,6 +30,7 @@ const defaultOptions = <VuexcellentOptions>{
3030

3131
export const hydrate = (vuexState: VuexStore, options: VuexcellentOptions = defaultOptions) => {
3232
let __PHASE_STATE__ = globalBase.__PHASE_STATE__ ?? {}
33+
3334
options = {
3435
...defaultOptions,
3536
...options
@@ -57,7 +58,6 @@ export const hydrate = (vuexState: VuexStore, options: VuexcellentOptions = defa
5758
: mergedState;
5859

5960
logger.info(`[Phase] State Merged, Mutations Generated`, newState)
60-
6161
if (options.axios && options.generateMutations && __BROWSER__) {
6262
// prepare plugin
6363
const VuexcellentPlugins = VuexcellentAutoCommitter(
@@ -74,9 +74,87 @@ export const hydrate = (vuexState: VuexStore, options: VuexcellentOptions = defa
7474

7575
} else if (options.generateMutations) {
7676
logger.error(
77-
"[Phase] It appears that auto-mutate could not be initialized.\nAn instance of axios could not be found. Make sure window.axios is available"
77+
"[VuexHydrate] It appears that auto-mutate could not be initialized.\nAn instance of axios could not be found. Make sure window.axios is available"
7878
);
7979
}
8080

8181
return newState;
8282
};
83+
84+
export const hydrateWatch = (
85+
_this: any,
86+
store: InitializedVuexStore,
87+
options: VuexcellentOptions = defaultOptions,
88+
logger: IPhaseLogger
89+
) => {
90+
const inertia = _this.$inertia.page.props;
91+
if (inertia && inertia.$vuex) {
92+
let __PHASE_STATE__ = globalBase.__PHASE_STATE__ ?? {}
93+
94+
// Currently not running actions/mutations on page load
95+
const { mutations, actions, ...phaseState } = __PHASE_STATE__
96+
const vuexState = _this.$store._modules.root._rawModule;
97+
98+
// merge incoming (store) options with window.__PHASE_STATE__
99+
const mergedState = loggingMerge(logger, vuexState, <VuexStore>phaseState);
100+
101+
// generate mutations
102+
const { createMutant, getMutation } = mutantGenerator(options);
103+
const newState = options.generateMutations
104+
? createMutant(mergedState)
105+
: mergedState;
106+
107+
autoMutateInertiaInterceptor(inertia, _this.$store, newState, getMutation);
108+
}
109+
}
110+
111+
/**
112+
* Axios interceptor Generator to automatically call mutations
113+
* and commit changed data. Sets up interceptor
114+
*
115+
* @param {Object} response the vuex response
116+
* @param {Object} store initialized vuex store
117+
* @param {Object} _state raw vuex starting data
118+
* @param {Function} mutator function name generator
119+
* @param {Object} options default options
120+
*
121+
* @return void
122+
*/
123+
const autoMutateInertiaInterceptor = (
124+
response: any,
125+
store: InitializedVuexStore,
126+
_state: VuexModule,
127+
mutator: any,
128+
options: VuexcellentOptions = defaultOptions,
129+
) => {
130+
131+
const logger = options.logger = createLogger(options.logLevel)
132+
133+
if (!response.$vuex) {
134+
logger.debug("[VuexHydrate] no vuex data detected. Skipping auto mutations.")
135+
return response;
136+
}
137+
138+
logger.debug("[VuexHydrate] vuex data detected, attempting to auto-commit")
139+
140+
try {
141+
let $vuex = JSON.parse(response.$vuex);
142+
// grab state & modules, if existing & auto-commit
143+
autoCommitData({ store, _state, mutator }, $vuex, logger);
144+
145+
// user specified mutations
146+
($vuex.mutations || []).forEach(
147+
([mutation, value]: [string, any?]) => store.commit(mutation, value)
148+
);
149+
150+
// user specified actions
151+
($vuex.actions || []).forEach(
152+
([action, value]: [string, any?]) => store.dispatch(action, value)
153+
);
154+
} catch (err) {
155+
logger.error(err);
156+
logger.warning(
157+
`[@pderas/vuex-hydrate-state] An error occurred during the auto commit process.\nYour vuex state may not be what you expected.`
158+
);
159+
}
160+
};

packages/@pderas/state/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"moduleResolution": "node",
88
"target": "ESNext",
99
"lib": ["ESNext", "DOM"],
10-
"noImplicitAny": true,
10+
"noImplicitAny": false,
1111
"removeComments": true,
1212
"preserveConstEnums": true,
1313
"noEmit": false,

0 commit comments

Comments
 (0)