PiotrFLEURY / nenuphar_cli

A Very Good Dart CLI generating openapi.json file for Dart Frog
https://pub.dev/packages/nenuphar_cli
BSD 3-Clause "New" or "Revised" License
17 stars 1 forks source link

feat: Generating schemas based on json_serializable models #38

Open dawid-niedzwiecki opened 1 year ago

dawid-niedzwiecki commented 1 year ago

Description

It would be great if the tool generated all the schemas based on the models that are being returned from a route.

PiotrFLEURY commented 1 year ago

Hi @dawid-niedzwiecki

Thanks for submitting this issue.

It is for sure a great simplification. We just need to find a good way to detect the model returned from a route.

Each Dart Frog route currently returns a Response or a Future<Response>.

Proposal

As nenuphar_cli works with comments I can try to create a new /// @Returns() comment to specify the returned model.

If the model is located in /lib/models/todos.dart

The syntax should be

/// @Returns(models/todos)
Future<Response> onRequest(RequestContext context) async {
//...
}

Questions

dawid-niedzwiecki commented 12 months ago

I am not really a fan of comments, makes it hard to move files between folders. How about annotations? Didn't mean to close the issue.

PiotrFLEURY commented 12 months ago

I was thinking about annotations.

For the moment, I tried to be as less intrusive as possible in the code compilation.

Maybe it is time to go next level.

New proposal

Replace all existing comment tags by annotations from a brand new library nenuphar_annotations.

Routes annotations

Routes annotations can be

///
/// The /todos routes
///
@Allow(GET, HEAD, POST, OPTIONS)
@Headers(['User-Name'])
@QueryParameters(['completed'])
@SecuritySchemes(['todos_basic_auth', 'todos_oauth'])
@Scopes(['read:todos', 'write:todos'])
@RequestBody('todos')
@Response('todos')
Future<Response> onRequest(RequestContext context) async {
//...
}

Model annotations

import 'package:json_annotation/json_annotation.dart';

part 'todos.g.dart';

/// Todo model
@JsonSerializable()
@JsonSchema()
class Todo {
//...
}

This is representing a lot of stuff but can represent the 1.0.0 version candidate.

What's your opinion @dawid-niedzwiecki ?

PiotrFLEURY commented 12 months ago

@dawid-niedzwiecki you can look at the branch version feat/annotations

This is a very experimental version made to imagine the future nenuphar version

See https://github.com/PiotrFLEURY/nenuphar_cli/pull/39

ralfeus commented 8 months ago

Hi Piotr, I tried your generator and it seems to be a good idea. Also I tried feat/annotations but it doesn't seem to recognize annotations. Here is how I annotate my methods:

@Allow(['GET'])
Future<Response> _get(Request request) async {
...
}

and that's what I've got as a result:

parsing route: /Users/ralfeus/Projects/atk_server/routes/block/index.dart evaluating path: /block No allowed methods found for /block Using default allowed methods: [options, get, head, post, put, patch, delete]

I've activated nenuphar_cli with command: dart pub global activate --source git https://github.com/PiotrFLEURY/nenuphar_cli.git --git-ref feat/annotations

PiotrFLEURY commented 8 months ago

Hi @ralfeus

Thank you for your feedback

I'm not really satisfied of the result on feat/annotations It require 2 more dependencies and code generation using build_runner, this is too much confusing.

The main version is only requiring a CLI command nenuphar gen. Using build_runner adds too much steps and complexity to reach the goal.

I plan a rework of the proposal idea in order to use only annotations and nenuphar gen command.

ralfeus commented 8 months ago

Would it make sense to build components definitions using reflection?

PiotrFLEURY commented 8 months ago

Would it make sense to build components definitions using reflection?

In fact it was my first purpose but I fall into a rabbit hole using it and I finally made the feat/annotations version.

I'll try to make a specific version targeting only the component definitions in order to close this issue and check for annotations later

ralfeus commented 8 months ago

I think you can't avoid using annotations even when using reflection. Any object tends to get more complicated, include runtime only attributes so it's better to declare serialisable attributes explicitly