Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Commit

Permalink
generate queries option
Browse files Browse the repository at this point in the history
  • Loading branch information
vasilich6107 committed Apr 1, 2022
1 parent 081b0d5 commit e0ab11a
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 53 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

- operation name constant

## 7.6.2-beta

- generate_queries flag to signify if query documents and operation names should be generated

## 7.6.1-beta

- operation name constant

## 7.6.0-beta

- package updates
Expand Down
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,20 @@ targets:

> ⚠️ Make sure your configuration file is called `build.yaml` (with `.yaml` extension, not `.yml`)!
| Option | Default value | Description |
| - | - | - |
| `generate_helpers` | `true` | If Artemis should generate query/mutation helper GraphQLQuery subclasses. |
| `scalar_mapping` | `[]` | Mapping of GraphQL and Dart types. See [Custom scalars](#custom-scalars). |
| `schema_mapping` | `[]` | Mapping of queries and which schemas they will use for code generation. See [Schema mapping](#schema-mapping). |
| `fragments_glob` | `null` | Import path to the file implementing fragments for all queries mapped in schema_mapping. If it's assigned, fragments defined in schema_mapping will be ignored. |
| `ignore_for_file` | `[]` | The linter rules to ignore for artemis generated files. |

It's important to remember that, by default, [build](https://github.com/dart-lang/build) will follow [Dart's package layout conventions](https://dart.dev/tools/pub/package-layout), meaning that only some folders will be considered to parse the input files. So, if you want to reference files from a folder other than `lib/`, make sure you've included it on `sources`:
| Option | Default value | Description | | - | - | - | | `generate_helpers` | `true` | If Artemis should generate
query/mutation helper GraphQLQuery subclasses. | | `generate_queries` | `true` | If Artemis should generate query
documents and operation names. If you are using Artemis with `graphql` library it is useful to have those queries and
operation names generated but without Atremis specific classes to exclude Artemis from dependancies | | `scalar_mapping`
| `[]` | Mapping of GraphQL and Dart types. See [Custom scalars](#custom-scalars). | | `schema_mapping` | `[]` | Mapping
of queries and which schemas they will use for code generation. See [Schema mapping](#schema-mapping). |
| `fragments_glob` | `null` | Import path to the file implementing fragments for all queries mapped in schema_mapping.
If it's assigned, fragments defined in schema_mapping will be ignored. | | `ignore_for_file` | `[]` | The linter rules
to ignore for artemis generated files. |

It's important to remember that, by default, [build](https://github.com/dart-lang/build) will
follow [Dart's package layout conventions](https://dart.dev/tools/pub/package-layout), meaning that only some folders
will be considered to parse the input files. So, if you want to reference files from a folder other than `lib/`, make
sure you've included it on `sources`:
```yaml
targets:
$default:
Expand Down
1 change: 1 addition & 0 deletions lib/generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ Iterable<QueryDefinition> generateDefinitions({
],
inputs: visitor.context.inputsClasses,
generateHelpers: options.generateHelpers,
generateQueries: options.generateQueries,
suffix: suffix,
);
});
Expand Down
11 changes: 11 additions & 0 deletions lib/generator/data/query_definition.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class QueryDefinition extends Definition with DataPrinter {
/// If instances of [GraphQLQuery] should be generated.
final bool generateHelpers;

/// If query documents and operation names should be generated
final bool generateQueries;

/// The suffix of generated [GraphQLQuery] classes.
final String suffix;

Expand All @@ -34,13 +37,21 @@ class QueryDefinition extends Definition with DataPrinter {
this.classes = const [],
this.inputs = const [],
this.generateHelpers = false,
this.generateQueries = false,
this.suffix = 'Query',
}) : assert(hasValue(operationName)),
super(name: name);

/// class name for helper classes
String? get className => ClassName(name: operationName).namePrintable;

/// name for document constant
String get documentName => '$className${suffix}Document';

/// name for document operation name constant
String get documentOperationName =>
'$className${suffix}DocumentOperationName';

@override
Map<String, Object?> get namedProps => {
'name': name,
Expand Down
87 changes: 46 additions & 41 deletions lib/generator/print_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -275,16 +275,24 @@ Spec generateArgumentClassSpec(QueryDefinition definition) {
);
}

Spec generateQuerySpec(QueryDefinition definition) {
return Block((b) => b
..statements.addAll([
Code(
"final ${definition.documentOperationName.constantCase} = '${definition.operationName}';"),
Code('final ${definition.documentName.constantCase} = '),
dart.fromNode(definition.document).code,
Code(';'),
]));
}

/// Generates a [Spec] of a query/mutation class.
List<Spec> generateQueryClassSpec(QueryDefinition definition) {
Spec generateQueryClassSpec(QueryDefinition definition) {
final typeDeclaration = definition.inputs.isEmpty
? '${definition.name.namePrintable}, JsonSerializable'
: '${definition.name.namePrintable}, ${definition.className}Arguments';

final name = '${definition.className}${definition.suffix}';
final documentName = ReCase('${name}Document').constantCase;
final documentOperationName =
ReCase('${name}DocumentOperationName').constantCase;

final constructor = definition.inputs.isEmpty
? Constructor()
Expand All @@ -304,15 +312,15 @@ List<Spec> generateQueryClassSpec(QueryDefinition definition) {
..modifier = FieldModifier.final$
..type = refer('DocumentNode', 'package:gql/ast.dart')
..name = 'document'
..assignment = Code(documentName),
..assignment = Code(definition.documentName.constantCase),
),
Field(
(f) => f
..annotations.add(CodeExpression(Code('override')))
..modifier = FieldModifier.final$
..type = refer('String')
..name = 'operationName'
..assignment = Code(documentOperationName),
..assignment = Code(definition.documentOperationName.constantCase),
),
];

Expand All @@ -326,39 +334,30 @@ List<Spec> generateQueryClassSpec(QueryDefinition definition) {
));
}

return [
Block((b) => b
..statements.addAll([
Code("final $documentOperationName = '${definition.operationName}';"),
Code('final $documentName = '),
dart.fromNode(definition.document).code,
Code(';'),
])),
Class(
(b) => b
..name = name
..extend = refer('GraphQLQuery<$typeDeclaration>')
..constructors.add(constructor)
..fields.addAll(fields)
..methods.add(_propsMethod([
'document',
'operationName${definition.inputs.isNotEmpty ? ', variables' : ''}'
]))
..methods.add(Method(
(m) => m
..annotations.add(CodeExpression(Code('override')))
..returns = refer(definition.name.namePrintable)
..name = 'parse'
..requiredParameters.add(Parameter(
(p) => p
..type = refer('Map<String, dynamic>')
..name = 'json',
))
..lambda = true
..body = Code('${definition.name.namePrintable}.fromJson(json)'),
)),
)
];
return Class(
(b) => b
..name = name
..extend = refer('GraphQLQuery<$typeDeclaration>')
..constructors.add(constructor)
..fields.addAll(fields)
..methods.add(_propsMethod([
'document',
'operationName${definition.inputs.isNotEmpty ? ', variables' : ''}'
]))
..methods.add(Method(
(m) => m
..annotations.add(CodeExpression(Code('override')))
..returns = refer(definition.name.namePrintable)
..name = 'parse'
..requiredParameters.add(Parameter(
(p) => p
..type = refer('Map<String, dynamic>')
..name = 'json',
))
..lambda = true
..body = Code('${definition.name.namePrintable}.fromJson(json)'),
)),
);
}

/// Gathers and generates a [Spec] of a whole query/mutation and its
Expand Down Expand Up @@ -405,11 +404,17 @@ Spec generateLibrarySpec(LibraryDefinition definition) {
bodyDirectives.addAll(enums.map(enumDefinitionToSpec));

for (final queryDef in definition.queries) {
if (queryDef.inputs.isNotEmpty && queryDef.generateHelpers) {
if (queryDef.inputs.isNotEmpty &&
(queryDef.generateHelpers || queryDef.generateQueries)) {
bodyDirectives.add(generateArgumentClassSpec(queryDef));
}

if (queryDef.generateHelpers || queryDef.generateQueries) {
bodyDirectives.add(generateQuerySpec(queryDef));
}

if (queryDef.generateHelpers) {
bodyDirectives.addAll(generateQueryClassSpec(queryDef));
bodyDirectives.add(generateQueryClassSpec(queryDef));
}
}

Expand Down
5 changes: 5 additions & 0 deletions lib/schema/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class GeneratorOptions {
@JsonKey(defaultValue: true)
final bool generateHelpers;

/// If query documents and operation names should be generated
@JsonKey(defaultValue: true)
final bool generateQueries;

/// A list of scalar mappings.
@JsonKey(defaultValue: [])
final List<ScalarMap?> scalarMapping;
Expand All @@ -31,6 +35,7 @@ class GeneratorOptions {
/// Instantiate generator options.
GeneratorOptions({
this.generateHelpers = true,
this.generateQueries = true,
this.scalarMapping = const [],
this.fragmentsGlob,
this.schemaMapping = const [],
Expand Down
2 changes: 2 additions & 0 deletions lib/schema/options.g2.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: artemis
version: 7.6.1-beta
version: 7.6.2-beta

description: Build dart types from GraphQL schemas and queries (using Introspection Query).
homepage: https://github.com/comigor/artemis
Expand Down
44 changes: 42 additions & 2 deletions test/generator/print_helpers_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,46 @@ class TestQueryQuery extends GraphQLQuery<TestQuery, JsonSerializable> {
''');
});

test(
'When generateHelpers is false and generateQueries is true, an execute fn is generated.',
() {
final buffer = StringBuffer();
final definition = LibraryDefinition(
basename: r'test_query.graphql',
queries: [
QueryDefinition(
name: QueryName(name: 'test_query'),
operationName: 'test_query',
document: parseString('query test_query {}'),
generateHelpers: false,
generateQueries: true,
)
],
);
final ignoreForFile = <String>[];

writeLibraryDefinitionToBuffer(buffer, ignoreForFile, definition);

expect(buffer.toString(), '''// GENERATED CODE - DO NOT MODIFY BY HAND
// @dart = 2.12
import 'package:json_annotation/json_annotation.dart';
import 'package:equatable/equatable.dart';
import 'package:gql/ast.dart';
part 'test_query.graphql.g.dart';
final TEST_QUERY_QUERY_DOCUMENT_OPERATION_NAME = 'test_query';
final TEST_QUERY_QUERY_DOCUMENT = DocumentNode(definitions: [
OperationDefinitionNode(
type: OperationType.query,
name: NameNode(value: 'test_query'),
variableDefinitions: [],
directives: [],
selectionSet: SelectionSetNode(selections: []))
]);
''');
});

test('The generated execute fn could have input.', () {
final buffer = StringBuffer();
final definition =
Expand Down Expand Up @@ -621,8 +661,8 @@ class TestQueryArguments extends JsonSerializable with EquatableMixin {
suffix: 'Query',
);

final str =
generateQueryClassSpec(definition).map((e) => specToString(e)).join();
final str = specToString(generateQuerySpec(definition)) +
specToString(generateQueryClassSpec(definition));

expect(str,
r'''final TEST_QUERY_QUERY_DOCUMENT_OPERATION_NAME = 'test_query';
Expand Down
3 changes: 3 additions & 0 deletions test/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Future testGenerator({
String namingScheme = 'pathedWithTypes',
bool appendTypeName = false,
bool generateHelpers = false,
bool generateQueries = false,
Map<String, dynamic> builderOptionsMap = const {},
Map<String, Object> sourceAssetsMap = const {},
Map<String, Object> outputsMap = const {},
Expand All @@ -25,6 +26,7 @@ Future testGenerator({

final anotherBuilder = graphQLQueryBuilder(BuilderOptions({
if (!generateHelpers) 'generate_helpers': false,
if (!generateQueries) 'generate_queries': false,
'schema_mapping': [
{
'schema': 'api.schema.graphql',
Expand Down Expand Up @@ -66,6 +68,7 @@ Future testNaming({
}) {
final anotherBuilder = graphQLQueryBuilder(BuilderOptions({
'generate_helpers': false,
'generate_queries': false,
'schema_mapping': [
{
'schema': 'api.schema.graphql',
Expand Down

0 comments on commit e0ab11a

Please sign in to comment.