jhipster / generator-jhipster

JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.
https://www.jhipster.tech
Apache License 2.0
21.47k stars 4.02k forks source link

Enriching the JDL grammar #6275

Closed agoncal closed 7 years ago

agoncal commented 7 years ago
Overview of the issue

The idea of this ticket is to brainstorm about a possible enrichment of the JDL grammar.

Motivation for or Use Case

ATM the JDL syntax is mostly used to describe all the entities and their relationships. Having a richer JDL would give many extra code generation possibilities (repositories, services...). On the other hand, it would be the start of having JDL and CLI shifting apart : the CLI can't ask hundreds of questions to be as rich as the JDL.

So if we agree that CLI can't support 100% of JDL, what new features could we have in the JDL ? Let me start with a few ideas, you can then give some feedback and also give your new ideas.

Entity

Entities are already pretty rich, but we can go further.

Versionning

In some cases it's useful to have @Version for optimistic locking. We could use the with keyword :

entity MyEntity with version {
  myField String required,
  mySecondField String
}

Adding with version would generate a @Version attribute in the entity :

@Entity
public class MyEntity implements Serializable {
  // ...
  @Version
  private Long version;
}

Auditing

JHipster already has an AbstractAuditingEntity allowing auditing on entities. It would just be a matter of having a new with audit keyword :

entity MyEntity with audit {
  myField String required,
  mySecondField String
}

The with audit would generate the following code (and of course, the Liquibase changelog) :

@Entity
public class MyEntity extends AbstractAuditingEntity implements Serializable
  // ...
}

Uniqueness

Today we have several validations on our attributes (required, minlength, maxlength, pattern). We could have unique.

entity MyEntity {
  myCode String unique,
  myField String required,
  mySecondField String
}

This would generate a @Column(unique = true) as well as a Liquibase constraint :

  <addUniqueConstraint columnNames="code"
  tableName="mytable"
  constraintName="my_unique_code"/>

List of datatypes

It's sometimes useful to map a list of datatypes (String, Integer...). We could introduce the List<> syntax, such as :

entity MyEntity {
  myCodes List<String>,
  myFields List<Integer>
}

Embeddable

Embeddables are important mapping objects. We should be able to declare them and embed them on entities (lists of embeddables are also possible) :

embeddable Address {
  street String,
  city String
}

entity MyEntity {
  myAdress Address,
  myDeliveryAddresses List<Address>
}

Repositories

Today there is no JDL for repositories. This could be quite useful to add extra query methods. When we have a Customer entity, we automatically generate an empty Customer repository. With the new repository JDL keyword, we could add extra queries :

repository Customer {
  List<Customer> findAllByDateAfter(Instant after),
  Optional<Customer> findOneByEmail(String email),
  Customer findOneWithByCode(Long code) with entityGraph(attributePaths = "customers")
}

And off-course, have these query methods generated in the service and REST controller too.

Services

Services are where we find the business code, so it's difficult to generate a lot of code. One thing could be extending from a custom service (therefore adding the extends keyword). For example :

service A with serviceClass, extends MyOwnService

Of course, depending on what does MyOwnService some tests might break.

REST Controllers

Again, REST resources can handle complex code, so I don't see a lot of customization here. Extending from another resource maybe (not sure it's really useful) ?

rest A extend MyOwnResource

A bunch of variables

Today we can set the JHI_PREFIX in JDL, but it would be good to be able to set others. Just as an example, I find my self always changing the title of website (which is by default the name of the project). This title is mostly in the i18n files ("global": {"title": "myproject")) that I regenerate and need to rechange. Having access to a few variables would solve the problem

JHI_TITLE=My Beautiful Project // which by default is the project name if not set

Your thoughts ?

Related issues
MathieuAA commented 7 years ago

I like your ideas, but some depend on the fact that we generate code some special way. For instance, with version implies that the generated code will "always" (or for a very long time, not susceptible to change) have somewhere @Version on a field. The same remark applies for extends AbstractAuditingEntity.

If we were to change the code (because some new way would be better than some former way of doing something), we'd have to change the grammar, and that's a direct dependency... That's not that big an issue and I can implement a "deprecated" warning.

Except this problem, I like the idea of extending the JDL. After all, it can already be used to generate entities and applications.

Looks like VagabondUML is not actively maintained anymore, too bad =(

atomfrede commented 7 years ago

👍 I really like the idea to make the jdl more powerful. Especially the idea to be able to provide some more hints to an entity as I was asked multiple times already how to get audit functions.

hakandilek commented 7 years ago

@agoncal thanks for bringing that into discussion and letting me know about that. I agree that JDL is a lot more powerful than CLI and I am a fan of "persisted textual representations of domain models". ;-)

vagabond-uml has started about a year ago to put some ideas about making JDL more flexible. It was not updated since then due to the lack of interest from the community. At that time we have exchanged some emails with @MathieuAA and that was it.

I'd love to see where the discussion here will bring us and I am open to contribute. :-)

deepu105 commented 7 years ago

@jhipster/developers let me share my thoughts. I had some discussion with @agoncal regarding this and I believe I had some exchanges with @MathieuAA on similar things in the past. These are my personal opinions.

@MathieuAA what is the status of supporting app generation from JDL, I believe you were working on that

I also wish that at some point in future JHipster becomes an intelligent platform where you could craft entire applications or microservice stack using JDL, something like

app MyAwesomeGateway {
  config {
    type 'gateway'
    package 'com.awesome.app'
    clientFramework: 'angular'
    databaseType 'sql'
    ...
  }
  entity myEntity {
  ...
  }
  relationship ManyToOne {
  ...
  }
  pagination ...
  ....
}

app MyAwesomeService1 {
  config {
    type 'microservice'
    package 'com.awesome.app'
    databaseType 'mongo'
    ...
  }

  entity myEntity {
  ...
  }
  relationship ManyToOne {
  ...
  }
  pagination ...
  microserviceName ...
  ....
}

app MyAwesomeService2 {
  config {
    type 'microservice'
    package 'com.awesome.app'
    databaseType 'no'
    ...
  }
  service MyAwesomePollingService {
    void pollStuff(Long interval, SomeClass data)
  }

  microserviceName ...
  ....
}
deepu105 commented 7 years ago

Imagine how magical it would be to have an entire microservice stack generated from one command with the JDL above :sunglasses:

MathieuAA commented 7 years ago

@deepu105 the app generation is done (minus some probable minor changes I might make before releasing). With the first version of the app generation one can generate apps (no big deal). The second version (more of an improvement really) that I intend to commit this week-end will enable adding entities to any previously created app (in the same or any separate file).

About the first version, documentation is on its way. About the second, if for instance I want to use a JDL file to create 3 apps, and 13 entities in each, this would be the generated structure:

Of course Deepu, the point is to be able to quickly generate microservice apps (gateway included). That was the whole point from the very beginning =)

deepu105 commented 7 years ago

@MathieuAA what is the syntax that you have now? It would be very nice if it is something like

app AppName {
  config {
  ....
  }
  entity EntityName {
  ...
  }
  ....
}

so that segrgation is easier and and it is easier to read as well. WDYT?

deepu105 commented 7 years ago

@MathieuAA also I think its very important that we all agree on the syntax/grammar before releasing this else it will become difficult to change later so lets discuss and get concurrence from the core team first here before we release version1 as its a big step

agoncal commented 7 years ago

@deepu105 I like the "new" syntax that you are proposing: one single file to generate an entire app (this new syntax could be an excuse to get a JHipster 5.0 ;o).

ATM when I need to add new attributes on an entity, I always try to keep my JDL up to date. So for me, it feel redundant to have the entity descriptors (under .jhipster). You have twice the same information, and you can either generate the code from the JDL or from the JSON entity files.

But I have to say, even if I don't use the CLI anymore, it is a nice way for new comers to get into JHipster quickly. Maybe the CLI could stay displaying a little warning "Use the JDL syntax to get the most of JHipster", or something like that ;o)

MathieuAA commented 7 years ago

I had a more "split" syntax in mind, so that moving entities to and fro apps (or adding and removing) wouldn't change the app declaration or the entity declaration (for instance one could declare entities in one file, and apps in another). one Of course, two syntaxes could be possible in any case:

application {
  baseName MySuperApp
  type monolith
  entities J, H, I, P, S, T, E, R
}

application {
  baseName IDontHaveAnyIdeaHowIShouldCallIt
  type microservice
  entities J, D, L
}

application {
  baseName Tutu
  type microservice
  entities * except A // because why not?
}

entity A
entity B
...
entity Z

or

application {...}
application {...}

entity A...Z

generate <A..Z> in <app_name>
generate * except <A...Z> in <app_name>
deepu105 commented 7 years ago

@MathieuAA while your syntax is perfect for power users it might not be very friendly to beginners and people who look at a JDL for the first time as you have to mentally map entities to apps. Where as grouping them in app makes user experience much better and very easy to read and understand the model. IMO It would be very nice if we can support both what I suggested and one of the option you suggested without much overhead. Lets see what others think about it

MathieuAA commented 7 years ago

@deepu105 Yeah, let's do both.

agoncal commented 7 years ago

In microservice architectures, you tend to see the same entity name, but with different meaning. So, for example, let's say we have twice the entity Customer with total different meaning on 2 applications (so, with different attributes):

app Relation {
  config {  ....  }
  entity Customer {
    String name required,     
    String contactEmail required,
    String street
  }
}

app Accountancy {
  config {  ....  }
  entity Customer {
    String name required,     
    int customerBilling,
    String invoiceAddress
  }
}

If we can use both syntaxes, we would need to differentiate them. Either fully qualifying the name

app Relation {
  config {  ....  }
  entities A, B, relation.Customer 
}

app Accountancy {
  config {  ....  }
  entities C, D, account.Customer 
}

entity relation.Customer {
    String name required,     
    String contactEmail required,
    String street
}

entity account.Customer {
    String name required,     
    int customerBilling,
    String invoiceAddress
}

Or using aliases (as keyword)

app Relation {
  config {  ....  }
  entities A, B, CustomerRelation as Customer 
}

app Accountancy {
  config {  ....  }
  entities C, D, CustomerAccountancy as Customer 
}

entity CustomerRelation {
    String name required,     
    String contactEmail required,
    String street
}

entity CustomerAccountancy {
    String name required,     
    int customerBilling,
    String invoiceAddress
}
MathieuAA commented 7 years ago

Fully qualifying is a good idea.

hakandilek commented 7 years ago

I like the idea of generating entire microservice stack based on JDL without CLI interaction.

What about other JDL syntax changes and backwards compatibility? Is it a better idea to push other proposed changes like service, repository, and (env)variables and still keep it compatible with the current JDL syntax or skip the overhead and keep it simple?

MathieuAA commented 7 years ago

Implementing new things like that isn't an issue for me. As @agoncal and I talked about last time we met, it's more about making it possible in the generator.

agoncal commented 7 years ago

And what about the best of both worlds.

We could use singular to mark an artifact (eg. entity, repository, service...) and plural to mark a reference to an artifact (eg. entities, repositories, services...). And we could still qualify names.

Is something like that readable:

app Relation {
  config {  ....  }

  entities A, B, rel.Customer   // notice the rel
  entity MyOnlyEntity {         // singular
    String code;
  }

  repositories ARep, BRep       // plural, references other repositories
  repository MyOnlyRep {        // singular
    Customer findByName(String name);
  }
}

app Accountancy {
  config {  ....  }
  entities A, B, acc.Customer   // notice the acc 
}

entity rel.Customer {
    String name required,     
    String contactEmail required,
    String street
}

entity acc.Customer {
    String name required,     
    int customerBilling,
    String invoiceAddress
}

entity A {...}
entity B {...}

repository ARep {
  String findByTitle();
}
repository BRep {
  int countByAge(int age);
}
MathieuAA commented 7 years ago

That'd be a very understandable convention!

agoncal commented 7 years ago

If the "new" JDL is meant to bootstrap any kind of application, we could have things like that.

Bootstraping a Monolith

jdlVersion=2                  // This will help with future versions of the JDL

application {                 // This states that an application will get generated, that's all

  import myOtherJDLFile.jdl;  // I'm importing another JDL file, why not ;o)

  config {
    buildTool "maven",
    clientPackageManager "yarn"
  }

  monolith Relation {         // The monolith keyword is to create a monolith app

    config {
      groupId "org.comp.proj";
    }
}

Bootstraping a more complex microservice application

jdlVersion=2                

application {

  import myOtherJDLFile.jdl;  // Contains microservices MSOne, MSTwo, entities A, B, repositories ARep, BRep

  config {
    groupId "org.comp.proj";
    authenticationType "jwt";
    cache "hazelcast";
    serviceDiscoveryType "eureka",
    buildTool "maven",
    clientPackageManager "yarn"
  }

  microservices MSOne, MSTwo;       // microservices (plural) refers to MS that are external (from the import JDL file)

  microservice Relation {            // defines one microservice app
    config {
      httpPort=8081 // or httpPort = offset+100
      artifactId "relation-ms";
      packageName "org.comp.proj";
      serverPort "8081";
      databaseType "Postgresql",
      postgresqlPort "5499",
    }

    entities A, B                    // referes to external entities
    entity MyOnlyEntity {     // one entity of the MS Relation
      String code;
    }

    repositories ARep, BRep      // referes to external repositories
    repository MyOnlyRep {
      Customer findByName(String name);
    }
  }

  microservice Accountaincy {    //  a second microservice app
    config { 
      httpPort=8082
    }
    ...
  }

  gateway RelationOnAccountancy {   // here is the gateway
    config { 
      httpPort=8080
    }
    ...
  }

  uuaServer MyAythServer {...}     // here is a UUA server

  adminConsole MyAdminConsole {...}    // here is the JHipster admin console
}

Keywords

Basically, we would have a bunch of keywords related to the architecture we want:

And other keywords related to the content of each app:

MathieuAA commented 7 years ago

It may be too complicated:

entity J entity H ... entity R


looks pretty good to me. 

Having the singular & plural forms for "entity" or "service" is an **awesome idea**.
The only issue is wrapping things like entities inside an application. Declarations could really be bloated and ugly if people don't do versioning (keeping old JDL files as migration steps).

For me, an application is an application and can either be a microservice, a monolith or whatever. I don't see it as root. And I don't like the idea of mixing the `application` keyword with `monolith` or something else. Two choices are available:
  - Having `application { applicationType WHATEVER }`
  - Or having `WHATEVER { }`
I prefer the latter as we easily could exclude disallowed rules right from the grammar, and it's easier to see the app type.
---
To sum it all up, for me:
  - Importing a file with `import my_jdl_file.jdl` from an application declaration (as long as the file is valid, follows the grammar): **yes**
  - Having the `config` keyword: **no** (redundant)
  - `httpPort=XXXX` -> `httpPort XXXX` (JSON already needs delimiters, I'd like to keep my grammar as simple as possible)
  - Using singular and plural forms to mean two different things: **yes**
  - Keywords like `monolith, microservice, etc.` replacing the `application keyword`: **yes** (it could be a pain in the ass to maintain in the long term, but I don't care, it's a good idea)

A few other things:
  - Constants (already in delivered) can be extended to have other types (Strings for instance), but we have to refer to them some other way (like :CONSTANT8NAME or <WHATEVER_SYMBOL>CONSTANT_NAME
  - I'm seriously thinking about dropping PegJS as it has some annoying limitations, but it's **really** easy to use and everything's already done with it. I'd hate to switch to some other thing that could be a pain in the ass to use. I'm open for ideas.
cbornet commented 7 years ago

Defining several micro-services in a unique file feels like distibuting a monolith to me... IMO there should be only one app per JDL.

agoncal commented 7 years ago

@cbornet I think it's important to define "what is an application" ? Today, even the smallest project needs several blocks. These blocks are microservices, of course, but also one or two gateways, a registry, console, admin, log.... All these blocks will form one application (or let's call it product).

If you have:

application {
  microservice weather { ... }
  microservice forecast { ... }
  microservice continent { ... }
  gateway weatherforecast { ... }
  registry { ... }
  console { ... }
}

You could end up with the following structure:

├── README.md
├── .ignore
├── pom.xml
├── weather
│   ├── pom.xml
│   └── src
│       └── main
│
├── forecast
│   └── pom.xml
├── continent
│   └── pom.xml
├── weatherforecast
│   └── pom.xml
├── registry       // registry and console would just have the docker files under src/main/docker
└── console

But you would also have the choice to create one product per application:

application {
  microservice weather { ... }
}

application {
  microservice forecast { ... }
}

And you will end up with a different structure (no parent pom, different groupid...):

├── weather
│   ├── pom.xml
│   └── src
│       └── main
│
├── forecast
│   └── pom.xml

You could then have both choices.

cbornet commented 7 years ago

Well, to me, microservices should have independant lifecycle, ownership, etc... So binding them in a JDL file is against the philosophy.

agoncal commented 7 years ago

@cbornet For a single product, you could just have one microservice and one gateway (therefore, a registry). That's a valid application that needs 3 different blocks.

BTW, when I mentioned the previous structure, I didn't see any inheritance, or binding between the application (therefore, no lifecycle dependency). In terms of pom.xml (let's stick with Maven for now), you'll have:

├── README.md
├── .ignore
├── pom.xml        // Only has <modules>, can be deleted (but useful for IDE support for ex)
├── weather
│   └── pom.xml    // does not inherit from the pom
└── forecast
    └── pom.xml
cbornet commented 7 years ago

You have dependency at the JDL level. If there are multiple teams, who is owner of the JDL ?

deepu105 commented 7 years ago

Nice ideas @agoncal buts lets not complicate things too much I agree with @MathieuAA mostly except for few thing below

Having the config keyword: no (redundant)

It is redundant but good for readability as you can easily separate the application configuration from other stuff like entities, entity options(pagination, service ..) etc.

Keywords like monolith, microservice, etc. replacing the application keyword: yes (it could be a pain in the ass to maintain in the long term, but I don't care, it's a good idea)

Not very sure about this. using the application keyword gives as the flexibility to add an applicationType field in the config and decide what it is. I also don't like idea of nesting applications inside another application as @cbornet highlighted for microservices this feels against the whole theory. I would prefer 1 file per service and common stuff in another file

So wrapping up my personal favorite syntax would be (stealing some ideas from @agoncal and @MathieuAA )

commonConfig.jdl

BASE_PORT 8080 // common constants

application abstract BaseApp { // Implies that the app is abstract and will not be generated
  config {
    groupId "org.comp.proj"
    authenticationType "jwt"
    cache "hazelcast"
    serviceDiscoveryType "eureka"
    buildTool "maven"
    serverPort BASE_PORT
    packageName "org.comp.proj"
  }
}

entity abstract A {} // Implies entity is abstract and will not be generated unless referred to from an application
entity abstract B {}
entity abstract C {
    String name
}

services abstract AService { // Implies service is abstract and will only be generated when referred from an application
    Customer findByName(String name)
}

myMicroservice1JDLFile.jdl

import commonConfig.jdl             // import common configuration

application MyMicroservice1 {
  type 'microservice'
  config extend BaseApp {           // extend base app config
    serverPort (BASE_PORT + 100)
    databaseType "mongodb"
  }

  entity MyOnlyEntity extends C {     // one entity of the service extends one from commonConfig.jdl
    // this will have the field name generated as it extends entity C
    String code
  }

  services AService      // refers to external services from commonConfig.jdl
  services MyOnlyService {
    Customer findByName(String name)
  }

  paginate * with pager
  service * with serviceImpl
}

myGateway.jdl

import commonConfig.jdl             // import common configuration
import myMicroservice1JDLFile.jdl   // import microservice 1
import myMicroservice2JDLFile.jdl   // import microservice 2 and so on
import dockerConfig.jdl             // import docker compose setup

application MyGateway {
  type 'gateway'
  config extend BaseApp {           // extend base app config
    databaseType "Postgresql"
    clientFramework "react"
  }

  entities A, B                       // refers to external entities from commonConfig.jdl
  entity MyOnlyEntity extends C {     // one entity of the gateway extends one from commonConfig.jdl
    // this will have the field name generated as it extends entity C
    String code
  }

  relationship ManyToMany {
      A{b} to B{a}
  }

  services AService      // refers to external services from commonConfig.jdl
  services MyOnlyService {
    Customer findByName(String name)
  }

  paginate * with infinite-scroll
  service * with serviceImpl
}

This will generate

├── my-gateway
│   ├── pom.xml
│   └── src
│       └── main
│
├── my-microservice-1
│   └── pom.xml
|
├── my-microservice-2
│   └── pom.xml
├── docker-compose 

I'm seriously thinking about dropping PegJS as it has some annoying limitations, but it's really easy to use and everything's already done with it. I'd hate to switch to some other thing that could be a pain in the ass to use. I'm open for ideas.

@MathieuAA take a look at http://zaa.ch/jison/ its suppose to be easy to use as well, but not sure if its better than PegJS(it's apparently used for Coffescript). Also found few other options here https://sap.github.io/chevrotain/performance/

bd82 commented 7 years ago

Hello @MathieuAA @deepu105 & everyone else.

I'm the main author of the benchmark linked above: https://sap.github.io/chevrotain/performance/

And of the Chevrotain parsing library.

I'm seriously thinking about dropping PegJS as it has some annoying limitations, but it's really easy to use and everything's already done with it. I'd hate to switch to some other thing that could be a pain in the ass to use. I'm open for ideas.

Questions:

  1. Can you describe these "annoying limitations"?
  2. If you create your own JDL DSL do you also intend to to provide some kind of editor support for it? Examples:
    • Auto complete.
    • Highlighting syntax / semantic errors.
    • Formatting
    • EDIT: I just saw https://github.com/jhipster/jhipster-ide which uses Xtext.
    • Does this mean the pegjs grammar is for compilation purposes only and the grammar is duplicated in some Xtext format for editor purposes?

Additional Resource on Parsing Libraries in JavaScript:

On building Parsers by hand.

Most programing languages are built without Parser Generators or Combinators. Instead a recursive decent parser is created "by hand"

This is usually due to the need for maximum control, to achieve high performance, specific error messages, error recovery capabilities and so on.

From what I understand JDL is not a programing language, but a Definition Language So while this is not the exact use case described above, and perhaps performance considerations are less important, but I think that if the editor use case is relevant those other concerns could have an high impact in the long term.

Why would a Parser Library author recommend against using parsing libraries?

Firstly it always depends on the specific use case. More importantly Chevrotain represents a different approach and is more like a library which makes it easier to write parsers by hand (rather than write a grammar that generates a parser). So the usual limitations of Parsing generators/combinators are much less applicable.

MathieuAA commented 7 years ago

@deepu105 Yes, this syntax is really good. Let's freeze it for now to know where we're heading. The whole "abstract" thing is good and easy to implement, plus it's easy to guess what's its use so new and seasoned users know what they'd be using..

I'll have a look at everything you guys have linked to the previous posts.

@bd82 hello there! PegJS doesn't support Regexes, the generated parser is ugly (I think the parser is generated from a template, which is itself kinda ugly and never cleaned up after the generation process is over) and we (Carl and I, two years ago or so) have encountered some cases where we had to ask ourselves "Ok, we know how to do it using XXX, how the hell do we do that now?". I have to have a look at various tools to make my mind.

Finally, we have to redefine what is an application. I say redefine because (warning: I'll be using the "thing" word a lot):

So.... importing a JDL that creates an app structure isn't that crazy an idea, we just have to define a convention of usability and readability, -> define a good, clean way of doing things.

Defining several micro-services in a unique file feels like distributing a monolith to me... IMO there should be only one app per JDL.

I agree with @cbornet on this point, but users are free to do whatever they want and if they want to define everything they have in a single file (as ugly as it is) they are free to do it. We could have warnings to tell users why this is not considered a good practice and what they should do instead.

PierreBesson commented 7 years ago

@bd82

: I just saw https://github.com/jhipster/jhipster-ide which uses Xtext. • Does this mean the pegjs grammar is for compilation purposes only and the grammar is duplicated in some Xtext format for editor purposes?

From my understanding this is exactly what is done (sorry I'm not the developer of jhipster-ide and know very little about parsers...). Note that the IDE project is a work in progress (works only for Eclipse & VSCode) but it's really cool and definitely integration between the JDL and editors is a goal of the project.

deepu105 commented 7 years ago

For JDL studio I provide auto-complete support by adding a custom script. Syntax errors are reported by using the same pegJS parser used by the Jhipster core

deepu105 commented 7 years ago

@bd82 writing our own parser sounds like a good idea given that it is much more flexible. @MathieuAA what do you think about that and about Chevrotain parsing library?

bd82 commented 7 years ago

Syntax errors are reported by using the same pegJS parser used by the Jhipster core

So this means you can only report the first syntax error? because pegjs stops on the first error and cannot recover.

Try the Chevrotain Playground and select different "samples" in the input pane while examining the output pane to see how multiple syntax errors and partial parsing results **auto-magically" just work because the algorithms for fault tolerance and error recovery are embedded in the library.

For JDL studio I provide auto-complete support by adding a custom script.

Could you link to the custom script please?

Next questions:

MathieuAA commented 7 years ago
MathieuAA commented 7 years ago

I'm locking this thread as I've created the related issue in JHipster Core

deepu105 commented 7 years ago

@jdubois do let us know what you think as wellm

jdubois commented 7 years ago

Thanks @deepu105 - I didn't have a look at all, and I won't be able to do it this week (I'm in New York, meeting lots of JHipster users!). But I trust all of you on this: just go on, and I'll have a look when I have more time.