mirror of
https://github.com/foss42/apidash.git
synced 2025-12-01 18:28:25 +08:00
feat: add terminal state provider
This commit is contained in:
@@ -2,3 +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';
|
||||||
|
|||||||
@@ -2,5 +2,6 @@ export 'ai_providers.dart';
|
|||||||
export 'collection_providers.dart';
|
export 'collection_providers.dart';
|
||||||
export 'environment_providers.dart';
|
export 'environment_providers.dart';
|
||||||
export 'history_providers.dart';
|
export 'history_providers.dart';
|
||||||
|
export 'terminal_providers.dart';
|
||||||
export 'settings_providers.dart';
|
export 'settings_providers.dart';
|
||||||
export 'ui_providers.dart';
|
export 'ui_providers.dart';
|
||||||
|
|||||||
179
lib/providers/terminal_providers.dart
Normal file
179
lib/providers/terminal_providers.dart
Normal 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),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user