Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vuex API Store als eigenes NPM Package extrahieren #507

Closed
carlobeltrame opened this issue Aug 25, 2020 · 4 comments · Fixed by #616
Closed

Vuex API Store als eigenes NPM Package extrahieren #507

carlobeltrame opened this issue Aug 25, 2020 · 4 comments · Fixed by #616
Assignees
Projects

Comments

@carlobeltrame
Copy link
Member

carlobeltrame commented Aug 25, 2020

Soll mit Nuxt kompatibel sein, damit es im Print-Modul eingesetzt werden kann.

Auf einem ecamp-Account auf NPM veröffentlichen, und hal-json-normalizer auch dorthin verschieben.

Typescript yay or nay?

@carlobeltrame carlobeltrame created this issue from a note in Development (Specified) Aug 25, 2020
@carlobeltrame carlobeltrame self-assigned this Aug 25, 2020
@usu
Copy link
Member

usu commented Nov 7, 2020

Bin kürzlich über folgende Packages gestolpert. Vielleicht kann man da irgend eine gute Idee abkupfern wie man das ganze Modular gestalten kann. Diese Packages verknüpfen ja auch auf die eine oder andere Art vuex mit Api-calls.

Dann hätte ich noch ein paar Wünsche an den Weihnachtsmann. Aber das ist vielleicht eher was für den API Store 2.0 😄
(of course up for discussion)

let camp = api.get('/camps/1') // returns something like an EntityClass
camp.patch({title: "New camp title"}).then(...)
let camps = api.get('/camps') // returns something like a CollectionClass
camp = await camps.post({title: "new camp"})

Und was meinst du zu dem?
Das würde uns die date helpers sparen, welche jetzt mit dem Picasso mitgekommen sind.

let scheduleEntry= api.get('/schedule-entries/1')  // returns a ScheduleEntry class which extends from EntityClass (wie weiss die api, dass sie ein ScheduleEntry retournieren muss? keine Ahnung)
console.log(scheduleEntry.startTime) // startTime ist ein computed property in der ScheduleEntry class

@carlobeltrame
Copy link
Member Author

Cool, danke, ich schau mir die mal an.

Dann hätte ich noch ein paar Wünsche an den Weihnachtsmann. Aber das ist vielleicht eher was für den API Store 2.0 smile
(of course up for discussion)
let camp = api.get('/camps/1') // returns something like an EntityClass
camp.patch({title: "New camp title"}).then(...)

let camps = api.get('/camps') // returns something like a CollectionClass
camp = await camps.post({title: "new camp"})

Ich verstehe nicht ganz, was daran kann der API store jetzt noch nicht? Falls du dir konkrete JS-Klassen Camp und Period etc. wünschst, woher soll der API store denn wissen welche Klasse jetzt rauskommen soll wenn ich this.api.get().lastUsedCamp() aufrufe? Was wir machen könnten wäre: this.api.get().lastUsedCamp(Camp), also quasi die Klasse als Argument übergeben. Oder auch this.api.get().lastUsedCamp().as(Camp) oder Camp(this.api.get().lastUsedCamp()). Das ist dann eigentlich ein Decorator Pattern, und die letzte Variante könnte auch separat vom API-store package gemacht werden.

@usu
Copy link
Member

usu commented Nov 8, 2020

Ich verstehe nicht ganz, was daran kann der API store jetzt noch nicht?
Nix, was der Store heute noch nicht kann. Ich glaube einfach es gibt einfach schöneren und besser organisierten Code, wenn die API-Operationen direkt von den einzelnen Entities ausgelöst werden können.

War ursprünglich mal eine Idee von dir, ich verkauf sie dir nur wieder zurück 😄
Siehe heir: #416 (comment)
und hier: #426

Und das wäre eventuell ein Wegbereiter für den nächsten Punkt:

Falls du dir konkrete JS-Klassen Camp und Period etc. wünschst, woher soll der API store denn wissen welche Klasse jetzt rauskommen soll wenn ich this.api.get().lastUsedCamp() aufrufe?

Selbe Frage hatte ich auch schon oben im Kommentar notiert, keine Ahnung 🙈

Variante 1: Manuell beim Aufruf, so wie von dir vorgeschlagen. Könnte etwas murksig werden mit Relationsships und Collection. Dafür ziemlich unabhängig vom Store.

this.api.get().lastUsedCamp().periods(Period) // ok
this.api.get().lastUsedCamp().periods().as(Period) // hmm...
Period(this.api.get().lastUsedCamp().periods()) // akward

Variante 2: Automatisch über detektieren des Endpoints. Ich kann beim API store registrieren, dass Endpoint '/camps*' immer ein Camp liefern sollte. Sehr unschön. Genau das wollen wir ja vermeiden, routen im Frontend zu hardcoden.

Variante 3: API liefert für jedes Objekt eine property mit, welche die (backend) Entity-Klasse beschreibt, welche im Frontend wiederum in eine Frontend-Entity-Klasse übersetzt werden kann.

@usu
Copy link
Member

usu commented Nov 8, 2020

Habe gestern noch kurz mit vuex-orm und dem axios plugin herumgespielt. Und weils mehr Spass macht an echtem Code auszuprobieren anstatt konstruierte Beispiel mal in ecamp3 hineingekippt.

What I like:

Als Inpsiration für den API store.

Globale config für Axios

Ich kann axios global konfigurieren (baseURL). Ich hätte spontan gedacht, dass ich so auch eine andere Axios-Implementation unterjubeln kann (e.g. Nuxt), aber das scheint irgendwie anders zu funktionieren.
devel...usu:feature/vuex-orm#diff-e35af4cfa452e92e507a0317de89acd8c9e449406e1dd721076d6903525e3e41R17

dataTransformer

Das Plugin kennt eine config dataTransformer, welche entweder pro Model oder pro Request konfiguriert werden kann.
devel...usu:feature/vuex-orm#diff-b622d6137b16ead2f138f8f9512017a7ad75d5afcdd45f590a0c2dedd2042157R18

Das Konzept könnte man nutzen, um Daten beim empfangen bereits zu verarbeiten, bevor diese in den Store gelangen (z.B. Datums-format umrechnen, wenn man das möchte). Das könnte man dann als Hook ausbauen beim Empfangen und Senden, z.b. transformReceivingData und transformSendingData (oder eher im Hook style beforeStoring und beforeSending) . Pro Model/Entity natürlich.

In meinem Beispiel musste ich den dataTransformer nutzen um den HAL-Response zu verarbeiten. Das wäre bei uns natürlich nicht notwendig, da unser API Store ja HAL von Haus aus versteht. Allerdings (crazy idea) könnte man in einem zweitem Schritt vielleicht auch diese Funktion überschreibbar machen. Dann würde der API Store auch nutzbar, wenn jemand HAL leicht anders implementiert. Oder (crazy idea) der Store wäre auch für komplett andere HATEOS Protokolle nutzbar, wie z.B. JSON:API. vuex-hal wird zu vuex-hateoas 😄

Zusätzliche Getters/setters pro Entity

Wie oben schon beschrieben/diskutiert.
devel...usu:feature/vuex-orm#diff-b622d6137b16ead2f138f8f9512017a7ad75d5afcdd45f590a0c2dedd2042157R30

isDirty

Die haben ein extra Plugin um mit Dirty-Daten umzugehen (https://github.com/vuex-orm/plugin-change-flags). Ich hab das nicht im Detail angeschaut, aber hat mich auf folgende Idee gebracht (vielleicht für API Store 3.0): Heute werden die Daten im Store nur aktualisiert, wenn von der API neue Daten kommen. Dirty handling gibt es nur im ApiWrapper. Was wenn wir den Store auch enablen das zu tun? Natürlich optional nebst dem direkten patchen.

let scheduleEntry = api.get('/schedule-entries/1')
scheduleEntry.change({periodOffset: 500}) // Neuer Offset ist bereits im Store gespeichert und für alle Komponenten sichtbar. ScheuldeEntry ist Dirty.
scheduleEntry.persist() // Alle Änderungen werden zur API gesendet, inkl. Verarbeitung der Response (z.b. Zurücksetzen der Daten bei eine Fehlermeldung, etc.)

Das könnte das Frontend responsiver machen, weil ich nicht immer auf die API-Response warten muss, um eine Änderung anzuzeigen. Der API Wrapper kann das lokal für seinen Einzelwert, aber für komplexere Cases (z.B. Picasso) kann das schwierig werden. Beim eager deletion gehen wir ja fast schon etwas in diese Richtung.

What I dislike:

Halt der ganze Rest
Daten müssen manuell geladen werden und dann noch mit Queries zusammen gesetzt werden. Aber ist ja auch nur ein ORM und kein HAL API store 😄

@carlobeltrame carlobeltrame moved this from Specified to In progress in Development Nov 8, 2020
@carlobeltrame carlobeltrame moved this from In progress (assigned) to Pull-Request in Development Nov 11, 2020
Development automation moved this from Pull-Request to Done Nov 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Development
  
Done
Development

Successfully merging a pull request may close this issue.

2 participants