feat: add terminal state provider

This commit is contained in:
Udhay-Adithya
2025-09-07 23:48:55 +05:30
parent ef093ae5c2
commit 6db0f61321
3 changed files with 181 additions and 0 deletions

View File

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

View File

@@ -2,5 +2,6 @@ export 'ai_providers.dart';
export 'collection_providers.dart';
export 'environment_providers.dart';
export 'history_providers.dart';
export 'terminal_providers.dart';
export 'settings_providers.dart';
export 'ui_providers.dart';

View File

@@ -0,0 +1,179 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:uuid/uuid.dart';
import 'package:apidash_core/apidash_core.dart';
import '../models/terminal_models.dart';
final terminalStateProvider =
StateNotifierProvider<TerminalController, TerminalState>((ref) {
return TerminalController();
});
class TerminalState {
TerminalState({required this.entries})
: index = {
for (var i = 0; i < entries.length; i++) entries[i].id: i,
};
final List<TerminalEntry> entries; // newest first
final Map<String, int> index;
TerminalState copyWith({List<TerminalEntry>? entries}) {
return TerminalState(entries: entries ?? this.entries);
}
}
class TerminalController extends StateNotifier<TerminalState> {
TerminalController() : super(TerminalState(entries: <TerminalEntry>[]));
static const _uuid = Uuid();
String _newId() => _uuid.v4();
void clear() {
state = TerminalState(entries: <TerminalEntry>[]);
}
String append(TerminalEntry entry) {
final list = [entry, ...state.entries];
state = TerminalState(entries: list);
return entry.id;
}
void _updateById(String id, TerminalEntry Function(TerminalEntry) updater) {
final idx = state.index[id];
if (idx == null) return;
final current = state.entries[idx];
final updated = updater(current);
final list = [...state.entries];
list[idx] = updated;
state = TerminalState(entries: list);
}
// Convenience builders
String startNetwork({
required APIType apiType,
required HTTPVerb method,
required String url,
String? requestId,
Map<String, String>? requestHeaders,
String? requestBodyPreview,
bool isStreaming = false,
}) {
final id = _newId();
final entry = TerminalEntry(
id: id,
ts: DateTime.now(),
source: TerminalSource.network,
level: TerminalLevel.info,
requestId: requestId,
network: NetworkLogData(
phase: NetworkPhase.started,
apiType: apiType,
method: method,
url: url,
requestHeaders: requestHeaders,
requestBodyPreview: requestBodyPreview,
isStreaming: isStreaming,
sentAt: DateTime.now(),
),
);
append(entry);
return id;
}
void addNetworkChunk(String logId, BodyChunk chunk) {
_updateById(logId, (e) {
final n = e.network;
if (n == null) return e;
n.chunks.add(chunk);
return e.copyWith(
network: n.copyWith(phase: NetworkPhase.progress),
);
});
}
void completeNetwork(
String logId, {
int? statusCode,
Map<String, String>? responseHeaders,
String? responseBodyPreview,
Duration? duration,
}) {
_updateById(logId, (e) {
final n = e.network;
if (n == null) return e;
return e.copyWith(
level: (statusCode != null && statusCode >= 400)
? TerminalLevel.error
: TerminalLevel.info,
network: n.copyWith(
phase: NetworkPhase.completed,
responseStatus: statusCode,
responseHeaders: responseHeaders,
responseBodyPreview: responseBodyPreview,
duration: duration,
completedAt: DateTime.now(),
),
);
});
}
void failNetwork(String logId, String message) {
_updateById(logId, (e) {
final n = e.network;
if (n == null) return e;
return e.copyWith(
level: TerminalLevel.error,
network: n.copyWith(
phase: NetworkPhase.failed,
errorMessage: message,
completedAt: DateTime.now(),
),
);
});
}
void logJs({
required String level,
required List<String> args,
String? stack,
String? context,
String? contextRequestId,
}) {
append(TerminalEntry(
id: _newId(),
ts: DateTime.now(),
source: TerminalSource.js,
level: switch (level) {
'warn' => TerminalLevel.warn,
'error' || 'fatal' => TerminalLevel.error,
_ => TerminalLevel.info,
},
requestId: contextRequestId,
js: JsLogData(
level: level,
args: args,
stack: stack,
context: context,
contextRequestId: contextRequestId,
),
));
}
void logSystem({
required String category,
required String message,
String? stack,
TerminalLevel level = TerminalLevel.info,
List<String> tags = const <String>[],
}) {
append(TerminalEntry(
id: _newId(),
ts: DateTime.now(),
source: TerminalSource.system,
level: level,
tags: tags,
system: SystemLogData(category: category, message: message, stack: stack),
));
}
}