diff --git a/AGENTS.md b/AGENTS.md index e517769d..02861f4a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -427,6 +427,9 @@ melos run lint:all - SDK uses semantic versioning - Version managed in `packages/stream_feeds/pubspec.yaml` +- `packages/stream_feeds/lib/src/version.dart` is **generated** from that version by `tools/generate_version.dart`, + which runs automatically on every `melos bootstrap` (`command.bootstrap.hooks.post`). Never edit it by hand — it is + the SDK version reported in the `X-Stream-Client` header, and bootstrapping will overwrite any manual change. - `stream_feeds` is the only published package; releases go out behind a single `vX.Y.Z` tag - Below `1.0.0` the Dart convention shifts every slot down one: a breaking release is a **minor** bump, a feature release is a **patch** bump, and a change with no public API impact is a build (`+1`) bump. See diff --git a/melos.yaml b/melos.yaml index d6ef97b5..c7f349ae 100644 --- a/melos.yaml +++ b/melos.yaml @@ -64,7 +64,15 @@ command: retrofit_generator: ^10.2.6 test: ^1.26.3 + hooks: + # Syncs lib/src/version.dart with the version in stream_feeds' pubspec. + post: melos run version:update + scripts: + version:update: + run: dart tools/generate_version.dart + description: Updates packages/stream_feeds/lib/src/version.dart from its pubspec.yaml version. + postclean: run: melos run clean:flutter --no-select description: Runs "flutter clean" in all Flutter packages diff --git a/packages/stream_feeds/CHANGELOG.md b/packages/stream_feeds/CHANGELOG.md index a4a8489f..94cc0e12 100644 --- a/packages/stream_feeds/CHANGELOG.md +++ b/packages/stream_feeds/CHANGELOG.md @@ -60,6 +60,10 @@ the new names at your earliest convenience. - Raised the minimum Dart SDK to `^3.12.0`. +### 🐞 Fixed + +- Fixed the `X-Stream-Client` header values: the SDK identifier was duplicated, the version was hardcoded, and the OS was never reported. + ## 0.5.1 - Added missing state updates for the websocket events. - Add appeal-related methods to moderation client: `appeal`, `getAppeal`, and `queryAppeals`. diff --git a/packages/stream_feeds/lib/src/client/feeds_client_impl.dart b/packages/stream_feeds/lib/src/client/feeds_client_impl.dart index ad47700e..63de304c 100644 --- a/packages/stream_feeds/lib/src/client/feeds_client_impl.dart +++ b/packages/stream_feeds/lib/src/client/feeds_client_impl.dart @@ -59,6 +59,7 @@ import '../state/query/members_query.dart'; import '../state/query/moderation_configs_query.dart'; import '../state/query/poll_votes_query.dart'; import '../state/query/polls_query.dart'; +import '../version.dart'; import '../ws/feeds_ws_event.dart'; import 'endpoint_config.dart'; @@ -220,12 +221,15 @@ class StreamFeedsClientImpl implements StreamFeedsClient { late final PollsRepository _pollsRepository; late final CapabilitiesRepository _capabilitiesRepository; - // TODO: Fill this with correct values + static const _sdkName = 'stream-feeds'; + static const _sdkIdentifier = 'dart'; + late final _systemEnvironmentManager = SystemEnvironmentManager( - environment: const SystemEnvironment( - sdkName: 'stream-feeds-dart', - sdkIdentifier: 'dart', - sdkVersion: '0.3.0', + environment: SystemEnvironment( + sdkName: _sdkName, + sdkIdentifier: _sdkIdentifier, + sdkVersion: packageVersion, + osName: CurrentPlatform.operatingSystem, ), ); diff --git a/packages/stream_feeds/lib/src/feeds_client.dart b/packages/stream_feeds/lib/src/feeds_client.dart index b2a73054..ce60f95d 100644 --- a/packages/stream_feeds/lib/src/feeds_client.dart +++ b/packages/stream_feeds/lib/src/feeds_client.dart @@ -209,21 +209,29 @@ abstract interface class StreamFeedsClient { /// Updates the system environment information used by the client. /// - /// It allows you to set environment-specific information that will be - /// included in API requests, such as the application name, platform details, - /// and version information. + /// Sets the environment-specific information reported in the + /// `X-Stream-Client` header of API requests, such as the application name + /// and version, and the operating system and device details. + /// + /// [SystemEnvironment.sdkName], [SystemEnvironment.sdkIdentifier] and + /// [SystemEnvironment.sdkVersion] identify the SDK itself and are owned by + /// it, so pass through the values the SDK already reports rather than custom + /// ones. /// /// Example: /// ```dart /// client.updateSystemEnvironment( - /// SystemEnvironment( - /// name: 'my_app', - /// version: '1.0.0', + /// const SystemEnvironment( + /// sdkName: 'stream-feeds', + /// sdkIdentifier: 'dart', + /// sdkVersion: '0.5.1', + /// appName: 'my_app', + /// appVersion: '1.0.0', /// ), /// ); /// ``` /// - /// See [SystemEnvironment] for more information on the available fields. + /// See [SystemEnvironment] for the available fields. void updateSystemEnvironment(SystemEnvironment environment); /// Establishes a connection to the Stream service. diff --git a/packages/stream_feeds/lib/src/version.dart b/packages/stream_feeds/lib/src/version.dart new file mode 100644 index 00000000..8d331eff --- /dev/null +++ b/packages/stream_feeds/lib/src/version.dart @@ -0,0 +1,13 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// To regenerate, run: dart tools/generate_version.dart + +// ************************************************************************** +// VersionGenerator +// ************************************************************************** + +/// Current `stream_feeds` package version. +/// +/// Reported as the SDK version in the `X-Stream-Client` header. Kept in sync +/// with `pubspec.yaml` by `tools/generate_version.dart`, which runs on every +/// `melos bootstrap`. +const String packageVersion = '0.5.1'; diff --git a/pubspec.lock b/pubspec.lock index a1419934..bb1350d0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -154,7 +154,7 @@ packages: source: hosted version: "2.0.5" path: - dependency: transitive + dependency: "direct dev" description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" @@ -266,7 +266,7 @@ packages: source: hosted version: "1.1.1" yaml: - dependency: transitive + dependency: "direct dev" description: name: yaml sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce diff --git a/pubspec.yaml b/pubspec.yaml index 3899e6ca..94bbec49 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,3 +5,6 @@ environment: dev_dependencies: melos: ^6.2.0 + # Used by tools/generate_version.dart. + path: ^1.9.0 + yaml: ^3.1.3 diff --git a/tools/generate_version.dart b/tools/generate_version.dart new file mode 100644 index 00000000..97f99cf5 --- /dev/null +++ b/tools/generate_version.dart @@ -0,0 +1,45 @@ +// ignore_for_file: avoid_print + +import 'dart:io' show Directory, File; + +import 'package:path/path.dart' as p; +import 'package:yaml/yaml.dart'; + +/// Updates the version constant in stream_feeds/lib/src/version.dart based on +/// the version in its pubspec.yaml file. +Future main() async { + // Target the stream_feeds package + const packageName = 'stream_feeds'; + final rootDir = Directory.current.path; + final packageDir = p.join(rootDir, 'packages', packageName); + final pubspecPath = p.join(packageDir, 'pubspec.yaml'); + final versionFilePath = p.join(packageDir, 'lib', 'src', 'version.dart'); + + print('Reading version from $pubspecPath'); + + // Read version from pubspec.yaml + final yamlMap = loadYaml(File(pubspecPath).readAsStringSync()) as YamlMap; + final version = yamlMap['version'] as String; + + print('Found version: $version'); + + // Read the existing version file + final versionFile = File(versionFilePath); + if (!versionFile.existsSync()) { + print('Error: Version file not found at $versionFilePath'); + return; + } + + final fileContent = versionFile.readAsStringSync(); + + // Update the version constant + final updatedContent = fileContent.replaceFirst( + RegExp('const String packageVersion = .+;'), + "const String packageVersion = '$version';", + ); + + // Write the changes back to the file + await versionFile.writeAsString(updatedContent); + + print('✓ Successfully updated version to $version in $versionFilePath'); +}