chore: drop `@rocket.chat/string-helpers` in favor of `@rocket.chat/tools`

Merged
TA
2mo ago
+379-180

Proposed changes (including videos or screenshots)

@rocket.chat/string-helpers was a Fuselage package with four exports, all of them tiny pure string functions: escapeRegExp, escapeHTML, unescapeHTML and capitalize. This repo already has a home for exactly that kind of function — @rocket.chat/tools — and most of the files importing from string-helpers were already importing from tools on the line above.

So rather than moving the package here as its own workspace package, this PR absorbs it into @rocket.chat/tools and deletes the dependency. See Further comments for why this deviates from what ARCH-2361 describes.

Two commits do the work, and they are worth reading in order:

  1. feat(tools): embed functions from @rocket.chat/string-helpers — the four functions are copied into packages/tools/src, each with a spec file. The implementations are the published 0.32.0 ones, with the types tightened where the originals were loose:

    • capitalize is now generic, so it returns Capitalize<T> instead of string.
    • escapeHTML/unescapeHTML now take string instead of any; the runtime coercion they relied on is kept, moved into a small internal toString helper, so a nullish value passed from untyped JS still becomes '' rather than "undefined".
    • escapeRegExp keeps its behavior exactly (the spec pins the full escaped character set).
  2. chore: drop @rocket.chat/string-helpers in favor of @rocket.chat/tools — 122 files, almost entirely one-line import rewrites: 67 escapeRegExp, 29 escapeHTML, 14 capitalize, 2 unescapeHTML. The dependency is removed from nine package.jsons — apps/meteor, apps/meteor/ee/server/services, packages/models, ee/packages/omnichannel-services and the four ee/apps/* services (account, authorization, ddp-streamer, presence) — and @rocket.chat/tools is added to packages/models and packages/ui-client, the two consumers that did not already depend on it. fuselage.sh stops bumping the package, and it is gone from yarn.lock entirely — it was not a transitive dependency of anything else.

    Because the embedded signatures are tighter, a handful of type assertions that only existed to work around the old ones could go: capitalize(this.name) as Capitalize<TServiceName> in CustomOAuth, indexOf(_emoji as never) in the emoji helpers, and similar casts in packages/models. Those are the only non-import changes in the commit.

Issue(s)

ARCH-2361

Steps to test or reproduce

Nothing should change for the user — the functions are the same code, called from the same places.

  1. yarn workspace @rocket.chat/tools test — 14 suites, 118 tests, with the four new files at 100% coverage.
  2. yarn workspace @rocket.chat/meteor typecheck — clean. Same for @rocket.chat/models, @rocket.chat/ui-client and @rocket.chat/abac, the packages whose diffs are more than import rewrites.
  3. Anything that goes through the touched paths: search (spotlight, message search), emoji and custom emoji, mentions, markdown, highlighted words, message previews, OAuth service names in the login buttons, and the omnichannel admin tables.

Further comments

This is not the migration the ticket describes. ARCH-2361 is written as step 8 of 19 in the Fuselage migration: copy packages/string-helpers in, add the workspaces glob entry, keep the dual ESM/CJS build and the API report, flip consumers to workspace:^. It also owns repointing the package's npm trusted publisher from RocketChat/fuselage to RocketChat/Rocket.Chat.

Absorbing the package instead makes all of that unnecessary: there is no new workspace package to build, no API report to maintain, and the npm trusted-publishing repoint can be dropped from the migration plan — this package will never be published again from either repo. The tradeoff is that @rocket.chat/string-helpers stops existing as a published package after 0.32.0. Nothing outside Rocket.Chat and Fuselage consumes it, and Fuselage froze it in ARCH-2350, so I think that is the right call — but it is a plan change, not just an implementation detail, so flagging it explicitly for review. If we would rather keep the package alive as a published artifact, this PR should be replaced with the literal migration.

One follow-up is needed, not done here. apps/meteor/tests/end-to-end/api/http-response-truncation.ts replays a captured dynamic-import request whose body hardcodes a client module tree containing node_modules/@rocket.chat/string-helpers. That path no longer exists in the bundle. The test's own comment warns that these fixtures are build-dependent — if the tree changes, the response shrinks below the gzip threshold and loses the chunked+gzip shape the race needs, which is what its first assertion checks. The fixture has to be recaptured. I left it alone because it only runs under the specific traefik configuration it was written for, and recapturing it means reproducing that setup.

Summary by CodeRabbit

  • New Features

    • Added shared utilities for capitalizing text, converting values to strings, and escaping or unescaping HTML and regular expressions.
    • Expanded shared tooling exports for consistent text handling across the application.
  • Refactor

    • Consolidated text and escaping helpers without changing existing behavior.
    • Simplified internal type handling and removed obsolete helper usage.
  • Tests

    • Added comprehensive coverage for text conversion, capitalization, and HTML and regular-expression escaping utilities.