Skip to content

Latest commit

 

History

History
75 lines (47 loc) · 5.51 KB

File metadata and controls

75 lines (47 loc) · 5.51 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

About this package

df_log is a standalone Dart package published to pub.dev (https://pub.dev/packages/df_log). It is part of the df_* ecosystem by dev-cetera and is consumed by external apps as well as by the parent compledo monorepo it currently sits inside.

It has no Flutter dependency. Pure Dart, runs anywhere Dart runs (VM, web, isolates). Don't add Flutter imports.

The README (README.md) is the user-facing docs and is regenerated from _README_CONTENT.md by CI — edit _README_CONTENT.md for content changes between the <!-- BEGIN _README_CONTENT --> markers, never the README directly.

Common commands

# From the package root (/packages/df_log/):

# Run the full test suite
dart test

# Run a single test file
dart test test/df_log_test.dart

# Run a single test by name
dart test test/df_log_test.dart -n "Log.info stores a log item"

# Format / fix / analyze (CI runs format + fix + analyze on release)
dart format .
dart fix --apply
dart analyze

# Run the example
dart run example/example.dart

# Custom lints (df_safer_dart_lints) run via custom_lint
dart run custom_lint

Architecture

The whole package is three files in lib/src/, exported through a generated barrel:

  • log.dart — the Log final class. All-static, never instantiated. Holds global state (activeTags, items queue, callbacks, styling/storage flags, context) and the category methods (info, err, ok, alert, start, stop, trace, ignore, message) plus the printRed/printGreen/… color helpers. Every category method funnels into Log.log(...)_printLog(...).
  • log_item.dartLogItem, the immutable record of one log call. Carries id, timestamp, frame, location, icon, message, metadata, tags, context, internalIndex. Knows how to render itself (toConsoleString, toStyledConsoleString, toMap, toJson).
  • ansi_styled_string.dartAnsiStyle value object plus a String.withAnsiStyle(...) extension. Styles compose with +.

Three structural details that are easy to miss:

  1. Logs are stripped from release builds by default. Log.log wraps the print path in assert(() { ... return true; }()). In AOT/release the assert is gone, so nothing prints unless Log.enableReleaseAsserts = true. When you add a new logging entry point, follow the existing pattern in log.dart — don't bypass the assert wrapper.

  2. All Log static state is per-isolate. Dart statics aren't shared across isolates, so Log.context, Log.items, Log.activeTags, Log.callbacks, etc. are independent in each isolate. Log.context exists specifically so log lines from different isolates can be told apart in the shared stdout. Don't introduce cross-isolate shared state — the design depends on this isolation.

  3. Call-site location comes from df_safer_dart's Here(...), not a raw StackTrace. Each public entry point passes initialStackLevel + N down into _printLog, where N accounts for the inlined hops. Adding a new wrapper method means picking the right initialStackLevel offset — copy from a sibling method (Log.info, etc.) and verify the printed [file/method #line] points at the caller, not at log.dart.

The barrel file is generated — don't edit it

lib/src/_src.g.dart is regenerated by df_generate_dart_indexes and re-exports everything in lib/src/. Add a new file to lib/src/, then regenerate the barrel — never hand-edit _src.g.dart. lib/df_log.dart is the public entry point and only re-exports the barrel; lib/_common.dart is an internal-only barrel of third-party imports used inside the package (Queue, JsonEncoder, max, Here, Frame, Uuid, visibleForTesting) and is the import path for files in lib/src/ (import '/_common.dart';).

Conventions specific to this package

  • Categorized logging is the public surface (Log.info, Log.err, Log.ok, Log.alert, Log.trace, Log.start, Log.stop, Log.message, Log.ignore). Each one auto-applies a category tag (e.g. #info, #err) so users can filter via activeTags.
  • Enum names use UPPER_SNAKE_CASE (e.g. _IconCategory.TRACE) — the analyzer rule constant_identifier_names is intentionally disabled in analysis_options.yaml to allow this. Don't "fix" the casing.
  • Single quotes, trailing commas, const constructors, prefer_relative_imports — enforced by analysis_options.yaml. Violations are errors, not warnings.
  • The @visibleForTesting int initialStackLevel = 0 parameter on every public log entry exists so tests can inject the right stack offset. Don't remove it.
  • Tests reset all Log static state in setUp (see test/df_log_test.dart). New tests must do the same — global state leaks between tests otherwise.

Release process

Releases are driven entirely by commit messages on main, handled by .github/workflows/process-package.yml:

  • Commit starting with + → CI runs dart format, dart fix, regenerates README + CHANGELOG, bumps version, creates a git tag.
  • Commit starting with ++ → same as above, plus a full release (the publish step is currently commented out in the workflow but the prepare step is live).
  • The release-notes line in CHANGELOG.md comes from the commit message after stripping the leading +/++.

So: a normal commit does nothing special; a commit like +Add isolate support triggers the version-bump pipeline. Never bump the version in pubspec.yaml by hand — let CI do it.