Skip to content

Updated to latest package versions and added some UI use case #12

Open
lsfera wants to merge 12 commits intojkonowitch:mainfrom
lsfera:main
Open

Updated to latest package versions and added some UI use case #12
lsfera wants to merge 12 commits intojkonowitch:mainfrom
lsfera:main

Conversation

@lsfera
Copy link
Copy Markdown

@lsfera lsfera commented Mar 19, 2026

This pull request introduces several improvements to the development tooling, documentation, and project configuration for the Hex-Effect repository. The most significant changes include the addition of VS Code workspace configuration files to streamline local development, expanded and clarified documentation for both the main project and the example application, and enhancements to the Docker Compose setup for local infrastructure. There are also updates to the ESLint configuration and TypeScript service port definitions.

Development environment setup:

  • Added .vscode/launch.json with debug configurations for the Todo App (server, browser, and full stack), enabling easier debugging and development workflows in VS Code.
  • Added .vscode/tasks.json to automate starting and stopping Docker Compose services, further streamlining local development.
  • Introduced .vscode/extensions.json (currently empty) to support future recommendations for VS Code extensions.
  • Updated .vscode/settings.json to change the default TypeScript formatter and disable JavaScript network view in debug sessions.

Documentation improvements:

  • Significantly expanded README.md with a detailed overview of the architecture, how Effect is used, repository layout, getting started instructions, and references.
  • Rewrote examples/todo-app/README.md to provide a clear walkthrough of the example application's structure, layers, and how to run it locally.
  • Added examples/todo-app/contexts/@projects/application/README.md to document available use cases, service ports, and error handling in the application layer.

Infrastructure and configuration:

  • Enhanced docker-compose.yml to use the latest LibSQL image, added an outerbase/studio service for database management, and configured the default network for devcontainers. [1] [2]

Linting and code quality:

  • Introduced a root-level eslint.config.js using the latest ESLint flat config format, with TypeScript and Prettier integration.
  • Removed the redundant .eslintrc.cjs from the application context and updated the application package.json to use the new lint script. [1] [2]

Application layer enhancements:

  • Added new service port tags (DeleteTask, GetTasksByProjectId, FindTaskById, UpdateTask) to the @projects/application layer for more granular task management.
  • Minor code cleanup and import fixes in the application error module.

These updates collectively improve the developer experience, clarify the project's structure and usage, and make it easier to contribute and run the example application locally.

lsfera and others added 5 commits March 19, 2026 17:10
…ects

- Add VS Code launch/tasks configs for full-stack debugging with source maps
  through workspace packages (vite aliases bypass dist in favour of TS source)
- Implement remove-task feature end-to-end (domain event, service tag, infra
  layer, use-case, and SvelteKit action + UI)
- Fix task persistence: libsql column name transformation required project_id
  in schema; add DROP+CREATE migrations to migrate existing DBs
- Refactor use-cases to FP pipelines using Effect.tap/map/flatMap, push
  AppError.mapErrors to the web boundary layer
- Use Either.fromOption for Option→Effect unwrapping in addTaskToProject
  (Either implements Effect interface directly in effect@3.20)
- Add outerbase/studio to docker-compose with dockerfile_inline to bake
  NEXT_PUBLIC_OB_API at build time; use external devcontainer network
- Migrate ESLint config from per-package .eslintrc.cjs to root eslint.config.js
- Remove unused @repo/template, @repo/typescript-config, @repo/ui packages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…edEvent

- Add completeTask use case: finds task, calls Task.Service.complete, persists
  via UpdateTask, emits TaskCompletedEvent through withTXBoundary
- Add FindTaskById and UpdateTask service tags + Live implementations
- Add EventHandlersLive: registers a durable NATS consumer for TaskCompletedEvent
  that logs on receipt, demonstrating the full event-driven round-trip
- Wire EventHandlersLive into the Live layer so it starts with the server
- Extract findOrFail/findOrNotFound helper to remove duplicated Option→Either
  unwrapping in addTaskToProject and completeTask; restore getProjectWithTasks
  to direct Option.match (semantically returns None, not a failure)
- Add "Mark Complete" button in UI (hidden once completed, strikethrough styling)
- Fix vitest watch mode: add --run flag so pnpm test exits after one run
- Fix EventSchemas variance error in event-handlers.ts with type assertion
Effect.fork attaches the child to the parent fiber's scope, so when
the layer build fiber exits after registering the handler the stream
fiber is immediately interrupted. Switch to Effect.forkIn(scope) to
tie the stream fiber to the EventConsumerSupervisor's scope, which
lives for the runtime lifetime.

Also wrap the handler use-phase in Effect.uninterruptible so an
in-flight handler runs to completion even during scope teardown,
and guard sdk.batch([]) against empty write sets.

Add a startup drain to EventPublisherDaemon and a multi-event test
that reproduces and verifies the fix.
Demonstrates two cross-domain communication patterns:

- Async: badges-task-completed NATS durable consumer listens for
  TaskCompletedEvent and calls checkAndAwardBadges
- Sync: GetCompletedTaskCount queries the @projects tasks table
  directly — an explicit anti-corruption layer port

Badges (trailblazer / momentum / achiever) are awarded at 1, 5, and
10 total completed tasks. BadgeAwardedEvent flows through the same
outbox pipeline as all other domain events.

BadgesInfraLive shares BaseLive (EventConsumer, WithTransaction,
SqlClient, UUIDGenerator) with @projects — no second DB or NATS
connection needed.
Move ManagedRuntime creation to runtime.ts so Vite HMR never
re-evaluates it when hooks.server.ts changes. Since runtime.ts is a
dependency (not a dependent) of hooks.server.ts, it survives HMR
cycles naturally — no globalThis or var needed.

Load project tasks and badges in parallel via Effect.all, show the
badges section below the task list, and trigger a delayed invalidateAll
after task completion so the async badge award has time to land.
lsfera added 7 commits March 20, 2026 08:02
- Replace if/else if chains with Match.type/Match.value dispatch in
  transactional-boundary, error.ts, badge.ts, and messaging.ts
- Classify SQL errors as DataIntegrityError vs InfrastructureError
  based on SQLITE_CONSTRAINT error codes
- Simplify withTXBoundary from Effect.gen to Effect.flatMap
- Replace Effect.tryPromise try/catch form with single-arg + mapError
- Replace if guard on writes.length with Effect.when
- Replace boolean if/else in upsertConsumer with Effect.if
- Deduplicate TaskId.make call in removeTask
- Add effect-ts and new-bounded-context Claude Code skills
- effect 3.20 → 3.21, @effect/* packages to latest minors
- typescript 5.8 → 5.9, turbo 2.8.17 → 2.8.20, @types/bun patch
- vitest pinned to ^3.2.4 (vitest 4.x not yet supported by @effect/vitest)
- eslint-plugin-svelte 2 → 3, globals 16 → 17, vite 8.0.0 → 8.0.1
- Remove unused @effect/rpc-http dependency
- Tighten peer dep lower bounds in @hex-effect/core and infra-libsql-nats
- Add keys to {#each} blocks (svelte/require-each-key)
- Disable svelte/no-navigation-without-resolve link checking:
  the rule looks for `resolve` from '$app/paths' but SvelteKit 2
  exports `resolveRoute` — the rule's API check is stale
…SQL support

Split `@hex-effect/infra-libsql-nats` into three packages:

- `@hex-effect/infra-nats`: shared NATS + event-store base (SQL-vendor-agnostic).
  Uses `sql.unsafe()` for DDL and parses JSON payload in application code to
  avoid dialect-specific `json_extract()`.
- `@hex-effect/infra-libsql-nats`: now a thin adapter (LibSQL client +
  WithTransactionLive using sdk.batch() for Batched isolation).
- `@hex-effect/infra-pg-nats`: new PostgreSQL adapter. Both IsolationLevel.Batched
  and Serializable map to PG transactions. PG constraint codes (class 23) are
  classified as DataIntegrityError.

Also adds a `PgLive` export to `@projects/infra` and a `postgres:16-alpine`
service (profile `pg`) to docker-compose.yml so the todo-app can run against
either backend. Schema transforms in service layers handle both SQLite (0/1
booleans, epoch-ms dates) and PG (native boolean/Date) transparently.
- Add @projects/infra test/util.ts: shared testcontainer setup with a
  `backends` array parameterizing both LibSQL and PostgreSQL infra layers
- Add integration.test.ts: describe.each(backends) runs all use-case tests
  (create project, add tasks, complete task, NATS events, badge awarding)
  against both providers via ManagedRuntime
- Fix @badges/infra service schemas for PG type differences:
  COUNT(*) returns bigint-as-string, BIGINT awardedAt column returns string
- Add DB_PROVIDER env var switch in web/runtime.ts to select Live vs PgLive
- Add VSCode launch config and tasks for PostgreSQL backend (docker compose
  --profile pg), with DATABASE_URL and DB_PROVIDER=pg env vars
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant