Reference external Typescript models

This commit is contained in:
Tobe O 2018-05-15 15:50:12 -04:00
parent 90f7243c6b
commit 711bcebc0b
5 changed files with 47 additions and 12 deletions

View file

@ -7,6 +7,7 @@ import 'package:angel_serialize/angel_serialize.dart';
import 'package:build/build.dart'; import 'package:build/build.dart';
import 'package:code_buffer/code_buffer.dart'; import 'package:code_buffer/code_buffer.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:path/path.dart' as p;
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'package:source_gen/source_gen.dart' hide LibraryBuilder; import 'package:source_gen/source_gen.dart' hide LibraryBuilder;
import 'build_context.dart'; import 'build_context.dart';

View file

@ -12,8 +12,13 @@ class TypeScriptDefinitionBuilder implements Builder {
}; };
} }
Future<String> compileToTypeScriptType(BuildContext ctx, String fieldName, Future<String> compileToTypeScriptType(
InterfaceType type, List<CodeBuffer> ext, BuildStep buildStep) async { BuildContext ctx,
String fieldName,
InterfaceType type,
List<String> refs,
List<CodeBuffer> ext,
BuildStep buildStep) async {
String typeScriptType = 'any'; String typeScriptType = 'any';
var types = const { var types = const {
@ -30,14 +35,14 @@ class TypeScriptDefinitionBuilder implements Builder {
if (isListModelType(type)) { if (isListModelType(type)) {
var arg = await compileToTypeScriptType( var arg = await compileToTypeScriptType(
ctx, fieldName, type.typeArguments[0], ext, buildStep); ctx, fieldName, type.typeArguments[0], refs, ext, buildStep);
typeScriptType = '$arg[]'; typeScriptType = '$arg[]';
} else if (const TypeChecker.fromRuntime(Map).isAssignableFromType(type) && } else if (const TypeChecker.fromRuntime(Map).isAssignableFromType(type) &&
type.typeArguments.length == 2) { type.typeArguments.length == 2) {
var key = await compileToTypeScriptType( var key = await compileToTypeScriptType(
ctx, fieldName, type.typeArguments[0], ext, buildStep); ctx, fieldName, type.typeArguments[0], refs, ext, buildStep);
var value = await compileToTypeScriptType( var value = await compileToTypeScriptType(
ctx, fieldName, type.typeArguments[1], ext, buildStep); ctx, fieldName, type.typeArguments[1], refs, ext, buildStep);
//var modelType = type.typeArguments[1]; //var modelType = type.typeArguments[1];
/*var innerCtx = await buildContext( /*var innerCtx = await buildContext(
modelType.element, modelType.element,
@ -63,10 +68,26 @@ class TypeScriptDefinitionBuilder implements Builder {
typeScriptType = 'any[]'; typeScriptType = 'any[]';
else { else {
var arg = await compileToTypeScriptType( var arg = await compileToTypeScriptType(
ctx, fieldName, type.typeArguments[0], ext, buildStep); ctx, fieldName, type.typeArguments[0], refs, ext, buildStep);
typeScriptType = '$arg[]'; typeScriptType = '$arg[]';
} }
} else if (isModelClass(type)) { } else if (isModelClass(type)) {
var sourcePath = buildStep.inputId.uri.toString();
var targetPath = type.element.source.uri.toString();
if (!p.equals(sourcePath, targetPath)) {
//var relative = p.relative(targetPath, from: sourcePath);
var relative = (p.dirname(targetPath) == p.dirname(sourcePath))
? p.basename(targetPath)
: p.relative(targetPath, from: sourcePath);
var parent = p.dirname(relative);
var filename =
p.setExtension(p.basenameWithoutExtension(relative), '.d.ts');
relative = p.joinAll(p.split(parent).toList()..add(filename));
var ref = '/// <reference path="$relative" />';
if (!refs.contains(ref)) refs.add(ref);
}
var ctx = await buildContext( var ctx = await buildContext(
type.element, type.element,
new ConstantReader( new ConstantReader(
@ -122,6 +143,7 @@ class TypeScriptDefinitionBuilder implements Builder {
if (contexts.isEmpty) return; if (contexts.isEmpty) return;
var refs = <String>[];
var buf = new CodeBuffer( var buf = new CodeBuffer(
trailingNewline: true, trailingNewline: true,
sourceUrl: buildStep.inputId.uri, sourceUrl: buildStep.inputId.uri,
@ -148,11 +170,10 @@ class TypeScriptDefinitionBuilder implements Builder {
var alias = ctx.resolveFieldName(field.name); var alias = ctx.resolveFieldName(field.name);
var typeScriptType = await compileToTypeScriptType( var typeScriptType = await compileToTypeScriptType(
ctx, field.name, field.type, ext, buildStep); ctx, field.name, field.type, refs, ext, buildStep);
// foo: string; // foo: string;
if (!ctx.requiredFields.containsKey(field.name)) if (!ctx.requiredFields.containsKey(field.name)) alias += '?';
alias += '?';
buf.writeln('$alias: $typeScriptType;'); buf.writeln('$alias: $typeScriptType;');
} }
@ -168,10 +189,13 @@ class TypeScriptDefinitionBuilder implements Builder {
//buf //buf
// ..outdent() // ..outdent()
// ..writeln('}'); // ..writeln('}');
var finalBuf = new CodeBuffer();
refs.forEach(finalBuf.writeln);
buf.copyInto(finalBuf);
buildStep.writeAsString( buildStep.writeAsString(
buildStep.inputId.changeExtension('.d.ts'), buildStep.inputId.changeExtension('.d.ts'),
buf.toString(), finalBuf.toString(),
); );
} }
} }

View file

@ -91,6 +91,15 @@ main() {
expect(library.copyWith(), library); expect(library.copyWith(), library);
}); });
test('required fields fromMap', () {
expect(() => AuthorSerializer.fromMap({}), throwsFormatException);
});
test('required fields toMap', () {
var author = new Author(name: null, age: 24);
expect(() => author.toJson(), throwsFormatException);
});
group('deserialization', () { group('deserialization', () {
test('deserialization sets proper fields', () { test('deserialization sets proper fields', () {
var book = BookSerializer.fromMap(deathlyHallowsMap); var book = BookSerializer.fromMap(deathlyHallowsMap);

View file

@ -1,3 +1,4 @@
/// <reference path="./book.d.ts" />
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
interface Library { interface Library {
id?: string; id?: string;