Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,312 changes: 2,312 additions & 0 deletions apps/cli/lib/src/openapi/ast/openapi_ast.dart

Large diffs are not rendered by default.

6,535 changes: 6,535 additions & 0 deletions apps/cli/lib/src/openapi/ast/openapi_ast.g.dart

Large diffs are not rendered by default.

444 changes: 444 additions & 0 deletions apps/cli/lib/src/openapi/ast/openapi_reference.dart

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions apps/cli/lib/src/openapi/ast/openapi_visitor.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import 'package:celest_cli/src/openapi/ast/openapi_ast.dart';

abstract class OpenApiVisitor<R> {
R visitDocument(OpenApiDocument document);
R visitInfo(OpenApiInfo info);
R visitServer(OpenApiServer server);
R visitServerVariable(OpenApiServerVariable serverVariable);
R visitPathItem(OpenApiPathItem pathItem);
R visitOperation(OpenApiOperation operation);
R visitParameter(OpenApiParameter parameter);
R visitMediaType(OpenApiMediaType mediaType);
R visitRequestBody(OpenApiRequestBody requestBody);
R visitEncoding(OpenApiEncoding encoding);
R visitResponse(OpenApiResponse response);
R visitHeader(OpenApiHeader header);
R visitComponents(OpenApiComponents components);
R visitComponent(OpenApiComponent component) => switch (component) {
OpenApiPathItem() => visitPathItem(component),
OpenApiParameter() => visitParameter(component),
OpenApiRequestBody() => visitRequestBody(component),
OpenApiResponse() => visitResponse(component),
OpenApiHeader() => visitHeader(component),
OpenApiSchema() => visitSchema(component),
OpenApiSecurityScheme() => visitSecurityScheme(component),
};
R visitSchema(OpenApiSchema schema);
R visitSecurityRequirement(OpenApiSecurityRequirement securityRequirement);
R visitSecurityScheme(OpenApiSecurityScheme securityScheme);
R visitOAuthFlows(OpenApiOAuthFlows oauthFlows);
R visitOAuthFlow(OpenApiOAuthFlow oauthFlow);
R visitAdditionalProperties(OpenApiAdditionalProperties additionalProperties);
R visitDiscriminator(OpenApiDiscriminator discriminator);
R visitReference(OpenApiReference reference);
R visitExternalDocs(OpenApiExternalDocs externalDocs);
R visitTag(OpenApiTag tag);
R visitContact(OpenApiContact contact);
R visitLicense(OpenApiLicense license);
}

abstract class OpenApiVisitorWithArg<R, A> {
R visitDocument(OpenApiDocument document, A arg);
R visitInfo(OpenApiInfo info, A arg);
R visitServer(OpenApiServer server, A arg);
R visitServerVariable(OpenApiServerVariable serverVariable, A arg);
R visitPathItem(OpenApiPathItem pathItem, A arg);
R visitOperation(OpenApiOperation operation, A arg);
R visitParameter(OpenApiParameter parameter, A arg);
R visitMediaType(OpenApiMediaType mediaType, A arg);
R visitRequestBody(OpenApiRequestBody requestBody, A arg);
R visitEncoding(OpenApiEncoding encoding, A arg);
R visitResponse(OpenApiResponse response, A arg);
R visitHeader(OpenApiHeader header, A arg);
R visitComponents(OpenApiComponents components, A arg);
R visitComponent(OpenApiComponent component, A arg) => switch (component) {
OpenApiPathItem() => visitPathItem(component, arg),
OpenApiParameter() => visitParameter(component, arg),
OpenApiRequestBody() => visitRequestBody(component, arg),
OpenApiResponse() => visitResponse(component, arg),
OpenApiHeader() => visitHeader(component, arg),
OpenApiSchema() => visitSchema(component, arg),
OpenApiSecurityScheme() => visitSecurityScheme(component, arg),
};
R visitSchema(OpenApiSchema schema, A arg);
R visitSecurityRequirement(
OpenApiSecurityRequirement securityRequirement,
A arg,
);
R visitSecurityScheme(OpenApiSecurityScheme securityScheme, A arg);
R visitOAuthFlows(OpenApiOAuthFlows oauthFlows, A arg);
R visitOAuthFlow(OpenApiOAuthFlow oauthFlow, A arg);
R visitAdditionalProperties(
OpenApiAdditionalProperties additionalProperties,
A arg,
);
R visitDiscriminator(OpenApiDiscriminator discriminator, A arg);
R visitReference(OpenApiReference reference, A arg);
R visitExternalDocs(OpenApiExternalDocs externalDocs, A arg);
R visitTag(OpenApiTag tag, A arg);
R visitContact(OpenApiContact contact, A arg);
R visitLicense(OpenApiLicense license, A arg);
}
60 changes: 60 additions & 0 deletions apps/cli/lib/src/openapi/loader/openapi_loader.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'package:celest_cli/src/openapi/ast/openapi_ast.dart';
import 'package:celest_cli/src/openapi/loader/openapi_v3_loader.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';

final _versionPattern = RegExp(r'^(\d)\.(\d)(?:\.(\d))?$');

final class OpenApiDocumentLoader {
OpenApiDocumentLoader();

OpenApiDocument load({
required String jsonOrYaml,
required Uri sourceUri,
}) {
return loadOpenApiDocument(
jsonOrYaml,
sourceUri: sourceUri,
);
}
}

OpenApiDocument loadOpenApiDocument(
String jsonOrYaml, {
required Uri sourceUri,
}) {
final document = loadYamlDocument(jsonOrYaml, sourceUrl: sourceUri);
final root = document.contents as YamlMap;

final version = (root.nodes['swagger'] ?? root.nodes['openapi'])?.value;
if (version == null || version is! String) {
throw Exception('Could not detect OpenAPI version');
}

final semverMatch = _versionPattern.firstMatch(version);
final majorVersion = switch (semverMatch?.group(1)) {
final match? => int.tryParse(match),
null => null,
};
final minorVersion = switch (semverMatch?.group(2)) {
final match? => int.tryParse(match),
null => 0,
};
final patchVersion = switch (semverMatch?.group(3)) {
final match? => int.tryParse(match),
null => 0,
};
if (majorVersion == null || minorVersion == null || patchVersion == null) {
throw Exception('Invalid OpenAPI version string: $version');
}
final semver = Version(
majorVersion,
minorVersion,
patchVersion,
);
return switch (majorVersion) {
3 => OpenApiV3Loader(version: semver, rootNode: root).load(),
2 => throw Exception('OpenAPI 2.0 is not supported'),
_ => throw Exception('Unknown OpenAPI version: $version'),
};
}
Loading