Releases: nocoo/xray
Releases · nocoo/xray
v1.9.4
[1.9.4] - 2026-03-24
Changed
- Add superset run config and tweet export script
- Update retrospective #24 with correct root cause and fix
- Add retrospective #24 — ReadableStream lock in vinext auth
Fixed
- Exclude all api routes from proxy to prevent body consumption
- Clone request in auth route handler to avoid ReadableStream lock
v1.9.2
v1.9.1
Refactored
- Remove dead code — deleted unused
auth-context.ts,useMutationhook,createE2EDb(), and 4 dead chart/palette exports - Extract shared utilities — consolidated duplicate functions into single shared implementations:
formatCount(4 copies → 1 inutils.ts)formatTimeAgo(4 copies → 1 inutils.ts, withcompact/long/coarsestyle variants)estimateTweetHeight(2 copies → 1 inutils.ts)pMap(2 copies → 1 inutils.ts)sseMessage(2 copies → 1 inapi-helpers.ts)maskSecret(2 copies → 1 incrypto.ts, withprefix/tailmode parameter)formatDate(2 copies → 1 inutils.ts)
Fixed
- AI key masking security — restored conservative tail-only masking for API keys in AI settings (only last 4 chars visible), preventing the prefix exposure introduced by the maskSecret consolidation
Tests
- 35 new tests covering all extracted shared utilities (
formatCount,formatTimeAgo× 3 styles,formatDate,estimateTweetHeight,pMap,maskSecret× 2 modes)
Docs
- Removed stale
useMutationreferences from README, CHANGELOG, and architecture docs
v1.9.0
What's New
Added
- Remove button on post cards — each post card now has a trash icon button (right-aligned, red hover) that deletes the post via
DELETE /api/watchlists/[id]/posts?postId=Nand removes it from the UI instantly - 90-day retention option — watchlist settings now support 90-day post retention in addition to the existing 1/3/7/15/30-day options
- Rich translation progress — translation pipeline rewritten with sliding-window concurrency and live SSE previews; new
startandtranslatingevents provide real-time feedback before each translation completes
Fixed
- "Translating 0/0" flash — eliminated the brief zero-count display that appeared at the start of batch translation
getDb()test conflict — resolved module-level database initialization conflict that caused test failures when importing from@/db
Tests
- 8 new
parseSSEBufferunit tests covering chunked streaming and edge cases - 5 new DELETE endpoint API tests (success, 404, 400, cross-watchlist rejection)
- 3 new
deleteByIdDB repository tests - 90-day retention acceptance test
- 7 new route tests for settings and posts endpoints
v1.8.0
Documentation
- Architecture doc rewritten — reflects current vinext + ScopedDB stack with updated module structure
- Overview doc updated — web dashboard as primary purpose, refreshed feature descriptions
- Run & scripts doc rewritten — web app workflow as primary, scripts as secondary
- Config doc rewritten — environment variables as primary configuration method
- Deployment doc updated — vinext build/start commands, TWEAPI_API_KEY env var, fixed version reference
- API doc updated — added 8 missing webhook API endpoints (lists, messages, conversation, credits, usage, analytics, bookmarks, likes)
- README refreshed — added missing features (lists, AI settings, webhooks, usage), test scripts, and docs reference
- Project structure tree updated — all pages, services, and directories reflected
- Removed obsolete migration plan (
07-xray-web.md) - Fixed playwright port, eslint version, and pre-push status in testing doc
- Added TWEAPI_API_KEY to
.env.exampleand README env vars section - Fixed Docker volume mount path and added required env vars to deployment doc
v1.7.0
[1.7.0] - 2026-03-06
Added
- vinext 0.0.21 upgrade — 12 versions of fixes from vinext 0.0.9, improving RSC compatibility, font handling, and route handler stability
Changed
- ESLint 9 → 10 — major ESLint upgrade with typescript-eslint bumped to 8.56.1
- AI SDK upgraded —
aiand@ai-sdk/openaibumped to latest patch versions - lucide-react 0.575.0 → 0.577.0 — icon library patch upgrade
- Semver ranges tightened —
typescriptnarrowed from^5.0.0to^5.9.3,vitefrom^7.0.0to^7.3.1to match installed versions - Unused dependencies removed —
@auth/drizzle-adapter,zod, and@vitejs/plugin-rscdropped from package.json
Fixed
- TweAPI key leak — removed hardcoded API key from source; now reads exclusively from
TWEAPI_API_KEYenv var
Documentation
- README updated with new preview image and refreshed feature list
- TweAPI acknowledgement added to README
Housekeeping
- Removed one-time migration script (
migrate-profiles.ts) - Cleaned up
.bfg-report/artifacts and added pattern to.gitignore
v1.6.1
What's New
Fixed
- Masonry column breakpoints — evenly spaced 3/4/5-col breakpoints at 512px intervals (1024/1536/2048) for balanced coverage across screen sizes; raised tall-screen bonus threshold to 5+ base cols so that the 4-column range is no longer skipped
v1.6.0
What's New
Added
- Unified TweetCard action bar — every tweet card now displays a consistent bottom bar with Open (external link), Translate (inline 信达雅), and zhe.to Save buttons; replaces per-page ad-hoc actions
- Generic
/api/translateendpoint — standalone translation route for any tweet by ID, decoupled from the watchlist pipeline - Linkify tweet text — URLs in tweet text (t.co and other https links) are now clickable with external link styling
- Photo hover zoom overlay — magnifying glass icon appears on hover over photo grid items
- Quoted tweet author clickable — quoted tweet author name and avatar now link to the user's X profile with external link icon
- Masonry layout for bookmarks & likes — bookmarks and likes pages now use the shared
MasonryGridcomponent for responsive column layout - Batch edit mode for groups — group detail page supports multi-select members with batch delete
followers.jsexport format — twitter export parser now supportsfollowers.jsin addition tofollowing.js- User-paced batch resolution — import dialog uses cooldown timer between batches and deduplicates by
twitterIdto avoid redundant API calls
Changed
(dashboard)route group — all authenticated pages moved intosrc/app/(dashboard)/with a sharedlayout.tsxanduseBreadcrumbshook, replacing per-page<AppShell>wrappers- WatchlistPostCard simplified — delegates rendering and action bar entirely to
TweetCard, reducing the component to a thin wrapper - Tweet type badges relocated — Reply, Quote, and Retweet badges moved from inline to the card's top-right corner
- Author row streamlined — external link icon removed from the tweet card author row (now available in the action bar)
- Watchlist header compressed — 5-zone header consolidated into a single toolbar row
Fixed
- Route group import paths — 15 TypeScript errors across 10 files from the
(dashboard)migration; allshared/typesrelative imports updated for the extra nesting level, and@/app/watchlist/alias corrected to@/app/(dashboard)/watchlist/ - Watchlist member CRUD reactivity — member add/edit/delete now uses local state updates instead of triggering a full page reload
- Twitter export parser — handles unquoted JS keys, trailing commas, and numeric IDs (resolves to real usernames before import)
- Import dedup — pre-filters export IDs against existing group members to skip already-imported users
- Batch resolve stability — reduced batch size to 10, added
AbortControllerfor instant cancel, removed drop zone opacity flash
v1.4.0
Added
- Activity assessment columns — Groups detail table now displays Likes, Last Tweet (relative time), and Activity badge (🟢 Active / 🟡 Low / 🔴 Inactive / — Unknown) computed from tweet recency and frequency
- Enhanced Tweets column — shows tweet count with average tweets/day calculated from account age
- Last tweet tracking —
last_tweet_atcolumn added totwitter_profilestable; populated during profile refresh by fetching the user's most recent tweet viafetchUserTweets - Add Members page — dedicated
/groups/[id]/addpage with 3-tab import flow: From Account (fetch following list), Manual (paste usernames), and Import File (drag-and-dropfollowing.js)
Changed
- Groups detail table enriched — profile avatars link to X profiles; @username and display name are clickable; Added column right-aligned; User header left-aligned
- Streaming profile refresh — refresh button now resolves members one-by-one with live progress instead of batch-then-render
- Inline add form removed — replaced by dedicated Add Members page accessible via header button
v1.3.0
What's New
Added
- Groups feature — full CRUD for user-defined groups (
groups+group_memberstables), with/groupslist page and/groups/[id]detail page featuring sortable table, search filter, and Twitter export import (drag-and-dropfollowing.js) - Twitter profile cache — shared
twitter_profilestable withProfilesRepofor global caching of Twitter user data; auto-upserts on everygetUserInfoand batch resolve call - Profile refresh —
POST /api/profiles/refreshfor manual profile snapshot updates; per-member refresh buttons on both Watchlist cards and Groups table rows with spinning indicator - Batch user resolution —
POST /api/explore/users/batchfor bulk username lookup (up to 500); powers import dialogs and profile refresh flows - Profile linking —
link-profilesAPI for both watchlists and groups; automatically resolvestwitter_idFK from cached profiles - Import from Twitter export — drag-and-drop or file picker for
following.jsdata export files on both Following and Groups pages;parseTwitterExportFile()extracted to shared lib - Zhe.to integration — settings page at
/integrations/zhetowith API key management, and save-to-zheto button in watchlist post-card action bar - Quote count metric —
quote_countadded to tweet card stats row - 71 new unit tests — 48 for GroupsRepo/GroupMembersRepo, 23 for ProfilesRepo
Changed
- Sidebar restructured — Watchlists and Groups promoted to top-level collapsible sections (matching
NavGroupSectionstyle); Following page replaced by Groups; Integrations added as new nav group - MemberCard enriched — displays profile avatar, display name, verified badge, follower count, bio snippet, and tags from cached
twitter_profilesdata - Batch resolve limit raised from 100 to 500 usernames per request
Fixed
- TweAPI domain — migration script corrected from
tweapi.comtoapi.tweapi.iowith proper camelCase field name mapping - Batch import errors — error messages now expose actual server response instead of generic failure text
- Sidebar section styling — icons removed from Watchlists/Groups section headers; padding aligned with NavGroupSection