Skip to content

Commit

Permalink
Refactor Actions API (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
lesleysin authored Nov 19, 2024
1 parent 20c4fac commit bc9ba2a
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 59 deletions.
179 changes: 123 additions & 56 deletions lib/src/driver_api/action.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import 'package:duit_kernel/src/driver_api/dependency.dart';
import 'package:duit_kernel/src/driver_api/event.dart';
import 'package:duit_kernel/src/driver_api/parser.dart';

/// Represents the metadata for an HTTP action.
///
/// The [HttpActionMetainfo] class contains information about the HTTP method to be used for the action.
Expand All @@ -23,55 +27,73 @@ final class DuitScript {
required this.meta,
});

static DuitScript? fromJson(Map<String, dynamic>? json) {
if (json == null) return null;

factory DuitScript.fromJson(Map<String, dynamic> json) {
return DuitScript(
sourceCode: json["sourceCode"] ?? "",
functionName: json["functionName"] ?? "",
sourceCode: json["sourceCode"],
functionName: json["functionName"],
meta: json["meta"],
);
}
}

/// Represents a dependency for a server action.
///
/// The [ActionDependency] class contains information about the dependency target and ID.
final class ActionDependency {
/// The ID of the dependency.
String id;
extension type ActionJsonView(Map<String, dynamic> json) {
Iterable<ActionDependency> get dependsOn {
final hasProperty = json.containsKey("dependsOn");
if (hasProperty) {
return json["dependsOn"].map((el) => ActionDependency.fromJson(el));
} else {
return [];
}
}

/// Name of the target property at resulting object.
String target;
String get eventName {
final hasProperty = json.containsKey("event");
if (hasProperty) {
return json["event"];
} else {
return "";
}
}

ActionDependency({
required this.target,
required this.id,
});
/// Parse helper for script model
///
/// Use this method with !
DuitScript? get script {
final hasProperty = json.containsKey("script");

if (!hasProperty) {
throw Exception(
"An action with execution type 2 (script action) was created, but the script model is missing");
} else {
final scriptData = json["script"];

if (scriptData == null ||
scriptData is! Map<String, dynamic> ||
scriptData.isEmpty) {
throw Exception(
"An action with execution type 2 (script action) was created, but the script model is missing");
}
}

/// Creates an instance of [ActionDependency] from a JSON map.
factory ActionDependency.fromJSON(Map<String, dynamic> json) {
return ActionDependency(
target: json["target"],
id: json["id"],
);
return DuitScript.fromJson(json["script"]);
}

int get executionType {
final hasProperty = json.containsKey("executionType");
if (hasProperty) {
return json["executionType"];
} else {
return 0;
}
}
}

/// Represents a server action.
///
/// The [ServerAction] class encapsulates information about a server action, including its dependencies, event, and metadata.
final class ServerAction {
base class ServerAction implements Parser<ServerAction> {
/// The list of dependencies for the server action.
final List<ActionDependency> dependsOn;
final Iterable<ActionDependency> dependsOn;

/// The event associated with the server action.
final String event;

/// The event associated with the server action.
final HttpActionMetainfo? meta;

final DuitScript? script;
final String eventName;

/// Event execution type
///
Expand All @@ -82,35 +104,80 @@ final class ServerAction {
/// 2 - script
final int executionType;

/// Optional action payload for local execution
final Map<String, dynamic>? payload;

ServerAction({
required this.event,
required this.eventName,
required this.executionType,
this.dependsOn = const [],
this.meta,
this.script,
this.payload,
});

factory ServerAction.fromJson(Map<String, dynamic> json) {
final List<ActionDependency> deps = [];
@override
ServerAction parse(Map<String, dynamic> json) {
final view = ActionJsonView(json);

if (json["dependsOn"] != null) {
json["dependsOn"].forEach((el) {
final it = ActionDependency.fromJSON(el);
deps.add(it);
});
}
return switch (view.executionType) {
0 => TransportAction.fromJson(json),
1 => LocalAction.fromJson(json),
2 => ScriptAction.fromJson(json),
_ => throw Exception("Unknown execution type ${view.executionType}"),
};
}
}

final class LocalAction extends ServerAction {
final ServerEvent event;

LocalAction({required this.event})
: super(
eventName: "local_exec",
executionType: 1,
);

factory LocalAction.fromJson(Map<String, dynamic> json) {
return LocalAction(
event: ServerEvent.parseEvent(json),
);
}
}

abstract interface class DependentAction {
final Iterable<ActionDependency> dependsOn;

DependentAction({required this.dependsOn});
}

final class TransportAction extends ServerAction implements DependentAction {
TransportAction({
required super.eventName,
required super.dependsOn,
}) : super(
executionType: 0,
);

factory TransportAction.fromJson(Map<String, dynamic> json) {
final view = ActionJsonView(json);

return TransportAction(
eventName: view.eventName,
dependsOn: view.dependsOn,
);
}
}

final class ScriptAction extends ServerAction implements DependentAction {
final DuitScript script;

ScriptAction({required this.script, required super.dependsOn})
: super(
eventName: "script",
executionType: 2,
);

factory ScriptAction.fromJson(Map<String, dynamic> json) {
final view = ActionJsonView(json);

return ServerAction(
event: json["event"] ?? "",
executionType: json["executionType"],
dependsOn: deps,
meta: HttpActionMetainfo.fromJson(json["meta"]),
script: DuitScript.fromJson(json["script"]),
payload: json["payload"],
return ScriptAction(
script: view.script!,
dependsOn: view.dependsOn,
);
}
}
23 changes: 23 additions & 0 deletions lib/src/driver_api/dependency.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/// Represents a dependency for a server action.
///
/// The [ActionDependency] class contains information about the dependency target and ID.
final class ActionDependency {
/// The ID of the dependency.
String id;

/// Name of the target property at resulting object.
String target;

ActionDependency({
required this.target,
required this.id,
});

/// Creates an instance of [ActionDependency] from a JSON map.
factory ActionDependency.fromJson(Map<String, dynamic> json) {
return ActionDependency(
target: json["target"],
id: json["id"],
);
}
}
18 changes: 18 additions & 0 deletions lib/src/driver_api/event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

import 'package:duit_kernel/src/driver_api/parser.dart';

base class ServerEvent {
static late Parser<ServerEvent> _eventParser;

static set eventParser(Parser<ServerEvent> value) {
_eventParser = value;
}

final String type;

ServerEvent({required this.type});

static ServerEvent parseEvent(Map<String, dynamic> json) {
return _eventParser.parse(json);
}
}
3 changes: 3 additions & 0 deletions lib/src/driver_api/parser.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
abstract interface class Parser<T> {
T parse(Map<String, dynamic> json);
}
8 changes: 6 additions & 2 deletions lib/src/view_attributes/view_attribute.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import '../index.dart';
/// The [ViewAttribute] class is used to wrap view attributes,
/// providing a convenient way to access and manipulate them.
final class ViewAttribute<T> {
static late AttributeParserBase attributeParser;
static late AttributeParserBase _attributeParser;

static set attributeParser(AttributeParserBase value) {
_attributeParser = value;
}

/// The unique identifier of the view.
final String id;
Expand Down Expand Up @@ -44,7 +48,7 @@ final class ViewAttribute<T> {
String? tag, {
String? id,
}) {
return attributeParser.parse<R>(
return _attributeParser.parse<R>(
type,
json,
tag,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version: 2.1.1
repository: https://github.com/lesleysin/duit_kernel

environment:
sdk: '>=3.2.3 <4.0.0'
sdk: '>=3.4.4 <4.0.0'
flutter: ">=1.17.0"

dependencies:
Expand Down

0 comments on commit bc9ba2a

Please sign in to comment.