refactor: split terminal models

This commit is contained in:
Udhay-Adithya
2025-09-10 12:55:42 +05:30
parent 20982b93a6
commit 3bb9fb2531
9 changed files with 182 additions and 6 deletions

View File

@@ -3,6 +3,7 @@ import 'package:apidash_design_system/apidash_design_system.dart';
import 'package:apidash_core/apidash_core.dart'; import 'package:apidash_core/apidash_core.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// Terminal enums moved here from models to avoid circular imports and simplify usage
const kDiscordUrl = "https://bit.ly/heyfoss"; const kDiscordUrl = "https://bit.ly/heyfoss";
const kGitUrl = "https://github.com/foss42/apidash"; const kGitUrl = "https://github.com/foss42/apidash";
@@ -85,6 +86,15 @@ enum HistoryRetentionPeriod {
final IconData icon; final IconData icon;
} }
/// Source category of a terminal entry
enum TerminalSource { network, js, system }
/// Severity level of a terminal entry
enum TerminalLevel { debug, info, warn, error }
/// Phase of a network log lifecycle
enum NetworkPhase { started, progress, completed, failed }
enum ItemMenuOption { enum ItemMenuOption {
edit("Rename"), edit("Rename"),
delete("Delete"), delete("Delete"),

View File

@@ -2,4 +2,4 @@ export 'history_meta_model.dart';
export 'history_request_model.dart'; export 'history_request_model.dart';
export 'request_model.dart'; export 'request_model.dart';
export 'settings_model.dart'; export 'settings_model.dart';
export 'terminal_models.dart'; export 'terminal/models.dart';

View File

@@ -0,0 +1,15 @@
class JsLogData {
JsLogData({
required this.level,
required this.args,
this.stack,
this.context,
this.contextRequestId,
});
final String level; // log | warn | error | fatal
final List<String> args;
final String? stack;
final String? context; // preRequest | postResponse | global
final String? contextRequestId;
}

View File

@@ -0,0 +1,4 @@
export 'network_log_data.dart';
export 'js_log_data.dart';
export 'system_log_data.dart';
export 'terminal_entry.dart';

View File

@@ -0,0 +1,82 @@
import 'package:apidash/consts.dart';
import 'package:apidash_core/apidash_core.dart' show APIType, HTTPVerb;
class NetworkLogData {
NetworkLogData({
required this.phase,
required this.apiType,
required this.method,
required this.url,
this.requestHeaders,
this.requestBodyPreview,
this.responseStatus,
this.responseHeaders,
this.responseBodyPreview,
this.duration,
this.isStreaming = false,
this.sentAt,
this.completedAt,
this.errorMessage,
List<BodyChunk>? chunks,
}) : chunks = chunks ?? <BodyChunk>[];
final NetworkPhase phase;
final APIType apiType;
final HTTPVerb method;
final String url;
final Map<String, String>? requestHeaders;
final String? requestBodyPreview;
final int? responseStatus;
final Map<String, String>? responseHeaders;
final String? responseBodyPreview;
final Duration? duration;
final bool isStreaming;
final DateTime? sentAt;
final DateTime? completedAt;
final String? errorMessage;
final List<BodyChunk> chunks;
NetworkLogData copyWith({
NetworkPhase? phase,
APIType? apiType,
HTTPVerb? method,
String? url,
Map<String, String>? requestHeaders,
String? requestBodyPreview,
int? responseStatus,
Map<String, String>? responseHeaders,
String? responseBodyPreview,
Duration? duration,
bool? isStreaming,
DateTime? sentAt,
DateTime? completedAt,
String? errorMessage,
List<BodyChunk>? chunks,
}) {
return NetworkLogData(
phase: phase ?? this.phase,
apiType: apiType ?? this.apiType,
method: method ?? this.method,
url: url ?? this.url,
requestHeaders: requestHeaders ?? this.requestHeaders,
requestBodyPreview: requestBodyPreview ?? this.requestBodyPreview,
responseStatus: responseStatus ?? this.responseStatus,
responseHeaders: responseHeaders ?? this.responseHeaders,
responseBodyPreview: responseBodyPreview ?? this.responseBodyPreview,
duration: duration ?? this.duration,
isStreaming: isStreaming ?? this.isStreaming,
sentAt: sentAt ?? this.sentAt,
completedAt: completedAt ?? this.completedAt,
errorMessage: errorMessage ?? this.errorMessage,
chunks: chunks ?? this.chunks,
);
}
}
class BodyChunk {
BodyChunk({required this.ts, required this.text, required this.sizeBytes});
final DateTime ts;
final String text; // preview text (could be partial)
final int sizeBytes;
}

View File

@@ -0,0 +1,6 @@
class SystemLogData {
SystemLogData({required this.category, required this.message, this.stack});
final String category; // ui | provider | io | storage | unknown
final String message;
final String? stack;
}

View File

@@ -0,0 +1,55 @@
import 'package:apidash/consts.dart';
import 'network_log_data.dart';
import 'js_log_data.dart';
import 'system_log_data.dart';
class TerminalEntry {
TerminalEntry({
required this.id,
required this.ts,
required this.source,
required this.level,
this.requestId,
this.correlationId,
this.tags = const <String>[],
this.network,
this.js,
this.system,
});
final String id;
final DateTime ts;
final TerminalSource source;
final TerminalLevel level;
final String? requestId; // App request id for correlation
final String? correlationId; // Additional correlation if any
final List<String> tags;
final NetworkLogData? network;
final JsLogData? js;
final SystemLogData? system;
TerminalEntry copyWith({
DateTime? ts,
TerminalSource? source,
TerminalLevel? level,
String? requestId,
String? correlationId,
List<String>? tags,
NetworkLogData? network,
JsLogData? js,
SystemLogData? system,
}) {
return TerminalEntry(
id: id,
ts: ts ?? this.ts,
source: source ?? this.source,
level: level ?? this.level,
requestId: requestId ?? this.requestId,
correlationId: correlationId ?? this.correlationId,
tags: tags ?? this.tags,
network: network ?? this.network,
js: js ?? this.js,
system: system ?? this.system,
);
}
}

View File

@@ -1,7 +1,8 @@
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:apidash_core/apidash_core.dart'; import 'package:apidash_core/apidash_core.dart';
import '../models/terminal_models.dart'; import '../models/terminal/models.dart';
import '../consts.dart';
final terminalStateProvider = final terminalStateProvider =
StateNotifierProvider<TerminalController, TerminalState>((ref) { StateNotifierProvider<TerminalController, TerminalState>((ref) {

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../models/terminal_models.dart'; import '../../models/terminal/models.dart';
import '../../consts.dart';
import '../../providers/terminal_providers.dart'; import '../../providers/terminal_providers.dart';
class TerminalPage extends ConsumerWidget { class TerminalPage extends ConsumerWidget {
@@ -23,9 +24,11 @@ class TerminalPage extends ConsumerWidget {
final icon = _iconFor(e); final icon = _iconFor(e);
return ListTile( return ListTile(
leading: Icon(icon), leading: Icon(icon),
title: Text(title, maxLines: 1, overflow: TextOverflow.ellipsis), title: SelectableText(title, maxLines: 1),
subtitle: Text(subtitle ?? '', subtitle: SelectableText(
maxLines: 2, overflow: TextOverflow.ellipsis), subtitle ?? '',
maxLines: 2,
),
dense: true, dense: true,
); );
}, },