Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Generate client API code, part 1 #1259

Merged
merged 78 commits into from
Jul 9, 2019

Conversation

benjamingeer
Copy link

@benjamingeer benjamingeer commented Mar 19, 2019

This PR is a first step towards #1256.

  • Add ClientApi, a programming-language-independent representation of a Knora client API. Each KnoraRoute can implement ClientEndpoint to define client API functions that should be generated.
  • Add a route, /clientapi/TARGET, that generates client API code for the specified programming language target, returning a Zip file.
    • Implement GeneratorFrontEnd, which converts ontology class definitions into instances of ClientClassDefinition, which are suitable for use in code generation.
  • Add a Scala DSL for defining client functions (see docs/src/paradox/05-internals/design/client-api/index.md).
  • Each target is implemented in a class that extends GeneratorBackEnd.
    • Implement the target typescript in TypeScriptBackEnd, which generates source code for use with knora-api-js-lib, using templates in twirl/clientapi/typescript.
  • Add AdminClientApi, defining the admin client API. Implemented so far:
    • UsersRouteADM
    • PermissionsRouteADM
    • GroupsRouteADM
    • ProjectsRouteADM
  • Add documentation.

To test locally, start Knora and visit http://0.0.0.0:3333/clientapi/typescript.

To do in subsequent PRs:

@benjamingeer benjamingeer self-assigned this Mar 19, 2019
@benjamingeer benjamingeer mentioned this pull request Mar 19, 2019
@benjamingeer benjamingeer changed the title Generate client code from ontologies, part 1 feat: Generate client code from ontologies, part 1 Apr 1, 2019
benjamingeer pushed a commit that referenced this pull request Apr 11, 2019
* test: Compare instances with class definitions (ongoing).

* test: Check responses against ontology defs (ongoing).

* test: Check instance against ontology (ongoing).

* feat: Check Knora responses against ontologies (ongoing).

* test: Check Knora responses against ontology definitions (ongoing).

* test: Check Knora responses against ontologies (ongoing).

* test: Import some functionality from #1259.

* test: Import functionality from #1259.

* test: Check Knora responses against ontologies (ongoing).

- Fix some inconsistencies in ontologies.

* test: Check Knora responses against ontologies (ongoing).

- Fix more inconsistencies in ontologies.

* chore(api-v2): Fix Gravesearch type inference not to infer knora-api:ValueBase types.

* style (InstanceChecker): Clarify code, add comments.

* test: Start adding InstanceCheckerSpec.

* fix(api-v2): Put hasStandoffLinkTo back in simple schema because Gravsearch needs it.

- Fix broken IT test.

* test(InstanceChecker): Test InstanceChecker (ongoing).

* test(InstanceChecker): Test InstanceChecker (ongoing).

* test(InstanceChecker): Test InstanceChecker (ongoing).

* test(InstanceChecker): Test InstanceChecker with JSON.
# Conflicts:
#	webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala
@benjamingeer benjamingeer changed the title feat: Generate client code from ontologies, part 1 feat: Generate client API code, part 1 Jun 25, 2019
Copy link
Collaborator

@subotic subotic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great. Thanks :-)

@benjamingeer
Copy link
Author

Thanks, glad you like it!

@daschbot
Copy link
Collaborator

daschbot commented Jul 3, 2019

This pull request has been mentioned on Discuss DaSCH. There might be relevant details there:

https://discuss.dasch.swiss/t/generating-client-libraries/25/2

@benjamingeer benjamingeer merged commit 969f227 into develop Jul 9, 2019
@benjamingeer benjamingeer deleted the wip/1256-generate-client-code branch July 9, 2019 11:25
@daschbot
Copy link
Collaborator

daschbot commented Jul 9, 2019

This pull request has been mentioned on Discuss DaSCH. There might be relevant details there:

https://discuss.dasch.swiss/t/generating-client-libraries/25/3

code for the specified target:

```
HTTP GET to http://host/v2/clientapi/TARGET
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v2 should be removed from the path

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will fix in a new PR when I get back from holiday.

@andreas-aeschlimann
Copy link

I have looked into the TypeScript source and found the following issues:

Classes

  • Class names: It would be good if we kept the same structure. For example, admin/groups/groups-endpoint.ts instead of groups-api-endpoint.ts.
  • Import path: Some import paths are wrong, they start with models/... instead of the relative path.
  • Import name: Import strings must not end with .ts, there should not be any file extension given.
  • Code style: I suggest to drop the public keyword everywhere. It is the default and thus redundant.
  • Code style 2: There should be no new line before the first import line, and only one new line after the class end. There should not be more than 1 empty line in a row.
  • Documentation style: There is a space missing in the documentation code when you start a documentation block with /**.

Types

  • In some cases you used references like project.id where id is used in the API path. However, you have set the type of id to undefined | string because it is an optional property. This leads to a compile error when you use project.id as a string. We need a type check at every use (for example: if (project.id !== undefined) ...), or we do not make those properties optional.

As a general remark, if we really auto-generate everything, then we do not need to create the interfaces.

I think it looks good so far. I could not compile the library yet due to these issues, but I suppose it would be possible to fix them.

@andreas-aeschlimann
Copy link

As answer to your question: We do not need the interfaces/base classes until we bump into circular references. Indeed, I have found circular imports already which will lead to compile errors. For example, the class Project imports User and User imports Project.

@benjamingeer
Copy link
Author

@andreas-aeschlimann Thanks for checking the generated code.

Class names: It would be good if we kept the same structure. For example, admin/groups/groups-endpoint.ts instead of groups-api-endpoint.ts.

Are you talking about the directory structure or the filenames? I tried to keep the same directory structure, but some of the filenames are different. I assumed that the filenames were not important, but if you like the old filenames better, we can change them.

Import path: Some import paths are wrong, they start with models/... instead of the relative path.

Can you be more specific about which ones are incorrect and what they should be?

Code style 2: There should be no new line before the first import line, and only one new line after the class end. There should not be more than 1 empty line in a row.

It can be difficult to control whitespace in the output while still keeping the templates readable. I will try.

  • Documentation style: There is a space missing in the documentation code when you start a documentation block with /**.

I don't understand. Where should the space be? Can you give an example?

We need a type check at every use (for example: if (project.id !== undefined) ...)

That's easy to add.

As a general remark, if we really auto-generate everything, then we do not need to create the interfaces.

OK, that makes things simpler. :)

Since this PR has already been merged, please open a new issue for what needs to be changed. I can look at it when I get back from holiday on 12 August. Or you can try changing the TypeScript backend code and templates yourself:

https://github.com/dhlab-basel/Knora/blob/develop/webapi/src/main/scala/org/knora/webapi/util/clientapi/TypeScriptBackEnd.scala

https://github.com/dhlab-basel/Knora/tree/develop/webapi/src/main/twirl/clientapi/typescript

@benjamingeer
Copy link
Author

We do not need the interfaces/base classes until we bump into circular references. Indeed, I have found circular imports already which will lead to compile errors. For example, the class Project imports User and User imports Project.

Can you make a list of which classes need interfaces?

@andreas-aeschlimann
Copy link

  1. Name convention is: file-name.ts should be class FileName. file-name.service.ts should be injectable class FileNameService, for example.

  2. Some imports were models/bla/bla/file.ts. The path always must be relative, models is not the root folder.

  3. The first line of your documentation block /** has three spaces before the slash instead of 4. Our style checker whines about it, because it is usually 4 spaces.

I will be back mid August as well, so I will gladly respond you in detail then. Have a great time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API/Admin enhancement improve existing code or new feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants