diff --git a/CHANGELOG.md b/CHANGELOG.md index 1709f3f..a3fd73f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Changelog -## Unreleased +## 0.3.0 (7 Nov 2026) -- `strait init` writes setup for today's SDKs: Android 0.9.0 (JitPack) and iOS 0.10.0 (SwiftPM), was 0.8.4 and 0.9.5; React Native 0.10.2 and Flutter 0.9.7 unchanged. `strait events add` reads the same versions and says the iOS/Android `eventId` needs them. +- `strait events add`: the Flutter snippet shows `eventId` (strait_sdk 0.10.0+ has it); the React Native one says `eventId` needs 0.11.0+. +- `strait init` writes setup for today's SDKs: Android 0.10.0 (JitPack), iOS 0.11.0 (SwiftPM), and Flutter 0.10.1 (was 0.8.4, 0.9.5 and 0.9.7); React Native stays 0.10.2 until 0.11.0 is on npm. `strait events add` reads the same versions and says the iOS/Android `eventId` needs them. - `strait test`: one pass/fail list that says you're set up right: the engine answers, the secret key is valid (which workspace, test or live), and the workspace's link domain serves apple-app-site-association and assetlinks.json. Exit 1 on any failure, `--json` for CI. - `strait events add `: prints ready-to-paste event tracking code for React Native, Flutter, iOS, Android or the web (detected from the project files, or `--platform`), using each SDK's real `trackEvent` call. - `strait events add --platform web` prints `@straitlink/web`'s new `trackEvent` instead of a hand-written `POST /v1/event` (needs the web SDK release that adds it). diff --git a/package.json b/package.json index 8239fe2..cef5e9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@straitlink/cli", - "version": "0.2.2", + "version": "0.3.0", "description": "Strait deep links from the terminal: init sets them up in a React Native, Expo, Flutter or Android app, doctor checks your link host, links creates and lists links and saves QR codes.", "keywords": [ "strait", diff --git a/src/events.mjs b/src/events.mjs index f06a1e4..df4fce3 100644 --- a/src/events.mjs +++ b/src/events.mjs @@ -1,7 +1,7 @@ // `strait events add `: prints ready-to-paste tracking code (ADR 0001). Each snippet is the // SDK's own call, read from its source on 5 Nov 2026: -// React Native 0.10 links.trackEvent(name, { value, currency, eventId }) src/strait.ts -// Flutter 0.9 links.trackEvent(name, value:, currency:, linkId:, clickId:) lib/src/client.dart (no eventId) +// React Native 0.11 links.trackEvent(name, { value, currency, eventId }) src/strait.ts (0.10.2: no eventId) +// Flutter 0.10 links.trackEvent(name, value:, currency:, linkId:, clickId:, eventId:) lib/src/client.dart // iOS 0.10 strait.trackEvent(_:value:currency:linkId:clickId:eventId:completion:) StraitLinks.swift // Android 0.8 client.trackEvent(name, value, currency, linkId, clickId, eventId) StraitClient.kt (blocks) // Web (Unreleased) trackEvent(config, name, { value, currency, eventId }) src/index.ts (sdk-web ADR 0002) @@ -68,13 +68,15 @@ const SNIPPETS = { 'react-native': (n) => `import { links } from './links'; // the client strait init wrote; fix the path for this file // Resolves true when Strait took it; never throws. For revenue add -// { value: 49.99, currency: 'USD', eventId: order.id } (eventId: a retry is counted once). +// { value: 49.99, currency: 'USD', eventId: order.id } (eventId: a retry is counted once; +// eventId needs ${PACKAGES.reactNative} 0.11.0+). await links.trackEvent('${n}'); `, flutter: (n) => `import 'links.dart'; // lib/links.dart, the client strait init wrote // Resolves true when Strait took it; never throws. For revenue add -// value: 49.99, currency: 'USD' +// value: 49.99, currency: 'USD', eventId: order.id (eventId: a retry is counted once; +// needs ${PACKAGES.flutter} 0.10.0+). await links.trackEvent('${n}'); `, ios: (n) => `// strait: your StraitLinks instance (strait-sdk-swift README, "Use"). Never throws. diff --git a/src/install.mjs b/src/install.mjs index 84c5ae6..c7ff918 100644 --- a/src/install.mjs +++ b/src/install.mjs @@ -22,10 +22,10 @@ export const sourceFor = (src, registry) => (typeof src.source === 'string' ? sr * `strait events add` reads them too: its iOS/Android eventId needs these SDKs. */ export const VERSIONS = { - version: '0.10.0', // Swift (Unity is not written by this CLI) + version: '0.11.0', // Swift (Unity is not written by this CLI) rnVersion: '0.10.2', - flutterVersion: '0.9.7', - androidVersion: '0.9.0', + flutterVersion: '0.10.1', + androidVersion: '0.10.0', }; export const PACKAGES = { diff --git a/src/version.mjs b/src/version.mjs index b51c72a..53e447a 100644 --- a/src/version.mjs +++ b/src/version.mjs @@ -1,2 +1,2 @@ // Kept equal to package.json version (test/links.test.mjs checks it). Sent as the API User-Agent. -export const CLI_VERSION = '0.2.2'; +export const CLI_VERSION = '0.3.0'; diff --git a/test/events.test.mjs b/test/events.test.mjs index 9045dab..e99f305 100644 --- a/test/events.test.mjs +++ b/test/events.test.mjs @@ -26,8 +26,8 @@ test('each platform prints its SDK\'s real event call with the name', async () = const want = { 'react-native': [/import \{ links \} from '\.\/links'/, /await links\.trackEvent\('purchase'\);/, /value: 49\.99, currency: 'USD', eventId: order\.id/], flutter: [/import 'links\.dart';/, /await links\.trackEvent\('purchase'\);/, /value: 49\.99, currency: 'USD'/], - ios: [/strait\.trackEvent\("purchase"\) \{ ok in/, /eventId: order\.id/, /StraitSDK 0\.10\.0\+/], - android: [/StraitLinks\.client\.trackEvent\("purchase"\)/, /off the main thread/, /eventId = order\.id/, /strait-sdk-android 0\.9\.0\+/], + ios: [/strait\.trackEvent\("purchase"\) \{ ok in/, /eventId: order\.id/, /StraitSDK 0\.11\.0\+/], + android: [/StraitLinks\.client\.trackEvent\("purchase"\)/, /off the main thread/, /eventId = order\.id/, /strait-sdk-android 0\.10\.0\+/], web: [/import \{ reportWebOpen, trackEvent \} from '@straitlink\/web'/, /await reportWebOpen\(strait\);/, /await trackEvent\(strait, 'purchase'\);/, /value: 49\.99, currency: 'USD', eventId: order\.id/], }; for (const [platform, patterns] of Object.entries(want)) { @@ -37,9 +37,12 @@ test('each platform prints its SDK\'s real event call with the name', async () = } }); -test('Flutter has no eventId parameter, so its snippet never shows one', async () => { - const r = await run(['add', 'purchase', '--platform', 'flutter', FIXTURES]); - assert.doesNotMatch(r.out, /eventId/); +test('Flutter 0.10 takes eventId; React Native names the version that has it', async () => { + const f = await run(['add', 'purchase', '--platform', 'flutter', FIXTURES]); + assert.match(f.out, /eventId: order\.id/); + assert.match(f.out, /strait_sdk 0\.10\.0\+/); + const rn = await run(['add', 'purchase', '--platform', 'react-native', FIXTURES]); + assert.match(rn.out, /@straitlink\/react-native 0\.11\.0\+/); }); test('detects the platform from the project files', async () => { diff --git a/test/init.test.mjs b/test/init.test.mjs index 6595a90..cfdfe63 100644 --- a/test/init.test.mjs +++ b/test/init.test.mjs @@ -83,8 +83,8 @@ test('Flutter: lib/links.dart, pubspec install from the constant, manifest alrea assert.match(dart, new RegExp(`publishableKey: '${KEY}'`)); assert.match(dart, /links\.onLink\.listen/); assert.match(dart, /didChangeAppLifecycleState\(AppLifecycleState state\) => _ctl\.add\(switch \(state\)/, 'flutter analyze: avoid_renaming_method_parameters'); - assert.match(dart, /\(strait_sdk 0\.9\.7\)/, 'header names the Flutter SDK version'); - assert.match(r.out, /strait_sdk: \^0\.9\.7\n/); + assert.match(dart, /\(strait_sdk 0\.10\.1\)/, 'header names the Flutter SDK version'); + assert.match(r.out, /strait_sdk: \^0\.10\.1\n/); for (const line of installSpecs().flutterPubspec.split('\n')) assert.ok(r.out.includes(` ${line}\n`), line); assert.match(r.out, /intent filters for acme\.strait\.link and acmeflutter:\/\/ are already there/); assert.match(r.out, /flutter_deeplinking_enabled" android:value="false"/); diff --git a/test/install.test.mjs b/test/install.test.mjs index 4afcf8e..ddcddd8 100644 --- a/test/install.test.mjs +++ b/test/install.test.mjs @@ -10,22 +10,22 @@ const root = fileURLToPath(new URL('..', import.meta.url)); const walk = (d) => readdirSync(d).flatMap((n) => (n === 'node_modules' || n === '.git' ? [] : statSync(join(d, n)).isDirectory() ? walk(join(d, n)) : [join(d, n)])); test('github and registry sources', () => { - // Versions as of 5 Nov 2026 (site.config.json packages = npm / pub.dev / JitPack): RN 0.10.2, Flutter 0.9.7, Android 0.9.0. + // Versions as of 7 Nov 2026 (site.config.json packages = npm / pub.dev / JitPack): RN 0.10.2, Flutter 0.10.1, Android 0.10.0. const gh = installSpecs({ source: 'github', githubOwner: 'strait-sdks' }); assert.equal(gh.reactNative, 'github:strait-sdks/strait-sdk-react-native#v0.10.2'); - assert.equal(gh.android, 'com.github.strait-sdks:strait-sdk-android:v0.9.0'); + assert.equal(gh.android, 'com.github.strait-sdks:strait-sdk-android:v0.10.0'); assert.equal(gh.androidRepository, 'https://jitpack.io'); - assert.match(gh.flutterPubspec, /url: https:\/\/github\.com\/strait-sdks\/strait-sdk-flutter\n {6}ref: v0\.9\.7/); + assert.match(gh.flutterPubspec, /url: https:\/\/github\.com\/strait-sdks\/strait-sdk-flutter\n {6}ref: v0\.10\.1/); const today = installSpecs(); assert.equal(today.reactNative, '@straitlink/react-native@0.10.2', 'npm in registry mode (16 Oct)'); - assert.equal(today.flutterPubspec, ' strait_sdk: ^0.9.7', 'pub.dev in registry mode (16 Oct)'); - assert.equal(today.android, `com.github.${INSTALL.githubOwner}:strait-sdk-android:v0.9.0`, 'Android stays on JitPack'); + assert.equal(today.flutterPubspec, ' strait_sdk: ^0.10.1', 'pub.dev in registry mode (16 Oct)'); + assert.equal(today.android, `com.github.${INSTALL.githubOwner}:strait-sdk-android:v0.10.0`, 'Android stays on JitPack'); const reg = installSpecs({ ...INSTALL, source: 'registry' }); assert.equal(reg.reactNative, '@straitlink/react-native@0.10.2'); - assert.equal(reg.android, 'in.straitlink:strait-sdk-android:0.9.0'); - assert.equal(reg.flutterPubspec, ' strait_sdk: ^0.9.7'); + assert.equal(reg.android, 'in.straitlink:strait-sdk-android:0.10.0'); + assert.equal(reg.flutterPubspec, ' strait_sdk: ^0.10.1'); assert.equal(reg.androidRepository, null); - assert.equal(VERSIONS.version, '0.10.0', 'Swift tag v0.10.0 (SwiftPM)'); + assert.equal(VERSIONS.version, '0.11.0', 'Swift tag v0.11.0 (SwiftPM)'); }); test('the owner is spelled out only in src/install.mjs', () => {