Giter Site home page Giter Site logo

openapi-jaxrs-client's People

Contributors

dependabot[bot] avatar jskov avatar jskov-jyskebank-dk avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

openapi-jaxrs-client's Issues

Responses without types fail with NPE

Nexus API has two entries returning 200 with no type definintion. This causes a NPE.

  /v1/iq:
    get:
      tags:
      - "Manage IQ server configuration"
      summary: "Get IQ server configuration"
      description: ""
      operationId: "getConfiguration"
      consumes:
      - "application/json"
      produces:
      - "application/json"
      parameters: []
      responses:
        "200":
          description: "IQ server configuration returned"

Add Gradle DSL to allow for changing generated files

Add something like (for Api and Dto):

postProcessApi(Function<String, String>)
postProcessApi(Pattern, Function<String, String>)

To allow simple hacks such has:

postProcessApi(s -> s.replace("@HeaderParam(\"Authorization\") String auth", "@HeaderParam(\"Authorization\") String auth, @HeaderParam(\"x-api-key\") String xApiKey")

Inheritance does not include extends in generated model when properties is nested inside allOf

I am experiencing issues when generating DTO models from a spec with properties nested inside the allOf tag for models with inhertiance. If I move properties and tags other than " $ref" outside the allOf tag it seems to work.
Concretely extends is missing on model with nested properties in allOf, but present as it should be when properties is moved outside of allOf tag.
This exact combination is used in Swaggers own example for inheritance in their documentation, so I think this should be supported? https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/

I have included the snippet for the models with inheritance below (file upload did not seem to work properly?)
SMSMailIdentification has the problem (original spec)
VirkPersonIdentification works as it should (identation modified)

VirkPersonIdentification:
  allOf:
    - $ref: '#/components/schemas/Identification'
  properties:
    virkUnitNumber:
      description: 'DA: Virk.dk person id<br/>The id for a person at virk.dk'
      type: string
  description: 'DA: Virk.dk registreret person-id. <br/>Virk.dk registered personId'
  type: object
SMSMailIdentification:
  allOf:
    - $ref: '#/components/schemas/Identification'
    - type: object
      properties:
        countryCode:
          description: 'DA: Landekode for telefonnummeret<br/>The country code of
            the phone number'
          example: +45
          type: string
        phoneNumber:
          description: 'DA: Telefonnummer til brug ved SMS login<br/>The phone number
            to use for SMS login. Maximum of 30 digits excluding spaces allowed.'
          example: 12345678
          maxLength: 40
          type: string
      description: 'DA: SMS og mail identifikation<br/>SMS and mail identification'
IdentificationType:
  enum:
    - VIRK_PERSON
    - SMS_MAIL
  type: string
Identification:
  required:
    - type
  properties:
    type:
      $ref: '#/components/schemas/IdentificationType'
    locked:
      default: false
      description: If identification is protected by a secret, this field is true.<br>When
        true the following operations can only be done when the known secret is
        supplied in header x-locked-secret.<ul><li>PATCH of contact with a different
        identification type than already set.</li></ul>
      readOnly: true
      type: boolean
    loginId:
      description: 'DA: Login id<br/>Login id, from the security token.'
      readOnly: true
      type: string
  description: '
    <b>NOTE: Discriminator mapping is not shown in Swagger UI (as of september 2023). 
    Read the .yaml spec file directly for the discriminator mapping or use an alternative UI, for example Redoc.</b>
    <br/><br/>
    The identification of the contact. Can only be changed when identification.loginId
    is not set.
    '
  discriminator:
    mapping:
      VIRK_PERSON: '#/components/schemas/VirkPersonIdentification'
      SMS_MAIL: '#/components/schemas/SMSMailIdentification'
    propertyName: type
  oneOf:
    - $ref: '#/components/schemas/VirkPersonIdentification'
    - $ref: '#/components/schemas/SMSMailIdentification'
  nullable: true
  type: object

Do not require generator-api-package when api skipped

With generator-api-skip = true

I get:

Caused by: java.lang.IllegalArgumentException: The property generator-api-package must be specified!
        at dk.mada.jaxrs.generator.GeneratorOpts.getRequired(GeneratorOpts.java:392)
        at dk.mada.jaxrs.generator.GeneratorOpts.apiPackage(GeneratorOpts.java:97)
        at dk.mada.jaxrs.generator.GeneratorOpts.apiPackageDir(GeneratorOpts.java:102)
        at dk.mada.jaxrs.Generator.generateClient(Generator.java:64)
        ... 33 more

Add @MultipartForm handling of multipart form parameters

Current generator will make from:

    post:
      tags:
      - templates
      requestBody:
        content:
          multipart/form-data:
            schema:
              required:
              - template-jar
              - jar-size
              type: object
              properties:
                metadata:
                  $ref: '#/components/schemas/TemplateDTO'
                template-jar:
                  format: binary
                  type: string
                jar-size:
                  format: int64
                  type: integer
      responses:
        "201":
          description: Created
        "401":
          description: Not Authorized
        "403":
          description: Not Allowed

This API call:

void templatesPost(@HeaderParam("Authorization") String auth, @Valid  @FormParam("metadata") TemplateDTO metadata, @FormParam("template-jar") byte[] templateJar,  @FormParam("jar-size") long jarSize, Object dto);

But what is needed is more like this:

  void templatesPost(@HeaderParam("Authorization") String auth, @MultipartForm CreateMultiPartBody dto);

And a companion builder for:

	public static class CreateMultiPartBody {

		@FormParam("metadata")
		@PartType(MediaType.APPLICATION_JSON)
		@NotNull
		@Valid
		public final TemplateDTO dto;
		
		@FormParam("template-jar")
		@PartType(MediaType.APPLICATION_OCTET_STREAM)
		@NotNull
		public final InputStream templateJar;
		
		@NotNull
		@FormParam("jar-size")
		@PartType(MediaType.APPLICATION_JSON)
		public final long jarSize;
		
		public CreateMultiPartBody(TemplateDTO dto, InputStream templateJar, long jarSize) {
			this.dto = dto;
			this.templateJar = templateJar;
			this.jarSize = jarSize;
		}

		@Override
		public String toString() {
			return "CreateMultiPartBody [metadata=" + dto + ", template-jar=" + templateJar + ", jar-size=" + jarSize + "]";
		}
	}

Otherwise the Quarkus REST client will balk (see quarkusio/quarkus#12286).

Not sure if this is a workaround, or just the "Right Way(tm)". Seems that this is outside the spec, and what resteasy provides.

Fix actions warnings

Annotations
4 warnings
Build
Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: actions/checkout@v2, actions/cache@v1. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/.
Build
The save-state command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
Build
The save-state command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
Build
The set-output command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/

Render failure when 200 has no response type

This 200 response without data type:

  /api/aktiviteter:
    get:
      responses:
        "200":
          description: OK

Results in failure:

Caused by: java.lang.NullPointerException: null at: baseType
        at io.jstach.jstachio.formatters.DefaultFormatter.format(DefaultFormatter.java:50)
        at dk.mada.jaxrs.generator.api.tmpl.CtxApiRenderer.render(CtxApiRenderer.java:745)
        at dk.mada.jaxrs.generator.api.tmpl.CtxApiRenderer.execute(CtxApiRenderer.java:94)
        at dk.mada.jaxrs.generator.api.tmpl.CtxApiRenderer.execute(CtxApiRenderer.java:85)
        at dk.mada.jaxrs.generator.api.tmpl.CtxApiRenderer.process(CtxApiRenderer.java:161)

It should instead fail in parsing, and suggest use of option: parser-fixup-void-200-to-204

Option to include swagger basePath in all API @Paths

For example:

swagger: "2.0"
info:
  version: "3.38.0-01"
  title: "Nexus Repository Manager REST API"
basePath: "/service/rest/"
...
  /v1/components/{id}:
    post:

Spent some time not understading why the post did not work at /v1/components instead of /service/rest/v1/components

Support http response 425 and ref support (timestamp definition)

DTO generation fails with dk.mada.jaxrs:openapi-jaxrs-client:0.9.20

Cause of error is the presence of a "http response 425"

Caused by: java.lang.IllegalArgumentException: Unknown HTTP status code: '425'

    at dk.mada.jaxrs.model.api.StatusCode.of(StatusCode.java:136)

If you remove the http 425 it will parse the yaml without errors

`responses:
200:
description: Validerer at kro sagen er klar til dannelse af beslutningsgrundlaget
content:
application/json:
schema:
$ref: '#/components/schemas/klarTilBeslutningsGrundlagResponse'

    409:
      $ref: '#/components/responses/409'
    425:
      description: >-
        Indikerer at sagen endnu ikke er klar til beslutning.
        Se fejlmeddelse for detaljer.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/errorMessage'
    400:
      $ref: '#/components/responses/400'
    401:
      $ref: '#/components/responses/401'`

Another issue is parsing timestamp definitions that uses ref

It will be generated as
private <UNKNOWN> senestOpdat;

Which wont compile. It should propably have been type String instead of UNKNOWN

  klarTilBeslutningsGrundlagResponse:
      type: object
      required:
        - senestOpdat
      properties:
        senestOpdat:
          $ref: '#/components/schemas/senest-opdat'

  senest-opdat:
      $ref: '#/components/schemas/bdws-timestamp'

  bdws-timestamp:
      type: string
      example: "2022-02-18-09.18.12.788990"
      pattern: '^(\d{4}-\d{2}-\d{2}-\d{2}.\d{2}.\d{2}.\d{6})$'

Methods replacing null with empty collections causes doublet fields

Today the option generator-use-empty-collections replaced the normal getters with variants that translate null to empty collections.
And add a companion getter with a different name, that allows getting the raw property value (null or otherwise).

This causes problems when serializing (double properties).

The ideal code would be something like this:

@Valid
public List getFoobar() {}

@Valid
@JsonIgnore
public List getFoobarReplacingNullWithEmptyCollection() {}

But we have a lot of existing code expecting the default getter to do the null-for-collection magic.

Maybe add option to make naming the correct way.

And play with ignore-annotations to see if the existing code generation can be made to work (even if simple getter is ignored, the setter causes the field to be exposes double).

Allow Enum deserializer to declare an UNKNOWN value for unknown input

Allow Enum deserializer to declare an UNKNOWN value that all unknown strings will be translated to.

This should maybe be controllable per-type/matcher?

UNKNOWN should not be hardwired, but something that can be specified.

To replace the existing generated code which will explode with IllegalArgumentException.

See enumUnknownDefaultCase option in standard generator

(JB T158-7)

Allow control of default @Produces/@Consumes value

At present, if a method is void, no @produces will be added.

But this will make the MP client (as per spec) use Accept: application/json.

Not all services are happy with this and explode with status 500.

Allow specifying a default to be used for void methods, such as "*/*".
This will allow handling any type (e.g. text error messages).

This should probably be the default (would match what curl asks for).

For symmetry, allow option to control @consumes for types having no body (although I cannot see it making a difference)

(Lynge)

Long regexp naming rule fails to replace with empty string

    @ParameterizedTest
    @CsvSource({
        "JRAftalegrundlagBackendServiceInterfaceContractInterfaceAftalegrundlag20200301AftalegrundlagAftalegrundlag, Aftalegrundlag"
    })
    void regexpExpressionTests(String input, String expected) {
        Naming sut = makeSut("REGEXP/JRAftalegrundlagBackendServiceInterfaceContractInterfaceAftalegrundlag20200301Aftalegrundlag/_/;");
        assertThat(sut.convertTypeName(input))
            .isEqualTo(expected);
    }

The above does replace with _. But cannot replace with // (empty)

(Per)

Handle fields with undeclared (assumed Object) type

bpm motor contains at least one type with fields that have no declared type.

Swagger editor treats these as (plain) Object.

Add option to allow same behavior - but disabled by default.
Fail in parsing if this is seen and the option is disabled.

    AendringElement:
      required:
      - aendring
      type: object
      properties:
        aendring:
          description: Ændring som beskrevet i KRO API
          type: string
        oprindelig:
          description: Oprindelig værdi
        ny:
          description: Ønsket værdi
        valueType:
          description: Værdiens tekniske type (JAVA)
          type: string

Bad string escaping

ContactV2MergePatch:
      properties:
        email:
          description: Email address of the contact. Must comply with regex '^(?=.{1,64}@)[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$'

Ends up as:

  @JsonbProperty(JSON_PROPERTY_EMAIL)
  @Schema(nullable = true, description = "Email address of the contact. Must comply with regex '^(?=.{1,64}@)[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$'", example = "[email protected]")
  private String email;

which results in: Illegal escape character

(Martinsen)

Another lookup regression

If alloflookup is given this rename option, it fails as before:

// TODO: figure out why this breaks the lookup - it should have no effect given the input
naming-rules-type = TYPENAME; \
 REGEXP/.*_//

The test input contains no _, so it is unclear why this should have any effect at all.

Regression of empty objects

aftalepakke has:

"TilknytAftalegrundlagResponse": {
      "type": "object",
      "properties": {}
    },

which with 0.9.22 is referenced as that type - but the DTO is filtered out, because it is just a PlainObject.

Need to add test and handling of this.

Allow control of operation names - even when operationId provided

The ACR API contains some operation ids that are not nice in Java, see https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/containerregistry/data-plane/Microsoft.ContainerRegistry/preview/2019-08-15/containerregistry.json

Maybe allow suppressing operationIds and using the synthetic input instead.

Or better, possibly, two set of naming rules - one applied when operationId is available, the other for the synthetic names.

Add option to allow handling integer (wo format) as int32

Check what is now default behavior in swagger. Used to be int16 if format was missing.

If default is now int32, let mada generator use that as default as well - and add option to select int16/short.

(Lynge, krediterhverv.bpm.proces)

Allow property description with type ref

Currently including a description using the microprofile @Schema annotation with a description parameter changes the openapi spec from simple type ref to use allOf type ref like this

Without Schema annotation:

rolle:
    $ref: '#/components/schemas/RolleBeregnetEnum'

With @Schema(description="Deltagerens rolle i koncernen. F.eks. om deltageren er debitor på koncernens engagement")

rolle:
  description: Deltagerens rolle i koncernen. F.eks. om deltageren er debitor
    på koncernens engagement
  type: string
  allOf:
    - $ref: '#/components/schemas/RolleBeregnetEnum'

The last example should be a valid spec and have the same effect as the first + a property description. However this results in types being of String type rather than the refered type.

BitBucket REST API causes generator explosion

On REST API https://dac-static.atlassian.com/server/bitbucket/8.15.swagger.v3.json?_v=1.466.0

Unclear as yet which part of the API triggers the explosion.

2023-12-05T13:15:59.961+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Caused by: java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.media.Schema.getType()" because "schema" is null       
2023-12-05T13:15:59.961+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.TypeConverter.reference(TypeConverter.java:171)                                                       
2023-12-05T13:15:59.961+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.TypeConverter.toReference(TypeConverter.java:124)                                                     
2023-12-05T13:15:59.961+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.ApiTransformer.toParam(ApiTransformer.java:281)                                
2023-12-05T13:15:59.961+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.ApiTransformer.getParameters(ApiTransformer.java:269)                  
2023-12-05T13:15:59.961+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.ApiTransformer.processOp(ApiTransformer.java:117)                     
2023-12-05T13:15:59.961+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.ApiTransformer.lambda$processPath$0(ApiTransformer.java:107)          
2023-12-05T13:15:59.962+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.ApiTransformer.processPath(ApiTransformer.java:107)               
2023-12-05T13:15:59.962+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.ApiTransformer.transform(ApiTransformer.java:97)                  
2023-12-05T13:15:59.962+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.openapi.Parser.parse(Parser.java:114)                           
2023-12-05T13:15:59.962+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   at dk.mada.jaxrs.generator.mpclient.Generator.generateClient(Generator.java:51)  
2023-12-05T13:15:59.962+0100 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]   ... 33 more                                                                                                                                                                               

Need flag to stop mapping types to Object/String

For example:

    ProjectId:
      type: string

Gets remapped to String.

But:

  • API still tries to import the type
  • may want to use generator-map-external-types to retain type information
  • old code may expect a rendered type and not just Object

(Per/Jesper)

Bad method name when using resource base path

  /project-id/from-clone-url:
    put:
      tags:
      - Project Id Resource
      requestBody:
        content:
          application/json:
            schema:
              type: string
        required: true
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
            text/plain:
              schema:
                type: string

Results in (invalid method name):

@javax.annotation.processing.Generated(value = "dk.mada.jaxrs.Generator")
@Path("/project-id/from-clone-url")
public interface Project_Id_ResourceApi {

  /**
   * project-idFromCloneUrlPut.
   *
   * @param dto  (required)
   * @return String
   */
  @PUT
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
  @APIResponseSchema(String.class)
  String project-idFromCloneUrlPut(@NotNull String dto);
}

Special UUID-type handling broken in some cases

In the below API, the RoomId is handled as a DTO whereas UUID is handled as the java UUID type.

The parser logic handling this takes its cue from OpenApi schema type (UUIDSchema) not the type name.
So it is unclear if this is a OpenApi problem, or mada parser jumping the gun somewhere else.

Check if it is because the pattern is missing (could trigger magic in OpenAPI).

  /api/uuid/query:
    get:
      tags:
      - Resource Dtos
      parameters:
        - in: query
          name: roomId
          schema:
            $ref: '#/components/schemas/RoomId'
...
    UUID:
      format: uuid
      pattern: "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"
      type: string
    RoomId:
      description: UUID of the room.
      example: e017e2ea-ff98-4516-9a56-bbd02e1f161a
      format: uuid
      type: string

(MM)

default-schema response should be mapped to responses without schema

See https://swagger.io/specification/#responses-object

The ACR api declares a 200 response without type (schema), which causes generator to insist on parser-fixup-void-200-to-204.
It should instead use the provided default-schema.

{
  "swagger": "2.0",
  "info": {
    "title": "Azure Container Registry",
    "description": "Metadata API definition for the Azure Container Registry runtime",
    "version": "2019-08-15-preview"
  },
...
  "paths": {
    "/v2/": {
      "get": {
        "tags": [
          "v2"
        ],
        "description": "Tells whether this Docker Registry instance supports Docker Registry HTTP API v2",
        "operationId": "V2Support_Check",
        "x-ms-examples": {
          "Check Docker Registry V2 Support": {
            "$ref": "./examples/GetDockerRegistryV2Support.json"
          }
        },
        "responses": {
          "200": {
            "description": "Successful response. API v2 supported"
          },
          "default": {
            "description": "ACR error response describing why the operation failed.",
            "schema": {
              "$ref": "#/definitions/AcrErrors"
            }
          }
        }
      }
    },

Discriminator mapped subtypes do not extend abstract super

This example (customerRoomV3) renders Identification as abstract, but the three subtypes does not extend it.

    PrivateIdentification:
      allOf:
        - $ref: '#/components/schemas/Identification'
        - properties:
            sevenFirstCprDigits:
              type: string
          type: object
    VirkPersonIdentification:
      allOf:
        - $ref: '#/components/schemas/Identification'
        - properties:
            virkUnitNumber:
              type: string
          type: object
    SMSMailIdentification:
      allOf:
        - $ref: '#/components/schemas/Identification'
        - properties:
            countryCode:
              type: string
          type: object
    IdentificationType:
      enum:
        - PRIVATE
        - VIRK_PERSON
        - SMS_MAIL
      type: string
    Identification:
      required:
        - type
      properties:
        type:
          $ref: '#/components/schemas/IdentificationType'
        locked:
          default: false
          readOnly: true
          type: boolean
        loginId:
          readOnly: true
          type: string
      discriminator:
        mapping:
          PRIVATE: '#/components/schemas/PrivateIdentification'
          VIRK_PERSON: '#/components/schemas/VirkPersonIdentification'
          SMS_MAIL: '#/components/schemas/SMSMailIdentification'
        propertyName: type
      nullable: true
      type: object

(MM)

Multiple produces types failure

(aftalepakke) has endpoint with these:

"consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"]

which ends up getting rendered (badly) as:

  @Consumes(MediaType.APPLICATION_JSON)
  @Produces({"application/xml", "text/json", "text/xml", MediaType.APPLICATION_JSON})
  @APIResponses({
    @APIResponse(responseCode = "200", description = "OK",
                 content = @Content(schema = @Schema(implementation = DTOtype.class), mediaType = {"application/xml", "text/json", "text/xml", MediaType.APPLICATION_JSON})),

Should just be:

  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  @APIResponses({
    @APIResponse(responseCode = "200", description = "OK",
                 content = @Content(schema = @Schema(implementation = DTOtype.class), mediaType = MediaType.APPLICATION_JSON)),

(and most definitely not a list)

That is with preferences:

parser-api-preferred-request-mediatypes = application/json
parser-api-preferred-response-mediatypes = application/json

Remove property order annotations

They contain no spec-related information anyway, so they end up being randomly ordered (parse order).

eclipse/microprofile-open-api#359

also, from the JSON schema spec https://datatracker.ietf.org/doc/html/draft-wright-json-schema-00#section-4.3 :

Implied in this definition is that arrays must be the same length,
objects must have the same number of members, properties in objects
are unordered, there is no way to define multiple properties with the
same key, and mere formatting differences (indentation, placement of
commas, trailing zeros) are insignificant.

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.