| type | Reference | ||||||
|---|---|---|---|---|---|---|---|
| title | Namespace API removal workflow | ||||||
| description | Cross-package requirements for removing the deprecated namespaced JS API and leaving a modular-only public surface — extends the change authoring workflow. | ||||||
| tags |
|
||||||
| timestamp | 2026-06-26 00:00:00 UTC |
Cross-package requirements for one module (or the final NF app cleanup). Shared loop: change authoring workflow.
Policy: OKF documentation and commit policy. Live gate snapshots: namespace API removal work queue (ephemeral).
| Topic | Document |
|---|---|
| Change authoring loop | change-authoring-workflow.md |
| Work type / tier / gate field ids | iteration-vocabulary.md |
| E2e commands | running-e2e.md |
| Validation commands | validation-checklist.md |
| Auth compare-types triage (N6) | packages/auth/compare-types-triage.md |
Remove (the namespaced surface):
| Surface | Where |
|---|---|
firebase.<module>() root accessor |
app root proxy + each package's firebase named export |
firebase.app().<module>() accessor |
app setOnAppCreate getters + declare module '@react-native-firebase/app' augmentation in lib/types/namespaced.ts |
default export <module>() |
lib/namespaced.ts export default |
Firebase<Module>Types namespace |
lib/types/namespaced.ts (or FirebaseXTypes block in an alt type file) |
| per-method deprecation warnings | createDeprecationProxy + mapOfDeprecationReplacements entry in packages/app/lib/common/index.ts |
KNOWN_NAMESPACES entry + createModuleNamespace() |
packages/app/lib/internal/constants.ts, each lib/namespaced.ts |
Keep (modular surface): getX(app?) / fn(instance, …) in lib/index.ts (modular-only entry — no separate lib/modular.ts), public types in lib/types/<module>.ts, statics as top-level named exports, native wiring.
Modular-only end-state templates: phone-number-verification (stateless — getReactNativeModule directly; modular.ts is the sole implementation file) and ai (instance object via getAI(app); single index.ts entry). Factory-based modules (ml, in-app-messaging, …) follow the ai pattern: merge former modular.ts into index.ts and delete modular.ts. vertexai is a deprecated re-export of ai.
Today modular getters route through the namespaced accessor + deprecation proxy (getApp().<module>() → createDeprecationProxy(new ModuleClass())). Modular-only removal must build the instance without the namespaced registry/proxy.
Decision (proven on ml): getOrCreateModularInstance(ModuleClass, config, app?, customUrlOrRegion?) in packages/app/lib/internal/registry/modular.ts. Memoises new ModuleClass(app, config) per app.name+key; resolves the app via the registry by name (with modular sentinel — see factory JSDoc); applies multi-app guard; clears cache via additive addOnAppDestroy. Each module's lib/index.ts owns its ModuleClass + ModuleConfig (modular-only — no lib/modular.ts). Stateless modules may skip the instance (phone-number-verification template).
In addition to change authoring gates:
| Gate | Requirement |
|---|---|
| Gap analysis | Every namespaced capability has a modular export; flag cross-module namespaced hops, constructor side-effects, module-level state, multi-app support |
| Baseline | Module Jest + (where native) area-focused e2e on every required platform; compare:types baseline if registered |
| Implementation | Atomic swap — never register in both namespaced registry and factory at once (duplicate constructor side-effects) |
| Review | Removal greps empty (below); no deprecation-proxy regression for other modules; compare:types unchanged-or-improved if registered |
| Documentation | Row in docs/migrating-to-v26.mdx → "namespaced removed"; reconcile v22 deprecation messaging |
rg "firebase\.<module>\(" packages/<module>
rg "createModuleNamespace|getFirebaseRoot" packages/<module>/lib
rg "Firebase<Module>Types" packages/<module>
rg "'<module>'" packages/app/lib/internal/constants.ts
test ! -f packages/<module>/lib/namespaced.ts && test ! -f packages/<module>/lib/types/namespaced.ts
test ! -f packages/<module>/lib/modular.tsRead-only. Enumerate namespaced surface (instance methods, getters, statics, default + firebase exports, Firebase<Module>Types). Confirm modular parity; list gaps to add first. Note whether getX() still delegates via getApp().<module>().
Complete modular-only checklist (one focused commit scope):
- Move
Firebase<Module>Module, constructor side-effects, module state, statics out ofnamespaced.tsintolib/index.ts. - Rewire
getX()inlib/index.tsvia the N0 factory (or native module directly) — notgetApp().<module>(); preserve.app/.native/.emitter/multi-app guards/side-effects. - Drop the module's
MODULAR_DEPRECATION_ARG/withModularFlagplumbing. - Delete
lib/namespaced.ts,lib/types/namespaced.ts, andlib/modular.ts; keeplib/index.tsas the sole public entry (import './types/internal'; export public types + statics). - Remove from
KNOWN_NAMESPACES,mapOfDeprecationReplacements, anddeclare module '@react-native-firebase/app'augmentation. __tests__: deletedescribe('namespace')+ deprecation-pair tests; keep/expand modular.type-test.ts: drop namespaced +Firebase<Module>Types.e2e: removefirebase v8 compatibilitysuite; keep/expand modular API suite.README.md+ inline doc snippets.
Unit-focused tier: Jest subset + tsc:compile + type-test.ts; package-scoped e2e when native touched. Per change authoring § implementation inner loop and module area harness when applicable.
On a frozen tree — change authoring § independent-review, plus removal greps and module-specific area-focused e2e on every required platform (no .only; no Android/macOS shortcuts). Resolve every finding, including minor/nit — fix it, or record a user-accepted exception (review findings); no self-authorized deferral — then delta re-review before commit.
Extends change authoring § harness narrowing. Mechanics: running e2e § local harness overrides.
When native e2e runs: load only the target package's e2e spec(s) in tests/app.js. Narrow platformSupportedModules on both if (Platform.other) and if (!Platform.other) (recommended: Pattern A — initial array + if (false && …) on both blocks). Set RNFBDebug = true locally per running e2e § fail-fast — never commit (false is the committed default). Revert both blocks before commit or full tier. Pass counts must match loaded scope — not full-app totals (running e2e § gate, platform coverage gate).
- User migration guide row under
docs/migrating-to-v26.mdx(one section per module) - Validation checklist § handoff —
yarn reference:api, static analysis, etc. when applicable - Durable learnings in this file or package OKF — not only commit messages
refactor(<module>): remove deprecated namespaced API
Before git commit:
- Validation evidence package recorded; coverage evidence package when lib/native bridge touched.
- Set the queue row's
commit_subjectto that exact line (replace<module>). - Close
commit_gateand update the header/next-pickup line in namespace API removal work queue. - Stage product, user docs, durable OKF learnings, and the queue doc together — one commit.
Never stage: area narrowing, any .only, ad-hoc harness edits, or RNFBDebug = true in tests/globals.js.
Only after N1–N6 modules committed and their greps empty. Same change-authoring loop; full tier for pre-merge.
- App namespaced surface: remove
firebase+ default frompackages/app/lib/index.ts/namespaced.ts; remove namespace plumbing fromregistry/namespace.ts; removeKNOWN_NAMESPACESfromconstants.tsandutils'screateModuleNamespace. - Deprecation machinery: remove
createDeprecationProxy,mapOfDeprecationReplacements,MODULAR_DEPRECATION_ARG/withModularFlag/warnIfNotModularCall, and related globals inglobal.d.ts+tests/globals.js. Retire single-slotsetOnAppDestroyin favor ofaddOnAppDestroy. - Pre-existing modular-only packages:
ai,vertexai, andphone-number-verificationshipped before N1–N6 but must match the same end-state as migrated modules — sole public entry islib/index.ts(noexport * from './modular'shim; deletelib/modular.tsafter inlining).typedoc.jsonentry points and internal imports must referencelib/index.tsonly. - Repo sweep:
rg "createModuleNamespace|createDeprecationProxy|KNOWN_NAMESPACES" packages/
rg "MODULAR_DEPRECATION_ARG|withModularFlag|warnIfNotModularCall" packages/
rg "RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS|RNFB_MODULAR_DEPRECATION_STRICT_MODE" .
rg "firebase\.(app\(\)\.)?\w+\(" packages/*/e2e packages/*/__tests__ tests/- Atomic swap: side-effect constructors (messaging headless task) — delete namespaced path in the same change as factory wiring.
- Cross-module namespaced hops (e.g.
firebase.utils(app)in messaging): re-point before dependency loses accessor. - Dual-exposed statics: keep modular export; remove namespaced/proxy path only.
compare:typesgap: only 10 packages registered — rely ontsc+type-test.tsfor the rest.- Factory parity: registry re-resolution by name; custom-URL validation deferred to N5 modules.
- macOS e2e (native-only modules): register a no-op
lib/web/stub viasetReactNativeModuleinlib/index.tsso macOS Jet can load and exercise modular JS without a native bridge (seein-app-messagingRNFBFiamModuleweb fallback). - Firestore on Other/macOS: Firestore Lite only on the web bridge — no full
firebase/firestore. Unsupported APIs reject withNot supported in the lite SDK.See Other platform Firestore Lite.