Skip to main content

tom_basics 3.3.0 copy "tom_basics: ^3.3.0" to clipboard
tom_basics: ^3.3.0 copied to clipboard

Basic utilities for the TOM framework including exception handling with UUID tracking.

tom_basics #

Part of the Tom framework by al-the-bear. © 2024–2026 Peter Nicolai Alexis Kyaw — BSD-3-Clause, see LICENSE.

Basic utilities for the Tom framework including exception handling with UUID tracking.

tom_basics is the bottom of the dependency stack. It carries the few primitives that almost every other Tom package imports — a traceable exception base, a configurable logger, a platform-abstraction layer, and a small runtime environment model — while keeping its own dependency list to just three well-known packages (uuid, stack_trace, http). Nothing here pulls in Flutter, a database, or a server framework, so it is safe to import from the most foundational corners of the codebase.


Overview #

A foundational library has one job: give the layers above it a vocabulary they can share without dragging in heavy dependencies. tom_basics provides four such vocabularies, each independent of the others:

  • Errors that can be traced across process boundaries. A TomBaseException stamps every failure with a UUID at the moment it is created. When the same error is logged on a server, surfaced in a client, and filed in a bug tracker, the UUID is the thread that ties the three sightings together. The exception also captures a terse, core-folded stack trace (via stack_trace) so the noise of the SDK internals is stripped from the report.

  • Logging you can dial up and down per class. The global tomLog instance offers nine severity methods (trace → fatal plus status) and a bitwise level model that lets you compose, subtract, and match levels. You can raise the verbosity of a single class or method without touching the global level, and you can redirect all output to a destination of your choosing by swapping one field.

  • Platform detail behind a single seam. Code that needs to know "are we on the web?" or "give me an HTTP client" talks to TomPlatformUtils.current instead of importing dart:io or dart:html. The concrete implementation is injected once at startup, so the same library code compiles and runs on console, server, mobile, and web.

  • A runtime environment model for wiring. TomEnvironment, TomPlatform, and TomRuntime describe which environment (development / test / production) and which platform (web / macos / android / …) are active, with a parent hierarchy. Higher-level Tom packages use this to select environment- and platform-specific implementations.

These four concerns share no code with each other; you can import the package and use only the logger, only the exception base, or only the platform seam.


Installation #

Add the dependency with its hosted version constraint:

dependencies:
  tom_basics: ^1.0.0

or from the command line:

dart pub add tom_basics

SDK: Dart ^3.10.0. Transitive dependencies: uuid, stack_trace, http — all pure-Dart and platform-neutral, so tom_basics itself adds no native or Flutter requirement.


Features #

Exception handling #

Capability Type / member Notes
UUID-stamped exception TomBaseException Auto-generates a UUIDv4 unless one is supplied.
Request correlation requestUuid Optional id tying an error to an inbound request.
Structured context parameters Map<String, Object?> of diagnostic values.
Cause chaining rootException The underlying error this one wraps.
Terse stack trace stackTrace, printStackTrace() Core frames folded out via stack_trace.
Creation timestamp timeStamp UTC DateTime set at construction.

Logging #

Capability Type / member Notes
Global logger tomLog Ready-to-use TomLogger singleton.
Severity methods trace debug traffic info warn status error severe fatal One method per level.
Bitwise levels TomLogLevel + - matches Compose and subtract levels.
Compound levels development extended production still silent off Named presets.
Per-name overrides addNameLevel / setLogLevelExceptions Raise verbosity for one class or method.
Level stack pushLogLevel / popLogLevel Temporary, scoped verbosity.
Pluggable output logOutput, TomLogOutput Swap in file / remote / custom sinks.
Custom rendering TomLoggable Control how your objects appear in logs.
Into the structured sink TomDiagnosticsLogOutput TomLogger lines go to a TomDiagnostics sink, so a program keeps one log.

Structured diagnostics #

Capability Type / member Notes
The sink port TomDiagnostics log(TomDiagnosticEvent).
An entry TomDiagnosticEvent Operation name, level, UTC time, JSON-shaped field map — never a rendered sentence.
Shown and logged TomDiagnosticNotice One producer emits the field map for the log and the sentence for a person.
Failures TomStructuredFailure, tomFailureFields A failure is logged by its type and structural facts, never its text.
Sinks TomNullDiagnostics, TomInMemoryDiagnostics, TomFileDiagnostics Discard; bounded ring; rolling JSON-lines file (diagnostics_io.dart).

Utilities #

Capability Type / member Notes
Cancellation TomCancellationToken, TomCancellationSource, TomOperationCancelled The first reason wins; TomCancellationToken.none never cancels.
Hash and names tomSha256Hex, tomSha256OfText, tomSlugify, tomShortId One SHA-256 for content addressing; a filename-safe slug with a fallback.
Text codec tomDecodeTextBytes, tomEncodeText, TomTextEncoding Encoding and BOM detected and written back unchanged.
Glob and gitignore TomGlob, TomGitignore, TomGitignoreSet Git's rules, including escapes and folder ancestry.
Canonical YAML tomEmitYamlDocument, tomEmitLiteralBlock, tomEmitCanonicalFragment, tomOrderedMapping, tomSortedById Deterministic output for files a program owns.
Hand-edited YAML tomYamlScalar, tomYamlEntry, tomYamlListItem, tomNewlineOf, tomYamlSchemaRefOf Key-level writes into files people also edit, and the schema such a file names.
Comment-preserving edits TomYamlConfigWriter Set and remove values without losing comments (yaml_edit).
Protected clipboard TomProtectedClipboard, TomClipboardPort, TomProtectedClipboardState A copied secret is cleared after a delay, only while the clipboard still holds it; the port is the application's (Flutter bindings in tom_reusable_ui).

Platform abstraction #

Capability Type / member Notes
Injectable singleton TomPlatformUtils.current / setCurrentPlatform One seam for all platform detail.
Environment type isDesktop isMobile isWeb Coarse-grained checks.
OS detection isWindows isLinux isMacOs isFuchsia isAndroid isIos Fine-grained checks.
Console output out / outError Platform-routed stdout / stderr.
HTTP client factory httpClient() Returns a package:http Client.
Env vars envVars / getTomEnvVars Platform-neutral configuration map.
Default fallback TomFallbackPlatformUtils Console output works; detection throws until configured.

Runtime environments and platforms #

Capability Type / member Notes
Environment model TomEnvironment Named, with optional parent + initializer.
Platform model TomPlatform Named target with an initializer hook.
Runtime registry TomRuntime Holds current env / platform + hierarchy resolution.
Platform constants platformWeb platformMacos platformWindows platformLinux platformAndroid platformIos platformFuchsia Predefined targets.
Env constants defaultTomEnvironment noTomEnvironment Defaults / sentinels.

Quick start #

import 'package:tom_basics/tom_basics.dart';

void main() {
  // The global logger is ready to use immediately.
  tomLog.setLogLevel(TomLogLevel.development);
  tomLog.info('Application starting...');

  try {
    throw TomBaseException('example.run.failed', 'Something went wrong');
  } on TomBaseException catch (e) {
    tomLog.error('Caught: ${e.key} - ${e.defaultUserMessage}');
    print('Exception UUID: ${e.uuid}'); // e.g. aceec92a-90ab-4f7b-896e-...
  }

  tomLog.info('Application finished.');
}

Running it prints (timestamps and the UUID vary per run):

2026-06-16 21:27:22.128328 - INFO    Application starting...   [main]
2026-06-16 21:27:22.140356 - ERROR   Caught: example.run.failed - Something went wrong   [main]
Exception UUID: aceec92a-90ab-4f7b-896e-595d7f1a94ca
2026-06-16 21:27:22.140927 - INFO    Application finished.   [main]

This is exactly example/tom_basics_example.dart — run it with dart run example/tom_basics_example.dart.


Example projects #

Sample Demonstrates
example/tom_basics_example.dart The 12-line quick start above: logger + tracked exception.
tom_basics_sample The full exception-handling-with-UUID-tracking model, end to end, with the logger and platform seam. (article-grade sample, seven runnable examples)

Usage #

Exception handling with UUID tracking #

The constructor takes a key (a stable, machine-readable code) and a default user message (human-readable), with everything else optional.

A key is dotted lowercase, lower_snake_case within each segment, and reads <area>.<operation>.<condition> — users.fetch.not_found, orders.submit.no_positions. The first segment names the module or subsystem, which is what keeps keys from unrelated code from colliding and lets a handler match a whole area with a prefix test. tom_core_kernel documents the convention in full; every key in the Tom framework follows it, and this package's base class is where it starts.

import 'package:tom_basics/tom_basics.dart';

void main() {
  final ex = TomBaseException(
    'users.validate.invalid_email',
    'The email address is not valid',
    parameters: {'field': 'email', 'value': 'not-an-email'},
  );

  print(ex.key);                  // users.validate.invalid_email
  print(ex.defaultUserMessage);   // The email address is not valid
  print(ex.parameters?['field']); // email
  print(ex.uuid.length);          // 36  (a UUIDv4 string)
}

Why a key and a message? The key is what your code branches on and what you grep logs for; it never changes when you reword the prose. The defaultUserMessage is the fallback text shown when no localized message is available. Keeping them separate means translators and programmers never fight over the same string.

Correlating an error with a request. Pass requestUuid so a failure deep in a handler can be matched back to the inbound call that triggered it:

TomBaseException(
  'orders.query.timeout',
  'The database did not respond in time',
  requestUuid: incomingRequestId,
  parameters: {'table': 'orders', 'timeoutMs': 5000},
);

Wrapping a lower-level error. When you catch an exception and rethrow a domain-level one, keep the original in rootException and the original trace in stack so nothing is lost:

try {
  await db.query(sql);
} catch (e, s) {
  throw TomBaseException(
    'orders.load.failed',
    'Could not load the order',
    rootException: e,
    stack: s,
  );
}

Inspecting the trace. Each exception folds out core/SDK frames at construction time and stores the result in stackTrace. Print it directly, or use printStackTrace():

try {
  throw TomBaseException('example.demo.failed', 'demo');
} on TomBaseException catch (e) {
  e.printStackTrace();      // writes "<uuid>-<requestUuid> exception stacktrace:\n..."
  // or inspect the stored string:
  print(e.stackTrace.split('\n').first); // the first non-core frame
}

Note. tom_basics deliberately stops at this minimal base class. The full-featured exception type with integrated logging lives in tom_core_kernel as TomException; reach for that when you are above the foundation layer.

Logging #

The global tomLog instance is usable without any setup. Each severity has its own method:

import 'package:tom_basics/tom_basics.dart';

void main() {
  tomLog.info('Server started on port 8080');
  tomLog.warn('Cache miss for key user:42');
  tomLog.error('Failed to connect to database');
  tomLog.debug('Request payload: {"id": 42}');
  tomLog.trace('Entering computeChecksum()');
}

Output lines carry the timestamp, isolate name, level, message, and the detected origin (the class.method that called the logger), e.g.:

2026-06-16 21:27:22.140 - INFO    Server started on port 8080   [main]

Log levels are bit patterns

A TomLogLevel is a bit mask. Individual levels can be combined with + and removed with -, and a logger only emits a message when its level matches the message level:

// Build a custom level: info plus errors, nothing else.
var quiet = TomLogLevel.info + TomLogLevel.errors;
tomLog.setLogLevel(quiet);

tomLog.info('shown');      // matches -> printed
tomLog.debug('hidden');    // no overlap -> filtered out
tomLog.error('shown');     // matches -> printed

// Subtract a level from a preset.
var prodNoInfo = TomLogLevel.production - TomLogLevel.info;
print(prodNoInfo.matches(TomLogLevel.info)); // false
print(prodNoInfo.matches(TomLogLevel.warn)); // true

Named presets cover the common cases:

Preset Includes
development everything, including trace
extended production + debug + traffic
production info + warn + errors + status
still warn + errors + status
silent errors + status only
off nothing

You can also resolve a level by name (useful for reading a level from config or an environment variable):

tomLog.setLogLevelByName('DEVELOPMENT');          // case-insensitive
final lvl = TomLogLevel.byName('SILENT');          // or null if unknown

Temporary verbosity with a level stack

To turn the volume up around one tricky section and restore it afterwards, push and pop:

tomLog.pushLogLevel(TomLogLevel.trace);
// ... noisy operations are fully traced here ...
tomLog.popLogLevel(); // back to whatever was active before

Per-class and per-method overrides

When stack-trace analysis is enabled (the default, TomLogger.globalSettingDetermineCaller == true), the logger detects which class.method emitted each message. That lets you raise verbosity for one location only:

// Trace everything in DatabaseService, debug one method of ApiClient.
tomLog.addNameLevel('DatabaseService', TomLogLevel.trace);
tomLog.addNameLevel('ApiClient.sendRequest', TomLogLevel.debug);

// Or configure several at once from a pattern string (e.g. from config):
tomLog.setLogLevelExceptions('DatabaseService=TRACE,ApiClient=DEBUG');

Redirecting output

The logger writes through logOutput, a TomLogOutput. The default is TomConsoleLogOutput (errors and status to stderr, everything else to stdout). Implement TomLogOutput.output to send logs anywhere:

class CollectingLogOutput extends TomLogOutput {
  final List<String> lines = [];

  @override
  void output(
    TomLogLevel loggerLevel,
    TomLogLevel logLevel,
    String level,
    Object message,
    String isolateName,
    DateTime timeStamp,
    String? origin,
  ) {
    if (logLevel.matches(loggerLevel)) {
      lines.add('$level ${convertToString(message)}');
    }
  }
}

void main() {
  final sink = CollectingLogOutput();
  tomLog.logOutput = sink;
  tomLog.info('captured');
  print(sink.lines); // [INFO    captured]
}

convertToString (provided by the base class) handles Strings, lazy Function messages, and TomLoggable objects automatically.

Custom log representation for your types

Implement TomLoggable so an object renders cleanly in logs without exposing internals:

class User implements TomLoggable {
  User(this.id, this.name);
  final String id;
  final String name;

  @override
  String get logRepresentation => 'User($id, $name)';
}

void main() {
  tomLog.info(User('42', 'Ada')); // logs: User(42, Ada)
}

Structured diagnostics #

A rendered log line has already interpolated whatever its caller had, and no sink downstream can tell a locator from a password. The structured port keeps the payload as data until the sink renders it, which is what lets a rule like "secrets never reach the log" hold by construction:

import 'package:tom_basics/diagnostics.dart';

final TomDiagnostics log = TomInMemoryDiagnostics();
log.log(TomDiagnosticEvent(
  operation: 'sync.commit',
  level: TomDiagnosticLevel.warn,
  fields: {'locator': 'notes/a.md', 'status': 409},
));

Three entry points, by what they pull in:

  • package:tom_basics/diagnostics.dart — the port, the events, notices and failure fields, the null and in-memory sinks. Imports nothing, so a web-linkable or dependency-light package can take it.
  • package:tom_basics/diagnostics_io.dart — adds TomFileDiagnostics, a rolling JSON-lines file: one object per line, a byte ceiling checked before each append, a fixed number of generations, a settable path and level, and a value that is not JSON-shaped written as <non-JSON TypeName> rather than through toString(). A refused write stops the sink and is kept in failure, so a full disk is not a stall on every line.
  • package:tom_basics/tom_basics.dart — all of the port, plus TomDiagnosticsLogOutput, which sends TomLogger lines into a sink:
final file = TomFileDiagnostics(path: 'logs/app.log');
tomLog.logOutput = TomDiagnosticsLogOutput(file);
tomLog.warn('disk almost full'); // one JSON line, operation "log"

A TomLogger line's text is already rendered, so the bridge cannot redact it; what it keeps is the level, the time, the isolate and the sink's bounds — and a program that logs both ways has one log.

Utilities #

import 'package:tom_basics/utilities.dart';

final source = TomCancellationSource();
source.token.whenCancelled.then((reason) => print('stopped: $reason'));
source.cancel('deadline');

final ignore = TomGitignoreSet()
  ..add(TomGitignore.parse('', 'build/\n*.log\n!keep.log\n'));
ignore.isIgnored('build/out/app.js', isDirectory: false); // true

tomSlugify('Chapter 2: Design'); // chapter-2-design
tomEmitYamlDocument({'title': 'Fix: the parser'}); // title: "Fix: the parser"

utilities.dart imports no dart:io and no HTTP stack. The two YAML styles are deliberate: the canonical emitter is for files a program owns and always writes the same bytes; the hand-edited style changes only the keys it is asked to change in a file a person also edits. tomYamlToPlain reads either kind back as plain maps, lists and scalars.

Platform abstraction #

Library code that must not import dart:io or dart:html directly talks to TomPlatformUtils.current. The concrete implementation is injected once at startup. Until you do that, the default TomFallbackPlatformUtils supports console output but throws UnimplementedError for detection — a loud, deliberate signal that the platform was never configured:

import 'package:tom_basics/tom_basics.dart';

// A Linux console/server implementation. Extending TomFallbackPlatformUtils
// gives working out/outError; we override every detection method so that
// TomRuntime.initializePlatform() (which probes them all) also works.
class ConsolePlatformUtils extends TomFallbackPlatformUtils {
  @override
  bool isDesktop() => true;
  @override
  bool isMobile() => false;
  @override
  bool isWeb() => false;
  @override
  bool isWindows() => false;
  @override
  bool isLinux() => true;
  @override
  bool isMacOs() => false;
  @override
  bool isFuchsia() => false;
  @override
  bool isAndroid() => false;
  @override
  bool isIos() => false;
}

void main() {
  TomPlatformUtils.setCurrentPlatform(ConsolePlatformUtils());

  final p = TomPlatformUtils.current;
  print(p.isDesktop()); // true
  print(p.isLinux());   // true
  p.out('hello from the platform seam'); // prints to stdout
}

A stub that overrides only isDesktop/isMobile/isWeb is enough for those three checks, but TomRuntime.initializePlatform() (below) probes the full set of OS methods — so a complete implementation like the one above is what makes detection work end to end. In real apps you don't write this yourself: tom_basics_console ships the desktop/server implementation and tom_core_flutter ships the Flutter one. The seam is what lets the same upstream code run on both.

The same singleton also hands out an HTTP client and a configuration map:

// Configuration that travels with the platform, not the call site.
TomPlatformUtils.envVars['API_BASE'] = 'https://api.example.com';
print(TomPlatformUtils.current.getTomEnvVars()['API_BASE']);
// https://api.example.com

// A platform-appropriate http client (once a real platform is configured):
// final client = TomPlatformUtils.current.httpClient();
// final res = await client.get(Uri.parse('https://api.example.com/health'));

Runtime environments and platforms #

The runtime model answers "which environment and platform are active, and what is the chain of fallbacks?" Register environments, pick the current one, and walk the hierarchy:

import 'package:tom_basics/tom_basics.dart';

void main() {
  final prod = TomRuntime.addEnvironment(const TomEnvironment('production'));
  TomRuntime.addEnvironment(
    TomEnvironment('staging', parent: prod),
  );

  TomRuntime.setCurrentEnvironment('staging');
  print(TomRuntime.getCurrentEnvironment().env); // staging

  // Root-to-current chain, used by higher layers to resolve fallbacks.
  final chain = TomRuntime.getEnvironmentHierarchy().map((e) => e.env).toList();
  print(chain); // [production, staging]
}

An environment may carry an initializer that runs when it is activated:

final dev = TomEnvironment(
  'development',
  isDevelopment: true,
  initializer: (env) => tomLog.info('Activated ${env.env}'),
);
dev.initialize(); // logs: Activated development

Platform detection ties the platform seam to the runtime registry. Once a real TomPlatformUtils is configured, initializePlatform() detects and records the current platform:

TomPlatformUtils.setCurrentPlatform(ConsolePlatformUtils());
TomRuntime.setCurrentEnvironment('production');
TomRuntime.initializePlatform();
print(TomRuntime.printReport());
// TomRuntime: Platform TomPlatform: linux Root Environment ... Current Environment ...

Architecture #

tom_basics is a set of small, independent modules behind a single barrel export (lib/tom_basics.dart):

                       package:tom_basics/tom_basics.dart
                                     │  (barrel export)
        ┌──────────────┬─────────────┼──────────────────┐
        │              │             │                  │
 ┌──────┴──────┐ ┌─────┴──────┐ ┌────┴─────────┐ ┌──────┴────────────┐
 │ exceptions/ │ │ logging/   │ │ runtime/     │ │ runtime/          │
 │ exception_  │ │ logging.   │ │ platform_    │ │ platform_         │
 │ base.dart   │ │ dart       │ │ neutral.dart │ │ environment_      │
 │             │ │            │ │              │ │ runtime.dart      │
 │ TomBase     │ │ TomLogger  │ │ TomPlatform  │ │ TomEnvironment    │
 │ Exception   │ │ TomLogLevel│ │ Utils        │ │ TomPlatform       │
 │             │ │ TomLogOut  │ │ (+ fallback) │ │ TomRuntime        │
 └─────────────┘ └─────┬──────┘ └──────┬───────┘ └───────────────────┘
   uuid,                │  uses         │ uses
   stack_trace          └───────────────┘
                     (logging routes its console
                      output through the platform seam)

The only internal coupling is that logging writes through the platform seam (TomConsoleLogOutput calls TomPlatformUtils.current.out/outError) and reads the isolate name from it. Exceptions and the environment model stand alone.

Two further modules have entry points of their own and depend on nothing else in the package: diagnostics/ (diagnostics.dart, with the file sink in diagnostics_io.dart) and utilities/ (utilities.dart). The barrel re-exports both.

Key types #

Type Responsibility
TomBaseException Minimal exception base with UUID, timestamp, params, cause, and folded stack trace.
TomLogger The logger: severity methods, level + per-name configuration, output dispatch.
tomLog The global TomLogger instance.
TomLogLevel Bitwise log-level value with +, -, matches, and named presets.
TomLogOutput Abstract log sink; TomConsoleLogOutput is the default stdout/stderr impl.
TomLoggable Interface for objects that supply their own logRepresentation.
TomDiagnostics Structured sink port; TomNullDiagnostics, TomInMemoryDiagnostics, TomFileDiagnostics.
TomDiagnosticEvent / TomDiagnosticNotice A structured entry; a finding that is both logged and shown.
TomDiagnosticsLogOutput TomLogOutput that writes TomLogger lines into a TomDiagnostics sink.
TomCancellationToken / TomCancellationSource Cooperative cancellation with a reason.
TomGitignoreSet Gitignore matching across several files.
TomOutputTranscript / TomOutputRecorder A bounded, interleaved stdout/stderr transcript that states how many lines it dropped.
TomYamlConfigWriter Comment-preserving YAML edits.
TomProtectedClipboard Copies a secret and clears it again through an application-bound TomClipboardPort.
TomPlatformUtils Injectable platform seam: detection, console output, HTTP client, env vars.
TomFallbackPlatformUtils Default impl: console output works, detection throws until configured.
TomEnvironment A named runtime environment with optional parent + initializer.
TomPlatform A named target platform with an initializer hook.
TomRuntime Registry of current environment/platform and hierarchy resolution.

Ecosystem #

tom_basics sits at the root of the basics layer; the rest of the framework imports it, never the other way around.

                      ┌───────────────────────────┐
                      │  tom_core_kernel / server  │   higher-level Tom packages
                      │  tom_core_flutter, d4rt …  │   (TomException, DI, …)
                      └─────────────┬──────────────┘
                                    │ depends on
        ┌────────────────┬──────────┼───────────────┐
        │                │          │               │
 ┌──────┴──────┐  ┌──────┴──────┐   │        ┌───────┴────────┐
 │ tom_basics_ │  │ tom_basics_ │   │        │  tom_crypto     │
 │ console     │  │ network     │   │        │  (uses logging) │
 │ (platform   │  │             │   │        └────────────────┘
 │  impl)      │  │             │   │
 └──────┬──────┘  └──────┬──────┘   │
        └────────────────┴──────────┘
                         │ all depend on
                  ┌──────┴───────┐
                  │  tom_basics  │  ← you are here
                  └──────────────┘
            (uuid · stack_trace · http only)

See the basics repository map for the full package catalogue and the samples learning path.


Further documentation #

  • doc/runtime/runtime.md — the runtime guide: TomEnvironment, TomPlatform, TomRuntime and the TomPlatformUtils seam, with the initialization sequence and the bean-context integration.
  • Basics repository README — the map of all ten basics packages.
  • tom_basics_console — supplies the desktop/server TomPlatformUtils implementation that backs the platform seam.
  • tom_crypto — a downstream consumer that logs through tomLog.
  • tom_core_kernel (separate repo) — provides TomException, the full-featured exception type that builds on this base.

Status #

  • Version: 1.0.0
  • SDK: Dart ^3.10.0
  • Tests: 6 passing (TomBaseException group — construction, parameters, custom UUID, cause capture, toString, stack-trace capture). Run with dart test or testkit :test.
  • Analyzer: clean (dart analyze → no issues).
0
likes
160
points
368
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Basic utilities for the TOM framework including exception handling with UUID tracking.

Repository (GitHub)
View/report issues

License

BSD-3-Clause (license)

Dependencies

crypto, http, meta, stack_trace, uuid, yaml, yaml_edit

More

Packages that depend on tom_basics