Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reactotron plugin #349

Open
AldoMX opened this issue Apr 24, 2024 · 2 comments
Open

Reactotron plugin #349

AldoMX opened this issue Apr 24, 2024 · 2 comments

Comments

@AldoMX
Copy link

AldoMX commented Apr 24, 2024

Hi, I took the Reactotron plugin from here:
https://github.com/infinitered/reactotron/blob/master/lib/reactotron-react-native-mmkv/src/reactotron-react-native-mmkv.ts

And updated/adapted it to work with this mmkv package. I didn't open a PR because this was a quick-n-dirty update I made for myself, but I decided to share it in case someone else finds it useful.

// Taken from: https://github.com/infinitered/reactotron/blob/master/lib/reactotron-react-native-mmkv/src/reactotron-react-native-mmkv.ts
import { type MMKVInstance } from 'react-native-mmkv-storage';
import type { ReactotronCore } from 'reactotron-core-client';

export interface MmkvPluginConfig {
  /**
   * MMKV storage instance
   * @example
   * import { MMKVLoader } from "react-native-mmkv-storage"
   * const storage = new MMKVLoader().initialize()
   */
  storage: MMKVInstance;
  /** Storage keys you want to ignore */
  ignore?: string[];
}

/**
 * Reactotron plugin to log MMKV storage changes
 *
 * @example
 * import { MMKVLoader } from 'react-native-mmkv-storage'
 * import type { ReactotronReactNative } from 'reactotron-react-native'
 * // create your storage instance
 * const storage = new MMKVLoader().initialize()
 *
 * // pass your instance to the plugin
 * Reactotron.use(mmkvPlugin<ReactotronReactNative>({ storage }))
 */
export default function mmkvPlugin<Client extends ReactotronCore = ReactotronCore>(config: MmkvPluginConfig) {
  /** This gives us the ability to ignore specific writes for less noise */
  const ignore = config.ignore ?? [];

  const listeners: (() => void)[] = [];

  return (reactotron: Client) => {
    const logDelete = (key: string) => {
      if (ignore.includes(key)) return;
      reactotron.display({
        name: 'MMKV',
        value: { key },
        preview: `Delete "${key}"`,
        important: true,
      });
    };

    const logWrite = (key: string, value?: unknown) => {
      if (ignore.includes(key)) return;
      reactotron.display({
        name: 'MMKV',
        value: { key, value },
        preview: typeof value === 'object' ? `Set "${key}".` : `Set "${key}" to ${JSON.stringify(value)}`,
        important: true,
      });
      return value;
    };

    return {
      onConnect() {
        listeners.push(
          config.storage.transactions.register('_' as never, 'ondelete', logDelete),
          config.storage.transactions.register('string', 'onwrite', logWrite),
          config.storage.transactions.register('number', 'onwrite', logWrite),
          config.storage.transactions.register('object', 'onwrite', logWrite),
          config.storage.transactions.register('array', 'onwrite', logWrite),
          config.storage.transactions.register('boolean', 'onwrite', logWrite),
        );
      },
      onDisconnect() {
        for (const unregister of listeners) {
          unregister();
        }
        listeners.length = 0;
      },
    };
  };
}
@pnthach95
Copy link
Contributor

Can you create npm package?

@AldoMX
Copy link
Author

AldoMX commented May 3, 2024

I cannot create an npm package: transactions.register only allows a single listener per data type, so people which already have other listeners will see unintended side effects if they use this plugin.

I prefer to hand it over to whoever is interested in supporting it.

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

No branches or pull requests

2 participants