diff --git a/README.md b/README.md index a2578426..b94152db 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ the time you spend writing boilerplate serialization code for your models. * [Serialization](#serializaition) * [Nesting](#nesting) * [ID and Date Fields](#id-and-dates) + * [TypeScript Definition Generator](#typescript-definitions) # Usage In your `pubspec.yaml`, you need to install the following dependencies: @@ -209,3 +210,41 @@ You can also override `autoIdAndDateFields` per model: @Serializable(autoIdAndDateFields: false) abstract class _Skinny extends Model {} ``` + +# TypeScript Definitions +It is quite common to build frontends with JavaScript and/or TypeScript, +so why not generate typings as well? + +To accomplish this, add `Serializers.typescript` to your `@Serializable()` declaration: + +```dart +@Serializable(serializers: const [Serializers.map, Serializers.json, Serializers.typescript]) +class _Foo extends Model {} +``` + +The aforementioned `_Author` class will generate the following in `author.d.ts`: + +```typescript +interface Author { + id: string; + name: string; + age: number; + books: Book[]; + newest_book: Book; + created_at: any; + updated_at: any; +} +interface Library { + id: string; + collection: BookCollection; + created_at: any; + updated_at: any; +} +interface BookCollection { + [key: string]: Book; +} +``` + +Fields with an `@Exclude()` that specifies `canSerialize: false` will not be present in the +TypeScript definition. The rationale for this is that if a field (i.e. `password`) will +never be sent to the client, the client shouldn't even know the field exists. \ No newline at end of file diff --git a/angel_serialize/.packages b/angel_serialize/.packages index 04b29188..a255ba50 100644 --- a/angel_serialize/.packages +++ b/angel_serialize/.packages @@ -1,2 +1,2 @@ -# Generated by pub on 2018-03-02 16:15:05.377739. +# Generated by pub on 2018-03-29 15:50:32.802835. angel_serialize:lib/ diff --git a/angel_serialize/CHANGELOG.md b/angel_serialize/CHANGELOG.md index 07b187c9..fa004575 100644 --- a/angel_serialize/CHANGELOG.md +++ b/angel_serialize/CHANGELOG.md @@ -1,2 +1,5 @@ +# 2.0.1 +* Added `Serializers.typescript`. + # 2.0.0 * Dart 2+ constraint \ No newline at end of file diff --git a/angel_serialize/lib/angel_serialize.dart b/angel_serialize/lib/angel_serialize.dart index ead7ab28..a33d689e 100644 --- a/angel_serialize/lib/angel_serialize.dart +++ b/angel_serialize/lib/angel_serialize.dart @@ -33,13 +33,16 @@ const Serializable serializable = const Serializable(); /// The supported serialization types. abstract class Serializers { /// All supported serialization types. - static const List all = const [map, json]; + static const List all = const [map, json, typescript]; /// Enable `fromMap` and `toMap` methods on the model class. static const int map = 0; /// Enable a `toJson` method on the model class. static const int json = 1; + + /// Generate a TypeScript definition file (`.d.ts`) for use on the client-side. + static const int typescript = 2; } /// Specifies an alias for a field within its JSON representation. diff --git a/angel_serialize/pubspec.yaml b/angel_serialize/pubspec.yaml index f2a5d456..3ab1dff0 100644 --- a/angel_serialize/pubspec.yaml +++ b/angel_serialize/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_serialize -version: 2.0.0 +version: 2.0.1 description: Static annotations powering Angel model serialization. Combine with angel_serialize_generator for flexible modeling. author: Tobe O homepage: https://github.com/angel-dart/serialize diff --git a/angel_serialize_generator/CHANGELOG.md b/angel_serialize_generator/CHANGELOG.md index f97c84a0..2d130b82 100644 --- a/angel_serialize_generator/CHANGELOG.md +++ b/angel_serialize_generator/CHANGELOG.md @@ -1,3 +1,6 @@ +# 2.0.3 +* Added a `TypeScriptDefinitionBuilder`. + # 2.0.2 * Generates an `XFields` class with the serialized names of all fields in a model class `X`. diff --git a/angel_serialize_generator/build.yaml b/angel_serialize_generator/build.yaml index 440f73cc..842854c9 100644 --- a/angel_serialize_generator/build.yaml +++ b/angel_serialize_generator/build.yaml @@ -5,27 +5,13 @@ builders: builder_factories: - jsonModelBuilder - serializerBuilder + - typescriptDefinitionBuilder auto_apply: root_package build_to: source build_extensions: .dart: - ".g.dart" - ".serializer.g.dart" - required_inputs: - - .dart - defaults: - generate_for: - - "lib/src/models/**.dart" - - "test/**.dart" - typescript_definition: - target: "angel_serialize_generator" - import: "package:angel_serialize_generator/angel_serialize_generator.dart" - builder_factories: - - typescriptDefinitionBuilder - auto_apply: root_package - build_to: source - build_extensions: - .dart: - ".d.ts" required_inputs: - .dart @@ -37,8 +23,12 @@ targets: _book: sources: - "test/models/book.dart" + _typescript_definition: + sources: + - "lib/*.dart" $default: dependencies: - ":_book" sources: + - "lib/*.dart" - "test/models/author.dart" diff --git a/angel_serialize_generator/lib/typescript.dart b/angel_serialize_generator/lib/typescript.dart index ca4a3b76..d4cf7372 100644 --- a/angel_serialize_generator/lib/typescript.dart +++ b/angel_serialize_generator/lib/typescript.dart @@ -78,7 +78,14 @@ class TypeScriptDefinitionBuilder implements Builder { @override Future build(BuildStep buildStep) async { var contexts = []; - var lib = new LibraryReader(await buildStep.inputLibrary); + LibraryReader lib; + + try { + lib = new LibraryReader(await buildStep.inputLibrary); + } catch (_) { + return; + } + var elements = lib.annotatedWith(const TypeChecker.fromRuntime(Serializable)); @@ -86,6 +93,17 @@ class TypeScriptDefinitionBuilder implements Builder { if (element.element.kind != ElementKind.CLASS) throw 'Only classes can be annotated with a @Serializable() annotation.'; + var annotation = element.annotation; + + var serializers = annotation.peek('serializers')?.listValue ?? []; + + if (serializers.isEmpty) continue; + + // Check if TypeScript serializer is supported + if (!serializers.any((s) => s.toIntValue() == Serializers.typescript)) { + continue; + } + contexts.add(await buildContext( element.element, element.annotation, @@ -102,6 +120,8 @@ class TypeScriptDefinitionBuilder implements Builder { sourceUrl: buildStep.inputId.uri, ); + buf.writeln('// GENERATED CODE - DO NOT MODIFY BY HAND'); + // declare module `foo` { //buf // ..writeln("declare module '${buildStep.inputId.package}' {") diff --git a/angel_serialize_generator/pubspec.yaml b/angel_serialize_generator/pubspec.yaml index b4da0290..ed9b3270 100644 --- a/angel_serialize_generator/pubspec.yaml +++ b/angel_serialize_generator/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_serialize_generator -version: 2.0.2 +version: 2.0.3 description: Model serialization generators, designed for use with Angel. Combine with angel_serialize for flexible modeling. author: Tobe O homepage: https://github.com/angel-dart/serialize diff --git a/angel_serialize_generator/test/models/author.d.ts b/angel_serialize_generator/test/models/author.d.ts new file mode 100644 index 00000000..643f1451 --- /dev/null +++ b/angel_serialize_generator/test/models/author.d.ts @@ -0,0 +1,10 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +interface Library { + id: string; + collection: BookCollection; + created_at: any; + updated_at: any; +} +interface BookCollection { + [key: string]: Book; +} diff --git a/angel_serialize_generator/test/models/author.dart b/angel_serialize_generator/test/models/author.dart index 95bcf089..ebf99092 100644 --- a/angel_serialize_generator/test/models/author.dart +++ b/angel_serialize_generator/test/models/author.dart @@ -3,7 +3,9 @@ library angel_serialize.test.models.author; import 'package:angel_framework/common.dart'; import 'package:angel_serialize/angel_serialize.dart'; import 'book.dart'; + part 'author.g.dart'; + part 'author.serializer.g.dart'; @serializable @@ -20,7 +22,7 @@ abstract class _Author extends Model { String obscured; } -@serializable +@Serializable(serializers: Serializers.all) abstract class _Library extends Model { Map collection; } diff --git a/angel_serialize_generator/test/models/book.d.ts b/angel_serialize_generator/test/models/book.d.ts new file mode 100644 index 00000000..0d6303d2 --- /dev/null +++ b/angel_serialize_generator/test/models/book.d.ts @@ -0,0 +1,12 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +interface Book { + id: string; + author: string; + title: string; + description: string; + page_count: number; + not_models: any[]; + camelCase: string; + created_at: any; + updated_at: any; +} diff --git a/angel_serialize_generator/test/models/book.dart b/angel_serialize_generator/test/models/book.dart index 74381a70..c1b5b8fe 100644 --- a/angel_serialize_generator/test/models/book.dart +++ b/angel_serialize_generator/test/models/book.dart @@ -5,7 +5,7 @@ import 'package:angel_serialize/angel_serialize.dart'; part 'book.g.dart'; part 'book.serializer.g.dart'; -@serializable +@Serializable(serializers: Serializers.all) abstract class _Book extends Model { String author, title, description; int pageCount; diff --git a/angel_serialize_generator/tool/applications.dart b/angel_serialize_generator/tool/applications.dart index 3be1c5c6..561f3da0 100644 --- a/angel_serialize_generator/tool/applications.dart +++ b/angel_serialize_generator/tool/applications.dart @@ -29,6 +29,10 @@ final List applications = [ ), generateFor: all, ), + applyToRoot( + const TypeScriptDefinitionBuilder(), + generateFor: all, + ), ]; /*