Skip to content

feat(streams): add starter_pack user stream source with tag-aware IDs - #2391

Open
Orlandohub wants to merge 2 commits into
devfrom
feat/2386-starter-pack-stream-source
Open

feat(streams): add starter_pack user stream source with tag-aware IDs#2391
Orlandohub wants to merge 2 commits into
devfrom
feat/2386-starter-pack-stream-source

Conversation

@Orlandohub

@Orlandohub Orlandohub commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Changes

  • buildStarterPackStreamId(tags) (model helper): canonicalizes labels (trim/lowercase) and validates the full tag contract (1–5 tags, 1–20 chars, no banned chars) via Err.validation; emits starter_pack:all:all:<tags>.
  • createUserStreamParams: parses 4-part starter pack IDs, enforces all:all timeframe/reach segments, rejects noncanonical hand-built IDs; invalid-format fallthrough converted from raw Error to Err.validation.
  • NexusUserStreamService.fetch: dispatches starter_pack → new userStreamApi.starterPack (source=starter_pack&tags=…); switch default is now a never-checked Err.validation.
  • Config: STARTER_PACK_MAX_TAGS = 5 (Nexus contract) in src/config/nexus.ts.
  • Types: StarterPackStreamId extends the UserStreamId union; STARTER_PACK enum member and TUserStreamStarterPackParams in the Nexus service types.

Test plan

  • npm run typecheck — clean
  • ESLint + Prettier on touched files — clean
  • Helper suite: canonicalization, tag ordering, every rejection class (empty, over-limit, whitespace, overlength, delimiter-bearing, noncanonical)
  • Parser suite: ordered tags param, all:all segment enforcement, invalid timeframe/reach/source/label cases with AppError category/code assertions
  • Service suite: starter pack ID → source=starter_pack&tags=… via mocked queryNexus; endpoint count 10 → 11
  • Application suite (fake-indexeddb): reversed tag orders persist as distinct Dexie rows
  • Staging smoke: GET /v0/stream/users/ids?source=starter_pack&tags=bitcoin,art,music → 200 with user IDs; missing tags → 400

Notes

  • One pre-existing test was updated: the old "4+ parts is invalid" case now asserts the starter-pack-specific rejection; a 5-part case covers the format fallthrough.

Adds a 4-part user stream ID format (source:all:all:tag1,tag2) so
starter pack results can be cached per ordered tag list in Dexie.
While Nexus staging lacks the starter_pack source, a config flag keeps
IDs in a starter_pack_mock namespace served by most_followed, so stale
mock rows can never satisfy live requests after the swap (#2390).

Changes:
- buildStarterPackStreamId helper: canonicalizes (trim/lowercase) and
  validates tags (1-5, 1-20 chars, no banned chars) via Err.validation
- createUserStreamParams: parse/validate 4-part starter pack IDs,
  enforce all:all segments, reject noncanonical hand-built IDs
- NexusUserStreamService.fetch: dispatch starter_pack (live URL with
  tags param) and starter_pack_mock (most_followed, no tags param)
- STARTER_PACK_SOURCE_LIVE flag + STARTER_PACK_MAX_TAGS in config
- Tests: helper/parser/dispatch coverage + Dexie row isolation and
  mock-to-live swap regression at the application layer

Refs: #2386
@Orlandohub Orlandohub self-assigned this Aug 21, 2026
@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds tag-aware starter-pack user stream identifiers, parsing, Nexus dispatch, and isolated Dexie cache keys while temporarily routing the feature through most_followed.

  • Canonicalizes and validates ordered starter-pack tags.
  • Supports live and temporary mock stream namespaces.
  • Adds Nexus URL generation and service dispatch for starter-pack streams.
  • Covers validation, dispatch, pagination parameters, and cache isolation with tests.

Confidence Score: 5/5

The PR appears safe to merge; no concrete blocking or independently actionable non-blocking issue was identified.

The builder, parser, Nexus dispatch, and local cache all preserve the full ordered stream identity, while the temporary mock behavior consistently and intentionally aliases every tag selection to most_followed.

Important Files Changed

Filename Overview
src/config/nexus.ts Adds the backend tag limit and temporary live-source feature flag with explicit mock-to-live cache isolation.
src/core/models/stream/user/userStream.helper.ts Adds the canonical starter-pack stream-ID builder and validates tag count and labels.
src/core/models/stream/user/userStream.types.ts Extends user stream identifiers with distinct live and mock starter-pack namespaces.
src/core/services/nexus/stream/users/userStream.utils.ts Parses and validates four-part starter-pack IDs and produces source-specific Nexus parameters.
src/core/services/nexus/stream/users/userStream.ts Dispatches live starter packs to the new endpoint and temporary mock streams to most_followed.
src/core/services/nexus/stream/users/userStream.api.ts Adds URL construction for Nexus starter-pack requests.
src/core/application/stream/users/users.test.ts Verifies tag-order and mock/live namespaces remain isolated in Dexie.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Tags["Ordered interest tags"] --> Builder["buildStarterPackStreamId"]
  Builder --> MockId["starter_pack_mock:all:all:tags"]
  Builder -. "when live flag flips" .-> LiveId["starter_pack:all:all:tags"]
  MockId --> Parser["createUserStreamParams"]
  LiveId --> Parser
  Parser --> MockApi["most_followed request<br/>without tags"]
  Parser --> LiveApi["starter_pack request<br/>with ordered tags"]
  MockApi --> Nexus["Nexus"]
  LiveApi --> Nexus
  Nexus --> Dexie["Dexie row keyed by full stream ID"]
Loading

Reviews (1): Last reviewed commit: "feat(streams): add starter_pack user str..." | Re-trigger Greptile

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

URL: https://pubky-app-pr-2391-fzxmjul7ya-oa.a.run.app

pubky-app-pr-239157f2a7e

pubky/pubky-nexus#1024 is live on staging (verified: 200 with ordered
comma-separated tags, 400 when tags are missing), so the temporary
STARTER_PACK_SOURCE_LIVE flag, the starter_pack_mock cache namespace,
and the most_followed aliasing are no longer needed. Supersedes #2390.
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.

[Task]: Starter Packs — starter_pack user stream source with tag-aware stream IDs

1 participant