@devmedic/plugin-react-native
v0.1.0
Published
Official DevMedic plugin for React Native projects: framework metadata, project detection, configuration, and the first-party React Native rule pack.
Readme
@devmedic/plugin-react-native
The official DevMedic plugin for React Native projects. Integrates with the existing Plugin Framework — it doesn't modify Core, the Rule Engine, or the AST Engine.
import reactNativePlugin from '@devmedic/plugin-react-native';
// reactNativePlugin: { manifest, hooks, rules } — loadable by both
// @devmedic/plugin-sdk#loadPlugin and @devmedic/rule-engine#loadRuleModule
// from the same specifier.rules is the official React Native rule pack (Phase 12) — eleven rules
covering security (AsyncStorage tokens, WebView originWhitelist
wildcards, insecure HTTP URLs), correctness (missing keyExtractor,
console.log, uncleaned useEffect subscriptions), and performance/
architecture (Hermes disabled, oversized/duplicate images, unused
dependencies, an outdated react-native version). Every rule ships tests,
runnable examples, and an auto-fix where one is actually safe (only
console-log has one). See docs/rules.md for the full
list, including why five of them anchor their check to the project's entry
file instead of the file the Rule Engine handed them.
The manifest declares supportedProjectTypes: ['react-native', 'expo'],
supportedFileExtensions: ['.ts', '.tsx', '.js', '.jsx'],
supportedPlatforms: ['ios', 'android'], and
ignoredDirectories: ['tests', '__tests__', 'fixtures', '__fixtures__', 'generated']
— rules.ts propagates all four onto every rule this plugin exports. This
is Rule Isolation (@devmedic/rule-engine's execution plan): the
extension/directory fields are checked statically, with zero I/O, before
any file is even read; supportedProjectTypes/supportedPlatforms need a
projectGate (@devmedic/project-detection-engine#createProjectDetectionGate(),
wired in by devmedic). Together, this is what keeps these eleven
rules from ever running against a file outside a real React Native/Expo
project — or against their own test/fixture/generated-code scaffolding —
even though every rule and every other package live in the same monorepo.
Rule Metadata
Every rule declares the full @devmedic/rule-engine metadata contract —
extractRuleMetadata(rule) on any of the eleven produces a complete
RuleMetadata: documentationUrl (a github.com/devmedic/devmedic docs
link per rule), tags (e.g. ['security', 'storage', 'secrets'] for
async-storage-token), estimatedFixTime (rough minutes by hand — 1
for the auto-fixable console-log, up to 60 for outdated-version),
and references to the official docs/advisories each rule's rationale is
based on. sinceVersion and minimumRNVersion are inherited from the
manifest (0.1.0/0.70.0) by every rule that doesn't declare its own,
via rules.ts's withMetadataDefaults — the same mechanism that already
propagates supportedProjectTypes/supportedPlatforms/etc.
Only console-log sets fixable: true — it's the one rule whose fix()
does real work; the other ten always return null from fix(), so
fixable is false (or absent, which extractRuleMetadata defaults to
false) for all of them.
What this plugin registers
On initialize, it puts four things into the shared ServiceContainer so
host code and other plugins can look them up by token instead of depending
on this package directly:
| Registers | Token | What it is |
| ------------------------------ | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| React Native rules | reactNativeRulesToken | The eleven-rule Rule[] this plugin contributes. |
| React Native project detection | reactNativeProjectDetectionToken | isReactNativeProject(project: ProjectContext): boolean — a predicate over @devmedic/project-scanner's existing detection, not a new scan. |
| React Native metadata | reactNativeFrameworkMetadataToken | REACT_NATIVE_FRAMEWORK_METADATA — display name, signature files/dependencies, platform-specific file extensions. |
| React Native configuration | reactNativePluginConfigToken | This plugin's own validated options (enabled, platforms), parsed from context.config with a Zod schema. |
PluginContext carries no project root, so this plugin never scans a
filesystem itself — isReactNativeProject is registered as a predicate for
whoever already has a ProjectContext (from scanProject()) to call.
Configuration
// devmedic.config.ts
export default defineConfig({
plugins: [{ name: '@devmedic/plugin-react-native', options: { platforms: ['ios'] } }],
});| Option | Type | Default |
| ----------- | ------------------------ | -------------------- |
| enabled | boolean | true |
| platforms | ('ios' \| 'android')[] | ['ios', 'android'] |
Invalid options throw ReactNativePluginConfigError from the initialize
hook — isolated per-plugin by PluginRuntime, so it never crashes the host.
Depends on
@devmedic/plugin-sdk@devmedic/rule-engine@devmedic/parser-typescript@devmedic/project-scanner
