@expofp/debug 3.1.11 → 3.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ export type GlobalSettingSchema = {
2
+ type: 'boolean';
3
+ label?: string;
4
+ default?: boolean;
5
+ } | {
6
+ type: 'string';
7
+ label?: string;
8
+ default?: string;
9
+ placeholder?: string;
10
+ } | {
11
+ type: 'enum';
12
+ label?: string;
13
+ values: readonly string[];
14
+ default: string;
15
+ };
16
+ export interface EfpDebugGlobal {
17
+ settings?: Record<string, GlobalSettingSchema>;
18
+ }
19
+ declare global {
20
+ interface Window {
21
+ efpDebug?: EfpDebugGlobal;
22
+ }
23
+ }
24
+ export declare function adoptGlobalSettings(): void;
25
+ //# sourceMappingURL=adopt-global-settings.d.ts.map
@@ -0,0 +1,41 @@
1
+ import { registerBooleanSetting } from './register-boolean-setting.js';
2
+ import { registerEnumSetting } from './register-enum-setting.js';
3
+ import { registerStringSetting } from './register-string-setting.js';
4
+ const adopted = new Set();
5
+ export function adoptGlobalSettings() {
6
+ if (typeof window === 'undefined')
7
+ return;
8
+ const settings = window.efpDebug?.settings;
9
+ if (!settings)
10
+ return;
11
+ for (const [key, schema] of Object.entries(settings)) {
12
+ if (adopted.has(key))
13
+ continue;
14
+ adopted.add(key);
15
+ switch (schema.type) {
16
+ case 'boolean':
17
+ registerBooleanSetting({
18
+ key,
19
+ label: schema.label,
20
+ default: schema.default,
21
+ });
22
+ break;
23
+ case 'string':
24
+ registerStringSetting({
25
+ key,
26
+ label: schema.label,
27
+ default: schema.default,
28
+ placeholder: schema.placeholder,
29
+ });
30
+ break;
31
+ case 'enum':
32
+ registerEnumSetting({
33
+ key,
34
+ label: schema.label,
35
+ values: schema.values,
36
+ default: schema.default,
37
+ });
38
+ break;
39
+ }
40
+ }
41
+ }
@@ -1,6 +1,7 @@
1
+ export * from './adopt-global-settings.js';
1
2
  export * from './register-boolean-setting.js';
2
- export * from './register-debug-namespaces-setting.js';
3
3
  export * from './register-enum-setting.js';
4
4
  export * from './register-setting.js';
5
+ export * from './register-string-setting.js';
5
6
  export * from './reset-all-settings.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1,5 +1,6 @@
1
+ export * from './adopt-global-settings.js';
1
2
  export * from './register-boolean-setting.js';
2
- export * from './register-debug-namespaces-setting.js';
3
3
  export * from './register-enum-setting.js';
4
4
  export * from './register-setting.js';
5
+ export * from './register-string-setting.js';
5
6
  export * from './reset-all-settings.js';
@@ -1,3 +1,9 @@
1
1
  import { type DebugSetting } from './register-setting.js';
2
- export declare function registerBooleanSetting(label: string): DebugSetting<boolean>;
2
+ export interface RegisterBooleanSettingOptions {
3
+ key: string;
4
+ label?: string;
5
+ default?: boolean;
6
+ onChange?: (value: boolean) => void;
7
+ }
8
+ export declare function registerBooleanSetting(options: RegisterBooleanSettingOptions): DebugSetting<boolean>;
3
9
  //# sourceMappingURL=register-boolean-setting.d.ts.map
@@ -1,8 +1,14 @@
1
1
  import React from 'react';
2
2
  import { registerSetting } from './register-setting.js';
3
- export function registerBooleanSetting(label) {
3
+ export function registerBooleanSetting(options) {
4
4
  const BooleanEditorLazy = React.lazy(() => import('../ui/boolean-editor.js').then((mod) => ({
5
5
  default: mod.BooleanEditor,
6
6
  })));
7
- return registerSetting(label, false, BooleanEditorLazy);
7
+ return registerSetting({
8
+ key: options.key,
9
+ label: options.label,
10
+ default: options.default ?? false,
11
+ Editor: BooleanEditorLazy,
12
+ onChange: options.onChange,
13
+ });
8
14
  }
@@ -1,3 +1,10 @@
1
1
  import { type DebugSetting } from './register-setting.js';
2
- export declare function registerEnumSetting<T>(label: string, values: readonly T[], defaultValue: T): DebugSetting<T>;
2
+ export interface RegisterEnumSettingOptions<T> {
3
+ key: string;
4
+ label?: string;
5
+ values: readonly T[];
6
+ default: T;
7
+ onChange?: (value: T) => void;
8
+ }
9
+ export declare function registerEnumSetting<T>(options: RegisterEnumSettingOptions<T>): DebugSetting<T>;
3
10
  //# sourceMappingURL=register-enum-setting.d.ts.map
@@ -1,10 +1,15 @@
1
1
  import React from 'react';
2
2
  import { registerSetting } from './register-setting.js';
3
- export function registerEnumSetting(label, values, defaultValue) {
3
+ export function registerEnumSetting(options) {
4
4
  const EnumEditorLazy = React.lazy(() => import('../ui/enum-editor.js').then((mod) => ({
5
5
  default: mod.EnumEditor,
6
6
  })));
7
- return registerSetting(label, defaultValue, EnumEditorLazy, {
8
- values,
7
+ return registerSetting({
8
+ key: options.key,
9
+ label: options.label,
10
+ default: options.default,
11
+ Editor: EnumEditorLazy,
12
+ context: { values: options.values },
13
+ onChange: options.onChange,
9
14
  });
10
15
  }
@@ -5,5 +5,15 @@ export interface DebugSetting<T> {
5
5
  reset: () => void;
6
6
  useState: () => [T, (value: T) => void];
7
7
  }
8
- export declare function registerSetting<T, K = void>(label: string, defaultValue: T, Editor: React.FC<EditorProps<T, K>>, context?: K): DebugSetting<T>;
8
+ export interface RegisterSettingOptions<T, K = void> {
9
+ key: string;
10
+ label?: string;
11
+ default: T;
12
+ Editor: React.FC<EditorProps<T, K>>;
13
+ context?: K;
14
+ onChange?: (value: T) => void;
15
+ serialize?: (value: T) => string;
16
+ deserialize?: (raw: string) => T;
17
+ }
18
+ export declare function registerSetting<T, K = void>(options: RegisterSettingOptions<T, K>): DebugSetting<T>;
9
19
  //# sourceMappingURL=register-setting.d.ts.map
@@ -2,15 +2,28 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from 'react';
3
3
  import { editors, resets } from './setting-registry.js';
4
4
  const LOCAL_STORAGE_EVENT = 'efp-local-storage';
5
- export function registerSetting(label, defaultValue, Editor, context) {
6
- const key = `efp-debug-setting-"${label}"`;
7
- const get = () => tryJsonParse(localStorage.getItem(key), defaultValue);
5
+ export function registerSetting(options) {
6
+ const { key, default: defaultValue, Editor, context, onChange, serialize = JSON.stringify, deserialize = (raw) => JSON.parse(raw), } = options;
7
+ const label = options.label ?? key;
8
+ const get = () => {
9
+ const raw = localStorage.getItem(key);
10
+ if (raw === null)
11
+ return defaultValue;
12
+ try {
13
+ return deserialize(raw);
14
+ }
15
+ catch {
16
+ return defaultValue;
17
+ }
18
+ };
8
19
  const set = (value) => {
9
- localStorage.setItem(key, JSON.stringify(value));
20
+ localStorage.setItem(key, serialize(value));
21
+ onChange?.(value);
10
22
  emitLocalStorageChange(key);
11
23
  };
12
24
  const reset = () => {
13
25
  localStorage.removeItem(key);
26
+ onChange?.(defaultValue);
14
27
  emitLocalStorageChange(key);
15
28
  };
16
29
  resets.push(reset);
@@ -38,7 +51,6 @@ export function registerSetting(label, defaultValue, Editor, context) {
38
51
  }
39
52
  const EditorImpl = () => {
40
53
  const [state, setState] = useLocalStorageState();
41
- // context is always provided by callers that register an Editor expecting it
42
54
  return _jsx(Editor, { label: label, value: state, context: context, onChange: setState });
43
55
  };
44
56
  EditorImpl.displayName = `DebugSetting(${label})`;
@@ -50,16 +62,6 @@ export function registerSetting(label, defaultValue, Editor, context) {
50
62
  useState: useLocalStorageState,
51
63
  };
52
64
  }
53
- function tryJsonParse(str, fallback) {
54
- if (str === null)
55
- return fallback;
56
- try {
57
- return JSON.parse(str);
58
- }
59
- catch {
60
- return fallback;
61
- }
62
- }
63
65
  function emitLocalStorageChange(key) {
64
66
  window.dispatchEvent(new CustomEvent(LOCAL_STORAGE_EVENT, { detail: { key } }));
65
67
  }
@@ -0,0 +1,10 @@
1
+ import { type DebugSetting } from './register-setting.js';
2
+ export interface RegisterStringSettingOptions {
3
+ key: string;
4
+ label?: string;
5
+ default?: string;
6
+ placeholder?: string;
7
+ onChange?: (value: string) => void;
8
+ }
9
+ export declare function registerStringSetting(options: RegisterStringSettingOptions): DebugSetting<string>;
10
+ //# sourceMappingURL=register-string-setting.d.ts.map
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { registerSetting } from './register-setting.js';
3
+ export function registerStringSetting(options) {
4
+ const StringEditorLazy = React.lazy(() => import('../ui/string-editor.js').then((mod) => ({
5
+ default: mod.StringEditor,
6
+ })));
7
+ return registerSetting({
8
+ key: options.key,
9
+ label: options.label,
10
+ default: options.default ?? '',
11
+ Editor: StringEditorLazy,
12
+ context: { placeholder: options.placeholder },
13
+ onChange: options.onChange,
14
+ serialize: (v) => v,
15
+ deserialize: (v) => v,
16
+ });
17
+ }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { registerBooleanSetting } from '../settings/index.js';
3
- import { registerDebugNamespacesSetting } from '../settings/register-debug-namespaces-setting.js';
2
+ import debug from 'debug';
3
+ import { registerBooleanSetting, registerStringSetting } from '../settings/index.js';
4
4
  import { addDebugSecretListener } from '../utils/add-debug-secret-listener.js';
5
5
  let rendered = false;
6
6
  export function renderDebugUi() {
@@ -8,8 +8,21 @@ export function renderDebugUi() {
8
8
  return;
9
9
  }
10
10
  rendered = true;
11
- const showDebugButtonSetting = registerBooleanSetting('Show Debug Button Overlay');
12
- registerDebugNamespacesSetting();
11
+ const showDebugButtonSetting = registerBooleanSetting({
12
+ key: 'efp:show-debug-button',
13
+ label: 'Show Debug Button Overlay',
14
+ });
15
+ registerStringSetting({
16
+ key: 'debug',
17
+ label: 'Debug namespaces',
18
+ placeholder: 'e.g. efp:*',
19
+ onChange: (value) => {
20
+ if (value)
21
+ debug.enable(value);
22
+ else
23
+ debug.disable();
24
+ },
25
+ });
13
26
  const render = async (open) => {
14
27
  const { DebugUi } = await import('./debug-ui.js');
15
28
  const { createRoot } = await import('react-dom/client');
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Skeleton } from '@radix-ui/themes';
3
3
  import { Suspense } from 'react';
4
+ import { adoptGlobalSettings } from '../settings/adopt-global-settings.js';
4
5
  import { editors } from '../settings/setting-registry.js';
5
6
  export const SettingsList = () => {
7
+ adoptGlobalSettings();
6
8
  return editors.map((Editor, index) => (_jsx(Suspense, { fallback: _jsx(Skeleton, { height: "60px" }), children: _jsx(Editor, {}) }, index)));
7
9
  };
@@ -0,0 +1,5 @@
1
+ import type { EditorProps } from '../settings/editor-props.js';
2
+ export declare const StringEditor: React.FC<EditorProps<string, {
3
+ placeholder?: string;
4
+ }>>;
5
+ //# sourceMappingURL=string-editor.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { TextField } from '@radix-ui/themes';
3
+ import { SettingsItem } from './settings-item.js';
4
+ export const StringEditor = (props) => {
5
+ return (_jsx(SettingsItem, { label: props.label, children: _jsx(TextField.Root, { placeholder: props.context?.placeholder, value: props.value, onChange: (e) => props.onChange(e.target.value), style: { minWidth: 220 } }) }));
6
+ };
7
+ StringEditor.displayName = 'StringEditor';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expofp/debug",
3
- "version": "3.1.11",
3
+ "version": "3.1.13",
4
4
  "type": "module",
5
5
  "description": "ExpoFP SDK internal: debug utilities",
6
6
  "homepage": "https://developer.expofp.com/",
@@ -1,6 +0,0 @@
1
- export declare const STORAGE_KEY = "debug";
2
- export declare const LOCAL_STORAGE_EVENT = "efp-local-storage";
3
- export declare function registerDebugNamespacesSetting(): void;
4
- export declare function getDebugNamespaces(): string;
5
- export declare function setDebugNamespaces(pattern: string): void;
6
- //# sourceMappingURL=register-debug-namespaces-setting.d.ts.map
@@ -1,26 +0,0 @@
1
- import debug from 'debug';
2
- import React from 'react';
3
- import { editors, resets } from './setting-registry.js';
4
- export const STORAGE_KEY = 'debug';
5
- export const LOCAL_STORAGE_EVENT = 'efp-local-storage';
6
- export function registerDebugNamespacesSetting() {
7
- const DebugNamespacesEditorLazy = React.lazy(() => import('../ui/debug-namespaces-editor.js').then((mod) => ({
8
- default: mod.DebugNamespacesEditor,
9
- })));
10
- resets.push(() => setDebugNamespaces(''));
11
- editors.push(DebugNamespacesEditorLazy);
12
- }
13
- export function getDebugNamespaces() {
14
- return localStorage.getItem(STORAGE_KEY) ?? '';
15
- }
16
- export function setDebugNamespaces(pattern) {
17
- if (pattern) {
18
- localStorage.setItem(STORAGE_KEY, pattern);
19
- debug.enable(pattern);
20
- }
21
- else {
22
- localStorage.removeItem(STORAGE_KEY);
23
- debug.disable();
24
- }
25
- window.dispatchEvent(new CustomEvent(LOCAL_STORAGE_EVENT, { detail: { key: STORAGE_KEY } }));
26
- }
@@ -1,2 +0,0 @@
1
- export declare const DebugNamespacesEditor: React.FC;
2
- //# sourceMappingURL=debug-namespaces-editor.d.ts.map
@@ -1,32 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { TextField } from '@radix-ui/themes';
3
- import { useEffect, useState } from 'react';
4
- import { getDebugNamespaces, LOCAL_STORAGE_EVENT, setDebugNamespaces, STORAGE_KEY, } from '../settings/register-debug-namespaces-setting.js';
5
- import { SettingsItem } from './settings-item.js';
6
- export const DebugNamespacesEditor = () => {
7
- const [value, setValue] = useState(getDebugNamespaces);
8
- useEffect(() => {
9
- const update = () => setValue(getDebugNamespaces());
10
- const onLocal = (e) => {
11
- const detail = e.detail;
12
- if (detail?.key === STORAGE_KEY)
13
- update();
14
- };
15
- const onStorage = (e) => {
16
- if (e.key === STORAGE_KEY)
17
- update();
18
- };
19
- window.addEventListener('storage', onStorage);
20
- window.addEventListener(LOCAL_STORAGE_EVENT, onLocal);
21
- return () => {
22
- window.removeEventListener('storage', onStorage);
23
- window.removeEventListener(LOCAL_STORAGE_EVENT, onLocal);
24
- };
25
- }, []);
26
- return (_jsx(SettingsItem, { label: "Debug namespaces", children: _jsx(TextField.Root, { placeholder: "e.g. efp:*", value: value, onChange: (e) => {
27
- const next = e.target.value;
28
- setValue(next);
29
- setDebugNamespaces(next);
30
- }, style: { minWidth: 220 } }) }));
31
- };
32
- DebugNamespacesEditor.displayName = 'DebugNamespacesEditor';