Last active
February 25, 2021 00:57
-
-
Save izelnakri/1bef99f6af0a3c14ba996280cd53dd22 to your computer and use it in GitHub Desktop.
Ember-data + Memserver + Ecto(ORM) API unification && Memserver + Express.js API unification
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { from, where, join, leftJoin, innerJoin } from 'memserver/query'; | |
| import { cast, validat cast, validateRequired, validateFormat, validateLength, uniqueConstraint, foreignKeyConstraint } from 'memserver/changeset'; | |
| let userFirstNames = User | |
| |> where('u', 'u.id < 200') // 'm' because there could be multiple model references on |> sql joins() | |
| |> select('u', 'u.first_name') | |
| |> Repo.all | |
| // or maybe some API like this as well: https://apidock.com/rails/ActiveRecord/QueryMethods/where | |
| // or direct memserver like API User.findBy({}); | |
| export default class EmailValidator { | |
| static changeset(oldInstance: Email, paramsToCastValidate: object): Changeset { | |
| return oldInstance | |
| |> cast(paramsToCastValidate, ['address']) | |
| |> validateRequired(['address']) | |
| |> validateFormat('address', /@/) | |
| |> validateLength('address', { min: 3, max: 75 }) | |
| |> uniqueConstraint('address') | |
| |> foreignKeyConstraint('person_id') // some like this one maybe not needed I can express them as decorators in the model def | |
| } | |
| static userRegistrationChangeset(oldInstance: Email, paramsToCastValidate: object): Changeset { | |
| return oldInstance | |
| |> cast(paramsToCastValidate, ['person_id']) | |
| |> changeset(paramsToCastValidate) | |
| |> validateRequired(['person_id']) | |
| |> this.generateConfirmationToken() | |
| } | |
| // ... with static generateConfirmationToken() {} uses cast(changeset, ['confirmation_token'], generatedToken) inside | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import express from 'memserver/express'; | |
| import User from "./models/user"; | |
| const app = express({ mock: !!process.env.MOCK_SERVER }); | |
| app.get("/users", ({ params, query, headers }, res) => { | |
| return res.json({ users: User.serializer(User.findAll()) }); | |
| }); | |
| export default app; | |
| // so exported app can be listened to via another "server-only" file or frontend: app.listen(process.env.HTTP_PORT); | |
| // AREAS TO CONSIDER for rewriting express api: | |
| // ============================================ | |
| // 1 - noop-ing express-specific middleware or other code | |
| // 2 - openapi doc generation for express endpoints | |
| // 3 - res.json() vs return $model -> res.json() is necessary for background jobs etc | |
| // 4 - also check nest.js openapi integration | |
| // Then thing re-implementing passthrough(proxy) external link?, namespace, urlPrefix, timing, logging | |
| // OPEAN API GENERATION | |
| // ========================== | |
| // api info name, description | |
| // HTTP TYPE | endpoint string | params, description(md) | |
| // request Types -> response Types header, queryParams, requestBody | |
| // response status codes, response header, response body // description for each type? | |
| // parse the types of queryParam, response keys | |
| // GET /users ? where to description | |
| // all parameter parsing | |
| // response returns |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // MODEL API: | |
| import Model,{ belongsTo, hasMany } from 'memserver/model'; | |
| class User extends Model { | |
| static Adapter: MemoryAdapter, // or SQLAdapter, JSONAPIAdapter, JSONAdapter, GraphQLAdapter | |
| static Serializer: ModelSerializer // or JSONSerializer, JSONAPISerializer, GraphQLSerializer | |
| static primaryKey = 'id' // or uuid or function(?) | |
| // also attribute declaration here as typescript or from ember-data to TS migration | |
| person = belongsTo(); | |
| emails = hasMany(); | |
| static insert(options) { | |
| } | |
| static update(options) { | |
| } | |
| static delete(options) { | |
| } | |
| static serializer(userOrUsers) { | |
| } | |
| static serialize(user) { | |
| } | |
| static resetDatabase(targetInitialState: object[]) { | |
| } | |
| // Model Query Interface: | |
| static find(idOrIds) { | |
| } | |
| static findBy(options) { | |
| } | |
| static findAll(options) { | |
| } | |
| static count(options) { // in memory, or in the resource through adapter with options? | |
| } | |
| // Extra examples: customAPIActions: | |
| static confirm = APIAction({ | |
| type: 'POST', | |
| path: 'confirmation.microservice.com/user/confirm', | |
| before() { | |
| }, | |
| after() { | |
| } | |
| }) | |
| // private API: attributes, DB, defaultAttributes(string or lazy(with functions)) in future maybe as prop or decorator etc | |
| // maybe default App or DB validations expressed as decorators | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment