Cryrivers / manta-style

🚀 The futuristic API Mock Server for Frontend

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

RFC: Rethink Annotations

Cryrivers opened this issue · comments

tl;dr: this probably a Milestone for 2.0, for 1.0 we will still keep the current mechanism and specification, but re-design the API to be forward-compatible.

This issue is about normalizing JSDoc annotation and powerful Handlebars annotation. And we aim to achieve following goals:

  • Parse and execute Handlebar annotation under the hood, convert JSDoc annotation into handlebars annotation. For example:
/**
 * @iterate hello
 * @iterate world
 * @example a
 * @example b
 */

converts to (in practice, AnnotationNode would be constructed directly, without involving handlebars conversion):

/**
 * @mantastyle
 * {{iterate 'hello' 'world'}}
 * {{example 'a' 'b'}}
 */
  • Other than JSDoc, users can opt-in undocumented and powerful handlebars annotation by having @mantastyle in their comment. So a parsed annotation always starts with AnnotationNode[]

This could also unify JSDoc annotation and handlebar annotation, and also make previous annotationUtils compatible with new implementation.

  • Re-implement annotation generation logic by evaluating Handlebars under-the-hood, and the evaluation can be either lazy or eager as well. Subgoals would be:
    • Change signature of mock plugins from Annotation[] => any to AnnotationExpression => AnnotationNode.
    • Evaluation is lazy by default, (there should be a way to eagerly evaluate sub-expressions)
    • The evaluation order should respect to the evaluation order of type nodes. For example:
/**
* @mantastyle
* {{faker 'internet.UserName'}}
* {{length (range min=5 max=10)}}
*/
type Test = string[];

As deriveLiteral in ArrayType runs first, then in StringType. So {{length}} runs first, then {{faker}} (probably runs multiple times depending on {{length}}, accordingly.

  • Build in some annotation plugins by default
    • {{key [string]}} to manipulate keys of object
    • {{length [number]}} to manipulate length of array
    • {{range min= max= precision=}} to generate a random number given range
  1. what happens with
/**
 * @iterate hello
 * @iterate world
 * @example a
 * @example b
 * @mantastyle {{ xxx }}
 */

there's 3 different annotation, and they are conflicting with each other, what should be the mock data?

  1. Since we are talking about rethink the annotation system, how does the {{length [number]}} works? how does it make the array to have length [number] ? the only think i can think of now is to return array metadata, back to the ArrayType.

😂yeah, this issue looks very challenging to me. i've been creating and remove branches for several times...

  1. i think it would be translated to
{{iterate 'hello' 'world'}} {{example 'a' 'b'}} {{xxx}}

latter takes precedence over former expression (with respect to type evaluation order)

  1. this is the tricky part, i was thinking we can have plugin callback for deriveLiteral to generate some metadata. the type of it is different from type to type. For example, metadata has length if it is deriveLiteral in ArrayType, etc.

or to simplify the problem and API, we can just return metadata in ArrayType callback. as the element type has its own plugin to run.

So in this contrived example, iterate would never be called, because example is having the same behaviour (provide mock data), and having a higher precedence than iterate?

i think so, as for iterate and example, i wouldn't expect to use them like this.

we can print out a warning message actually

if we are going to give error, how are we going to detect this?

to check if 2 plugins apply to the same time. For example, iterate and example both apply to StringType, so not both can work. (consider non-composable case, in JSDoc syntax)