diff --git a/README.md b/README.md
index e78d0f5d..e0da28ef 100644
--- a/README.md
+++ b/README.md
@@ -102,6 +102,8 @@ let someEntity = this.$api.get('/some/endpoint')
...
```
+**Known limitations:** The current implementation has so far only be tested to generate static HTML on server side (nuxt config `injectScripts` set to `false`) without client side SPA. Serialization of Vuex store data & hydration on client side will probably not work without errors.
+
# Available options
### apiName
diff --git a/src/LoadingStoreValue.ts b/src/LoadingStoreValue.ts
index 9a1cda8a..6992f6be 100644
--- a/src/LoadingStoreValue.ts
+++ b/src/LoadingStoreValue.ts
@@ -48,7 +48,7 @@ class LoadingStoreValue implements Resource {
// This is necessary so that Vue's reactivity system understands to treat this LoadingStoreValue
// like a normal object.
- if (['then', 'toJSON', Symbol.toStringTag, 'state', 'getters', '$options', '_isVue', '__file', 'render', 'constructor'].includes(prop as string)) {
+ if (['then', Symbol.toStringTag, 'state', 'getters', '$options', '_isVue', '__file', 'render', 'constructor'].includes(prop as string)) {
return undefined
}
@@ -99,6 +99,10 @@ class LoadingStoreValue implements Resource {
public $href (relation: string, templateParams = {}): Promise {
return this._meta.load.then(resource => resource.$href(relation, templateParams))
}
+
+ public toJSON (): string {
+ return '{}'
+ }
}
export default LoadingStoreValue
diff --git a/src/StoreValue.ts b/src/StoreValue.ts
index 6517b635..4d555610 100644
--- a/src/StoreValue.ts
+++ b/src/StoreValue.ts
@@ -97,6 +97,16 @@ class StoreValue implements Resource {
$href (relation: string, templateParams = {}): Promise {
return this.apiActions.href(this, relation, templateParams)
}
+
+ /**
+ * Serialize object to JSON
+ * this avoid warnings in Nuxt "Cannot stringify arbitrary non-POJOs"
+ */
+ toJSON (): string {
+ // for the lack of any better alternative, return store data as JSON
+ // alternatively: could also return '{}', as the data cannot be used directly, anyway
+ return JSON.stringify(this._storeData)
+ }
}
export default StoreValue
diff --git a/src/index.ts b/src/index.ts
index e2b13237..c9254417 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -10,7 +10,7 @@ import { ExternalConfig } from './interfaces/Config'
import { Store } from 'vuex/types'
import { AxiosInstance, AxiosError } from 'axios'
import Resource from './interfaces/Resource'
-import StoreData, { Link } from './interfaces/StoreData'
+import StoreData, { Link, SerializablePromise } from './interfaces/StoreData'
import ApiActions from './interfaces/ApiActions'
import EmbeddedCollectionClass from './EmbeddedCollection'
import EmbeddedCollection, { EmbeddedCollectionMeta } from './interfaces/EmbeddedCollection'
@@ -407,7 +407,9 @@ function HalJsonVuex (store: Store>, axios: AxiosInstance,
* @param loadStoreData
*/
function setLoadPromiseOnStore (uri: string, loadStoreData: Promise | null = null) {
- store.state[opts.apiName][uri]._meta.load = loadStoreData || Promise.resolve(store.state[opts.apiName][uri])
+ const promise: SerializablePromise = loadStoreData || Promise.resolve(store.state[opts.apiName][uri])
+ promise.toJSON = () => '{}' // avoid warning in Nuxt when serializing the complete Vuex store ("Cannot stringify arbitrary non-POJOs Promise")
+ store.state[opts.apiName][uri]._meta.load = promise
}
/**
diff --git a/src/interfaces/StoreData.ts b/src/interfaces/StoreData.ts
index 630adc36..d9f39916 100644
--- a/src/interfaces/StoreData.ts
+++ b/src/interfaces/StoreData.ts
@@ -6,6 +6,10 @@ type TemplatedLink = Link & {
templated: string
}
+type SerializablePromise = Promise & {
+ toJSON?: () => string
+}
+
type StoreDataMeta = {
_meta: {
self: string
@@ -18,19 +22,19 @@ type StoreDataMeta = {
type StoreDataEntity = StoreDataMeta & {
items: never,
_meta: {
- load: Promise
+ load: SerializablePromise
}
}
type StoreDataCollection = StoreDataMeta & {
items: Array,
_meta: {
- load: Promise
+ load: SerializablePromise
}
}
type StoreData = StoreDataEntity | StoreDataCollection
-export { StoreData, Link, TemplatedLink, StoreDataEntity, StoreDataCollection }
+export { StoreData, Link, TemplatedLink, StoreDataEntity, StoreDataCollection, SerializablePromise }
export default StoreData
diff --git a/tests/store.spec.js b/tests/store.spec.js
index 1537e20d..ef72ef3a 100644
--- a/tests/store.spec.js
+++ b/tests/store.spec.js
@@ -18,6 +18,9 @@ import multipleReferencesToUser from './resources/multiple-references-to-user'
import templatedLink from './resources/templated-link'
import root from './resources/root'
+import LoadingStoreValue from '../src/LoadingStoreValue'
+import StoreValue from '../src/StoreValue'
+
async function letNetworkRequestFinish () {
await new Promise(resolve => {
setTimeout(() => resolve())
@@ -70,6 +73,24 @@ describe('API store', () => {
expect(vm.$store.state.api).toMatchObject(root.storeState)
})
+ it('can serialize StoreValue object', async done => {
+ // given
+ axiosMock.onGet('http://localhost/').reply(200, root.serverResponse)
+
+ // when
+ const loadingObject = vm.api.get()
+
+ // then (loading)
+ expect(loadingObject).toBeInstanceOf(LoadingStoreValue)
+ expect(loadingObject.toJSON()).toEqual('{}')
+
+ // then (loaded)
+ const loadedObject = await loadingObject._meta.load
+ expect(loadedObject).toBeInstanceOf(StoreValue)
+ expect(loadedObject.toJSON()).toEqual('{"this":"is","the":"root","_meta":{"self":"","loading":false,"reloading":false,"load":"{}"}}')
+ done()
+ })
+
it('imports embedded single entity', async () => {
// given
axiosMock.onGet('http://localhost/camps/1').reply(200, embeddedSingleEntity.serverResponse)