Skip to content

Releases: sideeffffect/dapr4s

v3.0.0 — Typed Dapr errors, invokeHttp, sbt build

Choose a tag to compare

@sideeffffect sideeffffect released this 12 Oct 17:19
9e98db8

Every sidecar error is now a dapr4s exception, service invocation exposes HTTP status and headers, and the build moved to sbt.

Breaking

  • Typed Dapr errors. Every sidecar error now arrives as a subclass of the sealed dapr4s.DaprException. Java SDK exceptions and js.JavaScriptException no longer reach your code. The subclasses:

    • ComponentNotFoundException(componentKind, name)
    • PermissionDeniedException
    • AppUnreachableException(appId)
    • InvokeHttpException(appId, method, status, body)
    • DaprApiException(errorCode)

    Update any catch of io.dapr.exceptions.DaprException. The mapping table is in wiki/dapr/dapr-error-codes.md.

  • Typed invoke throws on non-2xx. It throws InvokeHttpException, the same on JVM and JS. 3xx counts as non-2xx.

  • UnlockStatus.LockBelongsToOthers. Unlocking a lock that another owner holds returns this new case. Before, it returned InternalError. Exhaustive matches need the new case.

  • Scala.js 1.22. dapr4s_sjs1_3 is built with Scala.js 1.22, so consumers need a 1.22 linker.

Features

  • InvokeCapability.invokeHttp. It returns InvokeResponse(status, headers, body) and never throws on status. It takes headers and query parameters.

Build

  • dapr4s builds with sbt instead of scala-cli (PR #42).
    • ScalablyTyped facades are generated inside the build.
    • The scala-cli 1.14.0 pin and the facade and Wasm workaround scripts are gone.
    • Published coordinates are unchanged: com.github.sideeffffect:dapr4s_3 and dapr4s_sjs1_3.

Docs

  • Wasm component proposal. docs/WASM-COMPONENTS-PROPOSAL.md describes how to target WASI components through dapr-wasm-components v0.7.0.
  • Wiki. New articles on the WIT overlap and on Dapr error codes.

v2.0.0 — Capability tiers: universal XCapability + Instance + ReadOnly

Choose a tag to compare

@sideeffffect sideeffffect released this 12 Oct 11:53
4b354c7

Highlights

A new capability API: universal XCapability + Instance + ReadOnly tiers. This is a breaking change (#40).

  • Universal capability per building block. DaprCapability.state returns StateCapability, which reaches any store: StateCapability.save(storeName, key, value). The same holds for publish, invoke (appId per call), secrets, configuration, bindings, lock, crypto, workflow, actor, and, on the JVM, jobs and conversation.
  • Narrow by name with instance(name). It returns XCapability.Instance, bound to one resource: dapr.state.instance(store).get[T](key).
  • Narrow by authority with ReadOnly. State, Secrets, Configuration, Jobs and Workflow have X.ReadOnly and X.Instance.ReadOnly. Narrowing a read-only capability by name stays read-only, which the compiler checks.
  • Actor has two levels: ActorCapability.forType(actorType).instance(actorId).
  • Companion forwarders and accessors on every interface. For example, StateCapability.Instance.save(key, v) uses the capability in using scope, and StateCapability.ReadOnly.instance(store) returns the narrowed capability.
  • Handle-style sugar that respects the tiers:
    • WorkflowInstanceId: id.waitForCompletion(timeout) and id.getStatus need only WorkflowCapability.ReadOnly; id.suspend(), id.terminate() and the other mutations need WorkflowCapability.
    • JobName (JVM): name.get, name.scheduleOnce(...) and name.delete().
  • One package per family: dapr4s.state, dapr4s.invoke, dapr4s.workflow and so on. Cross-cutting types stay in dapr4s.

Migrating from 1.x

  • Add family imports, e.g. import dapr4s.state.*, dapr4s.workflow.*.
  • Code that is bound to one store, inside a DaprCapability.state(name) { ... } block, now uses StateCapability.Instance. For example, (using StateCapability) becomes (using StateCapability.Instance), and StateCapability.get(key) becomes StateCapability.Instance.get(key).
  • dapr.state(name) becomes dapr.state.instance(name). dapr.actor(t)(id) becomes dapr.actor.forType(t).instance(id).
  • These types were removed: Access*Capability, WorkflowInstanceCapability, ActorTypeCapability and JobCapability.
  • dapr4s-examples shows the full migration.

Features

  • Universal / Instance / ReadOnly capability tiers for all building blocks; derivation macros require the narrowest tier (#40).
  • Tier-aware handle sugar on WorkflowInstanceId and JobName (#40).
  • One package per capability family (#40).

Fixes

  • Scaladoc: 94 unresolved links fixed. JVM and Scala.js scaladoc now report 0 warnings.

Build / CI

  • Fixed a silent hang in the Scala.js integration tests. scala-cli chose __loader.js instead of main.js as the Wasm test entry when its temp dir was on ext4. The test harness now runs scala-cli with its temp dir on tmpfs. Upstream fix: VirtusLab/scala-cli#4548.
  • scala-cli is pinned to 1.14.0, because newer versions with the Scala.js 1.22 linker cannot link js.async on Wasm without a JSPI switch. The integration step now has a 20-minute timeout.
  • Publishes of the same version are serialized with a concurrency group.

Docs

  • New docs/CAPABILITY-HIERARCHY.md: one Mermaid class diagram per capability family.
  • docs/CAPABILITY-SPLITS.md §11 describes the implemented design. DESIGN.md, README and SPEC.allium are updated, and allium check reports 0 errors.

v1.0.0

Choose a tag to compare

@sideeffffect sideeffffect released this 17 Jun 11:20
a6f7123

First stable release of dapr4s — a cross-platform (JVM + Scala.js/Wasm) Scala 3 library for Dapr.

Library fixes

  • Actor & workflow clients now honour the configured sidecar endpoint. ActorClient / DaprWorkflowClient were built with no-arg constructors that defaulted to localhost:3500/50001, ignoring DaprConfig.sidecar — so actors and workflows broke against any non-default sidecar port. They now receive the endpoint/TLS/token overrides via Dapr.sidecarProperties.
  • bulkPublish encoding fixed. Events were double-encoded (JSON String through the wrong publishEvents overload, which also dropped per-entry ids), leaving them undeliverable. Now uses BulkPublishRequest<byte[]> with raw bytes and explicit entry ids.
  • Workflow gRPC channel no longer leaks on shutdown. The DurableTaskGrpcWorker channel is now closed on the server's InterruptedException path (removes the ManagedChannel allocation site warning at teardown).

Testing

  • Actor / PubSub / Invoke / Workflow integration suites are now single cross-platform classes in test/shared — JVM and Scala.js run the same test bodies, with only setup coming from per-platform fixtures. Each platform gained the other's previously-missing cases (real server-delivery coverage, not raw-HTTP shortcuts).
  • JVM and JS test-infrastructure files and types now mirror each other (ServerDaprItSuite / ServerDaprItEnv / SharedDaprItSuite / TestCodecs), so the two trees read as twins.

Full Changelog: v0.20.1...v1.0.0

v0.20.0

Choose a tag to compare

@sideeffffect sideeffffect released this 13 Jun 10:42
0317d09

Cross-compile dapr4s to Scala.js — ScalablyTyped facades over the Dapr JS SDK, Wasm+JSPI direct style (#38).

Highlights:

  • New dapr4s_sjs1_3 Scala.js artifact (self-contained: the ScalablyTyped facade is embedded; the POM references Maven Central only).
  • Shared/JVM/JS source layout with platform traits; Jobs and Conversation remain JVM-only.
  • Unified integration-test harness: one shared Dapr component set (redis everywhere) and shared scenario traits driving both platforms.

v0.19.0 — caller/callee dual derivations (deriveChecked)

Choose a tag to compare

@sideeffffect sideeffffect released this 09 Jun 01:23

Each Dapr building block is a dual pair (app→Dapr caller ↔ Dapr→app callee). This release lets one shared trait bind and type-check both sides.

Highlights

  • deriveChecked[Contract, Impl] added (alongside the unchanged derive) on InvokeRoutes, Subscriptions, ActorDefinitions, JobRoutes, WorkflowActivities, and WorkflowActivityCalls: the macro verifies the impl answers every contract method with matching request/response types, matched by method name or wire name (topic / job / actor) as appropriate.
  • New server-route engines BindingRoutes.derive and JobRoutes.derive — filling the previously-asymmetric Bindings and Jobs pairs.
  • Actor.derive now also schedules reminders/timers: a @reminder/@timer method forwards to ActorContext.registerReminder/registerTimer; ActorDefinitions.deriveChecked verifies them against the actor's @reminder/@timer routes.
  • Dual cross-reference docs on the capability traits and route types.

Additive over v0.18.0 (no breaking changes). Bindings has no deriveChecked — output operations vs input payload-delivery are independent directions, not a request/response contract.

v0.18.0 — Unified capability nomenclature

Choose a tag to compare

@sideeffffect sideeffffect released this 08 Jun 14:36

This release unifies the naming of every Dapr building block around the short name Dapr uses in its HTTP path, keeping Scala conventions (UpperCamel, *Capability suffixes). One concept, one stem — no more ServiceInvocation vs Invoker vs Invocation for the same thing.

⚠️ Breaking change. Public capability traits, op-types, companion accessors, the DaprApp route field, and several model types are renamed. Mechanical find-and-replace upgrades most code; see the mapping below.

Highlights

  • ServiceInvocationCapability / Invoker* / Invocation* → Invoke* (matches /v1.0/invoke)
  • PubSubCapability → PublishCapability (the client capability is publish-only; PubSubName kept — it is Dapr's literal pubsubname)
  • DistributedLockCapability → LockCapability (matches /v1.0-alpha1/lock)
  • Config* → Configuration* (matches /v1.0/configuration)
  • Conversation value types singularised to match their cardinality

Refactors

Service invocation → Invoke

  • ServiceInvocationCapability → InvokeCapability
  • InvocationRoute → InvokeRoute, InvocationRequest → InvokeRequest, InvocationMethodName → InvokeMethodName
  • Derivations ServiceInvocation/InvocationRoutes/ServiceInvocationDerivationRuntime → Invoke/InvokeRoutes/InvokeDerivationRuntime
  • Accessor DaprCapability.invoker → DaprCapability.invoke; DaprApp.invocations field → DaprApp.invokeRoutes

Pub/Sub → Publish

  • PubSubCapability → PublishCapability; accessor DaprCapability.pubsub(...) → DaprCapability.publish(...)
  • PubSubName unchanged (Dapr's component identifier)

Lock

  • DistributedLockCapability → LockCapability

Configuration

  • ConfigKey/ConfigStoreName/ConfigValue/ConfigVersion/ConfigItem/ConfigUpdate → Configuration*
  • Accessor DaprCapability.config(...) → DaprCapability.configuration(...)

Conversation

  • ConversationTools → ConversationTool, ConversationToolCalls → ConversationToolCall, ConversationResultChoices → ConversationResultChoice

Bindings

  • Accessor DaprCapability.binding(...) → DaprCapability.bindings(...)

Docs

  • DESIGN.md, SPEC.allium, derivation.md, validation.md, and AGENTS.md updated to the new nomenclature.

No behavioural changes — renames only. Verified with the full unit (33) and integration (90) suites green.

v0.17.0 — Configurable derive overloads

Choose a tag to compare

@sideeffffect sideeffffect released this 08 Jun 00:30

Highlights

The three name-bound derivations now each offer two derive overloads — pass the name explicitly, or let it be derived from the type's simple name (honouring @name):

Derivation Explicit Name-derived
ActorDefinitions derive[C](actorType: ActorType) (new) derive[C] → ActorType from the class name
ServiceInvocation derive[T](appId: AppId) derive[T] → AppId from the trait name (new)
Subscriptions derive[T](pubsubName: PubSubName) derive[T] → PubSubName from the type name (new)
// explicit
val svc = ServiceInvocation.derive[GreetingService](AppId("greeting-service"))
// name-derived — AppId("GreetingService")
val svc = ServiceInvocation.derive[GreetingService]

ActorDefinitions gains the explicit-ActorType form (it previously only derived from the class name); ServiceInvocation and Subscriptions gain the name-derived form (they previously required the name). All additions are backward compatible.

Features

  • Add name-deriving derive overloads for ActorDefinitions, ServiceInvocation and Subscriptions. Name resolution goes through a new MacroSupport.derivedTypeName, which honours @name on the type and strips a module's trailing $ so Foo.type yields Foo.

Docs

  • Mandate auto-commit/push and curated GitHub Releases in AGENTS.md.

Full Changelog: v0.16.0...v0.17.0

v0.9.0

Choose a tag to compare

@sideeffffect sideeffffect released this 07 Jun 13:21

Breaking changes

Each Dapr building block now gets its own name/key opaque type — one can no longer be passed where another is expected.

  • MethodName → InvocationMethodName (service invocation) / ActorMethodName (actors).
  • StoreName → StateStoreName (.state) / LockStoreName (.lock).
  • StateKey → StateStoreKey (app state) / ActorStateKey (per-actor state).

Migration

Replace MethodName with InvocationMethodName or ActorMethodName; StoreName with StateStoreName/LockStoreName; StateKey with StateStoreKey/ActorStateKey. See dapr4s-examples for the upgraded usage.

Other

  • Docs reorganized under docs/; CI and Maven Central badges added to the README.

Full Changelog: v0.8.1...v0.9.0

v0.8.1

Choose a tag to compare

@sideeffffect sideeffffect released this 07 Jun 13:21
  • Fix: stop double-encoding binding payloads (invokeBinding byte[] in/out).

Full Changelog: v0.8.0...v0.8.1

v0.8.0

Choose a tag to compare

@sideeffffect sideeffffect released this 07 Jun 13:21

Breaking: inject ActorContext into ActorDefinition build via a context function.

Full Changelog: v0.7.0...v0.8.0