diff --git a/.agents/memory/MEMORY.md b/.agents/memory/MEMORY.md index 641ad7b2c3..04b21a6a8d 100644 --- a/.agents/memory/MEMORY.md +++ b/.agents/memory/MEMORY.md @@ -13,7 +13,7 @@ See [README.md](README.md) for the format and routing rules. ## Project (durable context & rationale) -*(no entries yet)* +- [ts-codegen-via-buf](project/ts-codegen-via-buf.md) — TS codegen will likely use Buf (protobuf-es); keep proto option docs implementation-neutral. ## Reference (external systems) diff --git a/.agents/memory/project/ts-codegen-via-buf.md b/.agents/memory/project/ts-codegen-via-buf.md new file mode 100644 index 0000000000..d8cc098168 --- /dev/null +++ b/.agents/memory/project/ts-codegen-via-buf.md @@ -0,0 +1,24 @@ +--- +name: ts-codegen-via-buf +description: TypeScript codegen will likely use Buf (protobuf-es), not google-protobuf protoc — keep proto option docs implementation-neutral. +metadata: + type: project + since: 2026-08-11 +--- + +TypeScript code generation for the Spine SDK is likely to be built on +Buf (`protobuf-es`) rather than the `google-protobuf` runtime used by +the legacy JS stack (`web/client-js`, `mc-js`). + +**Why:** Stated by the project lead while reviewing the `ts_type` +property docs of `IsOption`/`EveryIsOption` (branch +`more-language-types`, 2026-08-11): the docs must not restrict +implementation details such as "extends the `Message` type from the +`google-protobuf` module", because the TS toolchain is not settled on +`google-protobuf`. + +**How to apply:** When documenting or implementing TypeScript-facing +options in `options.proto` (or elsewhere in the SDK), stay neutral +about the generation toolchain and runtime base types until the TS +codegen actually lands. Do not infer TypeScript contracts from what +`web/client-js` currently depends on. diff --git a/.agents/tasks/add-ts-type-option.md b/.agents/tasks/add-ts-type-option.md new file mode 100644 index 0000000000..0d9b0a415e --- /dev/null +++ b/.agents/tasks/add-ts-type-option.md @@ -0,0 +1,50 @@ +--- +slug: add-ts-type-option +branch: more-language-types +owner: claude +status: in-review +started: 2026-08-11 +--- + +## Goal + +`IsOption` and `EveryIsOption` in `base/src/main/proto/spine/options.proto` +gain a `ts_type` property naming the TypeScript interface for the annotated +message type(s), mirroring the existing `java_type` contract. + +## Context + +- Requested by the user on the `more-language-types` branch, which is + already version-bumped (`2.0.0-SNAPSHOT.440`). +- No consumer of `ts_type` exists yet anywhere in the SpineEventEngine + organisation; this repo introduces the property first. Codegen support + arrives later in the compiler/model-compiler repos. +- Spine's JS/TS client stack (`web/client-js`) is built on the + `google-protobuf` runtime, so a generated marker interface extends + `Message` from that module — the parallel of `com.google.protobuf.Message` + in the `java_type` docs. + +## Plan + +- [x] Add `ts_type = 2` to `IsOption` with docs mirroring `java_type`. +- [x] Add `ts_type = 3` to `EveryIsOption`, including the `generate` + interplay paragraphs. +- [x] Extend the `(is)` and `(every_is)` extension-field docs with + "When targeting TypeScript…" sentences. +- [x] Mention `ts_type` in the message-level docs of both option types. +- [x] Build (`proto` change → `clean build` per `running-builds.md`). + +## Log + +- 2026-08-11 — drafted; executing. +- 2026-08-11 — `./gradlew clean build` green; `review-docs` approved the + diff (nits only). Discussing the "not nested into a namespace" wording + with the user; docs may still be adjusted before commit. +- 2026-08-11 — per user: dropped the "generated interface extends + `Message` from `google-protobuf`" paragraph — TS codegen will likely + use Buf, so docs stay implementation-neutral (see team memory + `ts-codegen-via-buf`). Rebuilt: green. +- 2026-08-11 — pre-pr PASS (build green; kotlin-engineer APPROVE, + review-docs APPROVE, spine-code-review APPROVE WITH CHANGES — noted + the pre-existing +10 bump vs additive change; surfaced in PR body). + PR: https://github.com/SpineEventEngine/base-libraries/pull/956 diff --git a/base/src/main/proto/spine/options.proto b/base/src/main/proto/spine/options.proto index 254fe0f167..2f08e7ee1f 100644 --- a/base/src/main/proto/spine/options.proto +++ b/base/src/main/proto/spine/options.proto @@ -632,6 +632,9 @@ extend google.protobuf.MessageOptions { // When targeting Java, specify the name of a Java interface to be implemented by this // message via `(is).java_type`. // + // When targeting TypeScript, specify the name of a TypeScript interface to be + // implemented by this message via `(is).ts_type`. + // IsOption is = 73915; // Reserved 73916 to 73921 for future API annotation options. @@ -724,6 +727,9 @@ extend google.protobuf.FileOptions { // When targeting Java, specify the name of a Java interface to be implemented by these // message types via `(every_is).java_type`. // + // When targeting TypeScript, specify the name of a TypeScript interface to be + // implemented by these message types via `(every_is).ts_type`. + // EveryIsOption every_is = 73946; // Reserved 73947 to 73970 for future use. @@ -1235,6 +1241,7 @@ message EntityOption { // The nature of the type depends on the target programming language. // For example, the `java_type` property defines a name of the Java interface common // to all message classes generated for the proto file having this option. +// Similarly, the `ts_type` property defines a name of the TypeScript interface. // // The option triggers creation of the common type if the `generate` property is set to true. // Otherwise, it is expected that the user provides the reference to an existing type. @@ -1267,6 +1274,22 @@ message EveryIsOption { // will have no declared methods. // string java_type = 2; + + // The reference to a TypeScript top-level interface. + // + // The interface cannot be nested into a namespace or a class. + // If a nested interface is provided, the code generation should fail the build process. + // + // The value is a simple name of the interface. It is assumed that the interface + // is available in the scope of the generated message types. + // + // If the value of the `generate` field is set to `false`, the referenced interface must exist. + // Otherwise, a compilation error will occur. + // + // If the value of the `generate` field is set to `true`, the framework will + // generate the interface using the given name. + // + string ts_type = 3; } // Defines an additional type for a message type in which this option is declared. @@ -1274,6 +1297,7 @@ message EveryIsOption { // The nature of the type depends on the target programming language. // For example, the `java_type` property defines a name of the Java interface that // the generated message class will implement. +// Similarly, the `ts_type` property defines a name of the TypeScript interface. // message IsOption { @@ -1290,6 +1314,18 @@ message IsOption { // The referenced interface must exist. Otherwise, a compilation error will occur. // string java_type = 1; + + // The reference to a TypeScript top-level interface. + // + // The interface cannot be nested into a namespace or a class. + // If a nested interface is provided, the code generation should fail the build process. + // + // The value is a simple name of the interface. It is assumed that the interface + // is available in the scope of the generated message types. + // + // The referenced interface must exist. Otherwise, a compilation error will occur. + // + string ts_type = 2; } // Defines the way to compare two messages of the same type to one another. diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/boms/Boms.kt b/buildSrc/src/main/kotlin/io/spine/dependency/boms/Boms.kt index 5d06efb5b7..266dd8d76a 100644 --- a/buildSrc/src/main/kotlin/io/spine/dependency/boms/Boms.kt +++ b/buildSrc/src/main/kotlin/io/spine/dependency/boms/Boms.kt @@ -28,7 +28,7 @@ package io.spine.dependency.boms import io.spine.dependency.DependencyWithBom import io.spine.dependency.kotlinx.Coroutines -import io.spine.dependency.lib.Jackson +import io.spine.dependency.lib.JacksonV2 import io.spine.dependency.lib.Kotlin import io.spine.dependency.lib.Grpc import io.spine.dependency.test.JUnit @@ -60,7 +60,7 @@ object Boms { * Technology-based BOMs. */ object Optional { - val jackson = Jackson.bom + val jackson = JacksonV2.bom val grpc = Grpc.bom } } diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Jackson.kt b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Jackson.kt index ae24a928f0..7d078ed97e 100644 --- a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Jackson.kt +++ b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Jackson.kt @@ -37,6 +37,9 @@ import io.spine.dependency.DependencyWithBom * consuming the 2.x artifact, so both its coordinates and its * `com.fasterxml.jackson.annotation` package stay unchanged. * + * The Jackson 2.x artifacts, which some of our dependencies still consume, + * are declared by [JacksonV2]. + * * See: * - [Jackson Releases](https://github.com/FasterXML/jackson/wiki/Jackson-Releases) * - [Migrating to Jackson 3](https://github.com/FasterXML/jackson/blob/main/jackson3/MIGRATING_TO_JACKSON_3.md) @@ -50,7 +53,7 @@ object Jackson : DependencyWithBom() { * The version of `jackson-annotations`, which Jackson 3.x deliberately keeps * on the 2.x line. * - * Must match the `jackson.version.annotations` property declared by the [bom]. + * Must match the `jackson.version.annotations` property declared by the [JacksonV2.bom]. * * See: https://github.com/FasterXML/jackson-annotations?tab=readme-ov-file#release-notes */ diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/lib/JacksonV2.kt b/buildSrc/src/main/kotlin/io/spine/dependency/lib/JacksonV2.kt new file mode 100644 index 0000000000..256918f848 --- /dev/null +++ b/buildSrc/src/main/kotlin/io/spine/dependency/lib/JacksonV2.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2026, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.dependency.lib + +import io.spine.dependency.Dependency +import io.spine.dependency.DependencyWithBom + +/** + * Jackson 2.x dependencies. + * + * Jackson 2.x artifacts keep the `com.fasterxml.jackson.*` group IDs, unlike + * Jackson 3.x, which moved to `tools.jackson` (JSTEP-1). We declare the 2.x line + * to align the versions of the artifacts pulled transitively by third-party + * dependencies, while our own code uses Jackson 3.x declared by [Jackson]. + * + * The `jackson-annotations` artifact, although it belongs to the 2.x line, is + * declared by [Jackson.annotations] because Jackson 3.x keeps consuming it. + * + * See: + * - [Jackson Releases](https://github.com/FasterXML/jackson/wiki/Jackson-Releases) + * + * @see Jackson + */ +@Suppress("unused") +object JacksonV2 : DependencyWithBom() { + override val group = "com.fasterxml.jackson" + override val version = "2.22.1" + + // https://github.com/FasterXML/jackson-bom + override val bom = "$group:jackson-bom:$version" + + private val groupPrefix = group + + /** + * All Jackson 2.x modules we use are declared by the nested objects, + * such as [Core] or [DataType]. + */ + override val modules = emptyList() + + object Core : Dependency() { + override val version = JacksonV2.version + override val group = "$groupPrefix.core" + + @Suppress("MemberNameEqualsClassName") + val core = "$group:jackson-core" + val databind = "$group:jackson-databind" + + override val modules = listOf(core, databind) + } + + object DataType : Dependency() { + override val version = JacksonV2.version + override val group = "$groupPrefix.datatype" + + val jdk8 = "$group:jackson-datatype-jdk8" + val jsr310 = "$group:jackson-datatype-jsr310" + val guava = "$group:jackson-datatype-guava" + + override val modules = listOf(jdk8, jsr310, guava) + } + + object DataFormat : Dependency() { + override val version = JacksonV2.version + override val group = "$groupPrefix.dataformat" + + val xml = "$group:jackson-dataformat-xml" + val yaml = "$group:jackson-dataformat-yaml" + val protobuf = "$group:jackson-dataformat-protobuf" + + override val modules = listOf(xml, yaml, protobuf) + } + + object Module : Dependency() { + override val version = JacksonV2.version + override val group = "$groupPrefix.module" + + val parameterNames = "$group:jackson-module-parameter-names" + + override val modules = listOf(parameterNames) + } +} diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Log4j2.kt b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Log4j2.kt index 83b32e43d1..30b3dad8cb 100644 --- a/buildSrc/src/main/kotlin/io/spine/dependency/lib/Log4j2.kt +++ b/buildSrc/src/main/kotlin/io/spine/dependency/lib/Log4j2.kt @@ -37,6 +37,22 @@ package io.spine.dependency.lib */ @Suppress("unused", "ConstPropertyName") object Log4j2 { - private const val version = "2.26.0" + const val version = "2.26.1" + const val core = "org.apache.logging.log4j:log4j-core:$version" + + /** + * Routes the calls made through the [SLF4J API][Slf4J.lib] to the [core] backend. + * + * Add this artifact when a third-party library logs via SLF4J — such as Micronaut — + * and its output should reach the Log4j2 backend of the application. + * + * The artifact is `log4j-slf4j2-impl`, the binding for the SLF4J 2.x that [Slf4J] + * declares. Do not substitute `log4j-slf4j-impl`: it binds SLF4J 1.7 only, and + * under SLF4J 2.x it registers no provider, which leaves the logging silently + * unbound instead of failing the build. + * + * @see Log4j2 SLF4J 2.x binding + */ + const val slf4j2Bridge = "org.apache.logging.log4j:log4j-slf4j2-impl:$version" } diff --git a/config b/config index dbfa53987f..02824c32a4 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit dbfa53987f03d3371248f7062ef04047a162edc4 +Subproject commit 02824c32a44a1691a2dd2fc17c209cdacb3499ee diff --git a/docs/dependencies/dependencies.md b/docs/dependencies/dependencies.md index 3c0c9d96e0..b70091718a 100644 --- a/docs/dependencies/dependencies.md +++ b/docs/dependencies/dependencies.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine:spine-annotations:2.0.0-SNAPSHOT.430` +# Dependencies of `io.spine:spine-annotations:2.0.0-SNAPSHOT.440` ## Runtime 1. **Group** : org.jetbrains. **Name** : annotations. **Version** : 26.1.0. @@ -771,14 +771,14 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sat Aug 08 00:34:28 WEST 2026** using +This report was generated on **Tue Aug 11 20:19:51 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-base:2.0.0-SNAPSHOT.430` +# Dependencies of `io.spine:spine-base:2.0.0-SNAPSHOT.440` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -1646,14 +1646,14 @@ This report was generated on **Sat Aug 08 00:34:28 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sat Aug 08 00:34:28 WEST 2026** using +This report was generated on **Tue Aug 11 20:19:51 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-environment:2.0.0-SNAPSHOT.430` +# Dependencies of `io.spine:spine-environment:2.0.0-SNAPSHOT.440` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -2483,14 +2483,14 @@ This report was generated on **Sat Aug 08 00:34:28 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sat Aug 08 00:34:28 WEST 2026** using +This report was generated on **Tue Aug 11 20:19:51 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-format:2.0.0-SNAPSHOT.430` +# Dependencies of `io.spine:spine-format:2.0.0-SNAPSHOT.440` ## Runtime 1. **Group** : com.fasterxml.jackson.core. **Name** : jackson-annotations. **Version** : 2.22. @@ -3380,6 +3380,6 @@ This report was generated on **Sat Aug 08 00:34:28 WEST 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Sat Aug 08 00:34:28 WEST 2026** using +This report was generated on **Tue Aug 11 20:19:51 WEST 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file diff --git a/docs/dependencies/pom.xml b/docs/dependencies/pom.xml index e73aa2f9db..bf8f10881a 100644 --- a/docs/dependencies/pom.xml +++ b/docs/dependencies/pom.xml @@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject. --> io.spine base-libraries -2.0.0-SNAPSHOT.430 +2.0.0-SNAPSHOT.440 2015 diff --git a/version.gradle.kts b/version.gradle.kts index 5818c42507..76028d5b7a 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -24,4 +24,4 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -extra.set("versionToPublish", "2.0.0-SNAPSHOT.430") +extra.set("versionToPublish", "2.0.0-SNAPSHOT.440")