Code Monkey home page Code Monkey logo

mesh-model-generator's Introduction

Generator to render model interfaces from Gentics Mesh RAML

npm version

NOTE

This package is work in progress and not ready for production use. It requires Gentics Mesh 0.8.x+

Render the server interfaces returned by Mesh as type definitions which can be used in TypeScript. Designed for use with TypeScript, but can be extended for other languages.

Usage as a module

npm install mesh-model-generator
import { readFileSync, writeFileSync } from 'fs';
import { parseAndGenerate } from 'mesh-model-generator';

const inputFile = readFileSync('./my-api.raml', 'utf-8');
parseAndGenerate(inputFile)
    .then(generatedModels => {
        writeFileSync('./my-models.ts', generatedModels, 'utf-8');
    })
    .catch(err => console.error(err));

Generating from the CLI

npm install -g mesh-model-generator
mesh-model-generator my-api.raml > model-declarations.ts

License

MIT

mesh-model-generator's People

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

watheia

mesh-model-generator's Issues

Generator output is broken with 0.9.10

With mesh 0.9.10, the RAML declarations contain JSON models from Vertex, with an ID of urn:jsonschema:io:vertx:core:json:JsonObject. The ID gets output directly in TypeScript instead of being trimmed to JsonObject.

Cause: generateModelName assumes a prefix of urn:jsonschema:com, vertex uses urn:jsonschema:io

Parser & Renderer: Support `multipart/form-data` requests

The endpoint POST /{project}/nodes/{nodeUuid}/binary/{fieldName} accepts a multipart/form-data request body.

Example RAML:

post:
    description: Update the binaryfield with the given name.
    body: 
        multipart/form-data: 
            formParameters: 
                binary: 
                    description: Single binary file part.
                    type: file
                    required: true
                    repeat: false
                language: 
                    description: Language of the node content which contains the binary field which should be updated.
                    type: string
                    required: true
                    repeat: false
                    example: en
                version: 
                    description: Version of the node which should be updated. This information is used to determine conflicting updates.
                    type: string
                    required: true
                    repeat: false
                    example: "1.0"

Could be rendered as:

'/{project}/nodes/{nodeUuid}/binary/{fieldName}': {
    request: {
        ...
        body: {
            /** Single binary file part. */
            binary: File;
            /**
             * Language of the node content which contains the binary field which should be updated.
             * @example "en"
             */
            language: string;
            /**
             * Version of the node which should be updated. This information is used to determine
             * conflicting updates.
             * @example "1.0"
             */
            version: string;
        }
    };
    ...
};

TypeScriptRenderer: All number parameters default to "NaN"

Example RAML:

queryParameters: 
    cropx: 
        description: Set image crop area start x coordinate.
        type: number
        required: false
        repeat: false
        example: "260"

is rendered as:

queryParams?: {
    /**
        * Set image crop area start x coordinate (default: NaN).
        * @example 260
        */
    cropx?: number;

Expected:
No (default: ...) text is output

TypescriptModelRenderer: Multiple examples are rendered as one long string

Only happens for /roles/{roleUuid}/permissions/{pathToElement} (GET, POST).

Input RAML:

uriParameters: 
    pathToElement: 
        displayName: pathToElement
        description: API path to the element.
        type: string
        required: true
        repeat: false
        example: |
            projects/9b492ae687974f06892ae687978f060c
            projects/93494c1ff87d44f4894c1ff87da4f406/nodes/6f3ffb36e1324750bffb36e13277508a

Expected:

urlParams: {
    /**
     * API path to the element.
     * @example
     *   "projects/650444b34688442c8444b34688742c05"
     *   "projects/b646913e642442d186913e6424f2d182/nodes/8e90debc1934482c90debc1934982cdd"
     */
    pathToElement: string;
};

Actual:

urlParams: {
    /**
     * API path to the element.
     * @example "projects/650444b34688442c8444b34688742c05\nprojects/b646913e642442d186913e6424f2d182/nodes/8e90debc1934482c90debc1934982cdd\n"
     */
    pathToElement: string;
};

TypeScriptModelRenderer: URLs should be sorted

Output should be deterministic when checked into a VCS.

Current output (example):

/*
 * Returned for:
 *     POST /roles/{roleUuid}/permissions/{pathToElement}
 *     POST /schemas/{schemaUuid}/changes
 *     POST /microschemas/{microschemaUuid}/changes
 *     GET /search/createMappings
 *     GET /search/reindex
 *     GET /search/status
 *     GET /auth/logout
 *     POST /{project}/nodes/{nodeUuid}
 *     GET /{project}/releases/{releaseUuid}/migrateSchemas
 */
export interface TestModel { ...

should be:

/*
 * Returned for:
 *     GET /auth/logout
 *     GET /search/createMappings
 *     GET /search/reindex
 *     GET /search/status
 *     GET /{project}/releases/{releaseUuid}/migrateSchemas
 *     POST /microschemas/{microschemaUuid}/changes
 *     POST /roles/{roleUuid}/permissions/{pathToElement}
 *     POST /schemas/{schemaUuid}/changes
 *     POST /{project}/nodes/{nodeUuid}
 */
export interface TestModel { ...

FieldMap provides wrong JsonSchema in RAML

FieldMap is a "hash with any value type" model - { [k: string]: any } in TypeScript.
The RAML wrongly returns a type that has a single boolean empty property.

"fields": {
    "type": "object",
    "id": "urn:jsonschema:com:gentics:mesh:core:rest:node:FieldMap",
    "required": true,
    "description": "Dynamic map with fields of the node language specific content.",
    "properties": {
        "empty": {
            "type": "boolean"
        }
    }
}

This produces an incorrect TypeScript model:

export interface FieldMap {
    empty: boolean;
}

GenericResponse is correctly typed in the RAML, FieldMap needs to have a similar JsonSchema:

"fields": {
    "type": "object",
    "id": "urn:jsonschema:com:gentics:mesh:core:rest:node:FieldMap",
    "required": true,
    "description": "Dynamic map with fields of the node language specific content.",
    "additionalProperties": {
        "type": "any"
    }
}

This would produce the correct TypeScript model:

export interface FieldMap {
    [key: string]: any;
}

In a UserResponse rolePerms is optional, but required in all other response models.

See https://github.com/gentics/mesh-ui/blob/f3880d4c045d573c40a229ee0e14b0b96f415efe/src/app/common/models/server-models.ts#L4288

In fact, I think rolePerms should always be optional, since it depends on the role query parameter. I'm not sure if the error there lies with the Raml or with the model generator.

On a related theme, the editor property of the UserResponse is also optional, whereas all other response models have it as required. I have created this Jira ticket after discussing the editor thing with Johannes: https://jira.gentics.com/browse/CL-605

Fix response model for 204 responses

Example endpoint DELETE /{project}/nodes/{nodeUuid}/published

RAML:

delete: 
    description: Unpublish the given node.
    queryParameters: 
        recursive: 
            description: Specifiy whether the invoked action should be applied recursively.
            type: boolean
            required: false
            repeat: false
            default: "false"
            example: "true"
    responses: 
        "204": 
            description: Node was unpublished.

Current output:

responseType: any; // TODO: This is not typed in the RAML
responseTypes: {
    200: any; // TODO: This is not typed in the RAML
};

Expected output:

responseType: undefined;
responseTypes: {
    /** Node was unpublished. */
    204: undefined;
};

TypescriptModelRenderer: Asterisks in descriptions break output

Added with 0.9.10, the output breaks due to special characters in descriptions:

Example for GET /{projectName}/nodes:

description: Read all nodes and return a paged list response.
queryParameters: 
    role: 
        description: |
            The role permission parameter can be used to set the role parameter value in form of an UUID which will cause mesh to add the rolePerm field to the rest response.
            This may be useful when you are logged in as admin but you want to retrieve the editor role permissions on a given node.
            When used, the response will include the *rolePerms* property which lists the permissions for the specified role.
            Endpoint: */api/v1/:projectName/nodes?role=:roleUuid*
        type: string
        required: false
        repeat: false
        example: "24cf92691c7641158f92691c76c115ef"

TypeScript output:

interface SomeRequestType {
    queryParams?: {
        /**
         * The role permission parameter can be used to set the role parameter value in form of an UUID which will cause mesh to add the rolePerm field to the rest response.
         * This may be useful when you are logged in as admin but you want to retrieve the editor role permissions on a given node.
         * When used, the response will include the *rolePerms* property which lists the permissions for the specified role.
         * Endpoint: */api/v1/:projectName/nodes?role=:roleUuid*
         */
        role?: string;
    };
}

The */ ends the doc comment and breaks the TypeScript output.

MeshRamlParser: nested routes miss uriParameters of parent route

When we have nested routes, e.g. "/{project}" and "/{project}/microschemas", the latter misses the uriParameters of the parent (project in the example).

Current:

        '/{project}/microschemas': {
            request: {
                urlParams?: undefined;
                // ...
            };
            // ...
        }

Expected:

        '/{project}/microschemas': {
            request: {
                urlParams: {
                    /**
                     * Name of the project.
                     * @example "demo"
                     */
                    project: string;
                }
                // ...
            };
            // ...
        }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.