npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hero-dynamic-freamwork

v1.0.0

Published

Event orchestration layer for Formily JSON schemas.

Readme

Formily Event Framework with Global State Management

یک لایه رویدادی (Event Layer) برای Formily با قابلیت مدیریت state گلوبال.

ویژگی‌ها

  • ✅ اضافه کردن event handler های پویا به JSON Schema
  • ✅ مدیریت خطا و دیباگ آسان
  • Global State Management با $global
  • ✅ Reactive state updates
  • ✅ TypeScript support
  • ✅ React hooks برای دسترسی به state

نصب

npm install freamwork-formily

استفاده سریع

1. راه‌اندازی اولیه

import { EventRuntime, EventRuntimeProvider, GlobalStateManager } from 'freamwork-formily';

// ایجاد global state با مقادیر اولیه
const globalState = new GlobalStateManager({
  page1: {
    name: '',
    counter: 0
  }
});

// ایجاد runtime
const runtime = new EventRuntime({
  globalState,
  onError(error, meta) {
    console.error('Event error:', error, meta);
  }
});

function App() {
  return (
    <EventRuntimeProvider runtime={runtime}>
      {/* اپلیکیشن شما */}
    </EventRuntimeProvider>
  );
}

2. استفاده از $global در Schema

{
  "type": "object",
  "properties": {
    "username": {
      "type": "string",
      "title": "نام کاربری",
      "x-component": "Input",
      "x-component-props": {
        "events": [
          {
            "onChange": "{{$global.page1.name = event.target.value}}"
          }
        ]
      }
    },
    "submitButton": {
      "type": "void",
      "x-component": "Button",
      "x-component-props": {
        "children": "ثبت",
        "events": [
          {
            "onClick": "{{console.log('نام کاربر:', $global.page1.name)}}"
          }
        ]
      }
    }
  }
}

3. دسترسی به Global State در React

import { useGlobalState } from 'freamwork-formily';

function MyComponent() {
  const globalState = useGlobalState();
  const [name, setName] = useState('');

  useEffect(() => {
    // Subscribe به تغییرات
    const unsubscribe = globalState.subscribe((state) => {
      setName(state.page1?.name || '');
    });

    return unsubscribe;
  }, [globalState]);

  const updateName = () => {
    globalState.setState('page1.name', 'John Doe');
  };

  return (
    <div>
      <p>Name: {name}</p>
      <button onClick={updateName}>Update Name</button>
    </div>
  );
}

API Reference

GlobalStateManager

Constructor

const globalState = new GlobalStateManager(initialState);

Methods

getState()

دریافت کل state object

const state = globalState.getState();
setState(path, value)

تنظیم مقدار با dot notation

globalState.setState('user.profile.name', 'John');
globalState.setState('counter', 42);
getStateValue(path)

دریافت مقدار با dot notation

const name = globalState.getStateValue('user.profile.name');
merge(newState)

ادغام state جدید با state موجود

globalState.merge({
  page2: { title: 'New Page' }
});
reset(newState)

جایگزینی کامل state

globalState.reset({
  page1: { name: '', counter: 0 }
});
clear()

پاک کردن تمام state

globalState.clear();
subscribe(listener)

گوش دادن به تغییرات state

const unsubscribe = globalState.subscribe((state) => {
  console.log('State changed:', state);
});

// برای لغو subscription:
unsubscribe();

EventRuntime

Constructor Options

interface EventRuntimeOptions {
  defaults?: Partial<EventExecutionContext>;
  onError?: (error: unknown, meta: EventHandlerMeta & { code: string }) => void;
  globalState?: GlobalStateManager;
}

مثال:

const runtime = new EventRuntime({
  globalState: new GlobalStateManager({
    user: { isLoggedIn: false }
  }),
  defaults: {
    scope: {
      logger: console,
      api: myApiClient
    }
  },
  onError(error, meta) {
    console.error('Runtime error:', error);
    // ارسال به سیستم لاگ
  }
});

React Hooks

useEventRuntime()

const runtime = useEventRuntime();
const globalState = runtime.getGlobalState();

useGlobalState()

const globalState = useGlobalState();

مثال‌های پیشرفته

مثال 1: فرم با Validation

{
  "properties": {
    "email": {
      "type": "string",
      "title": "ایمیل",
      "x-component": "Input",
      "x-component-props": {
        "events": [
          {
            "onChange": "{{$global.form.email = event.target.value}}",
            "onBlur": "{{const isValid = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test($global.form.email); $global.form.emailValid = isValid; console.log('Email valid:', isValid)}}"
          }
        ]
      }
    }
  }
}

مثال 2: شمارنده با History

{
  "x-component-props": {
    "events": [
      {
        "onClick": "{{const newValue = ($global.counter || 0) + 1; $global.counter = newValue; $global.history = [...($global.history || []), newValue]; console.log('Counter history:', $global.history)}}"
      }
    ]
  }
}

مثال 3: دسترسی به API

const runtime = new EventRuntime({
  defaults: {
    scope: {
      api: {
        async fetchUser(id) {
          const response = await fetch(\`/api/users/\${id}\`);
          return response.json();
        }
      }
    }
  },
  globalState: new GlobalStateManager({
    users: {}
  })
});
{
  "x-component-props": {
    "events": [
      {
        "onClick": "{{scope.api.fetchUser(123).then(user => { $global.users[user.id] = user; })}}"
      }
    ]
  }
}

مثال 4: کامپوننت با Realtime Updates

function RealtimeCounter() {
  const globalState = useGlobalState();
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const unsubscribe = globalState.subscribe((state) => {
      setCounter(state.counter || 0);
    });

    // Initial value
    setCounter(globalState.getStateValue('counter') || 0);

    return unsubscribe;
  }, [globalState]);

  return (
    <div>
      <h2>Counter: {counter}</h2>
      <p>این شمارنده به صورت خودکار با تغییرات global state به‌روز می‌شود</p>
    </div>
  );
}

متغیرهای در دسترس در Event Handlers

در event handler های schema، متغیرهای زیر در دسترس هستند:

  • $global - Global state object
  • event - Event payload
  • form - Formily form instance
  • field - Current field instance
  • scope - Custom scope object
  • schema - Current schema node
  • path - Field path
  • meta - Additional metadata

Best Practices

1. ساختار State

// ✅ خوب - ساختار سازماندهی شده
const globalState = new GlobalStateManager({
  ui: {
    theme: 'light',
    sidebar: { collapsed: false }
  },
  data: {
    users: {},
    products: {}
  },
  temp: {
    searchQuery: ''
  }
});

// ❌ بد - flat و نامرتب
const globalState = new GlobalStateManager({
  theme: 'light',
  collapsed: false,
  users: {},
  searchQuery: ''
});

2. Error Handling

const runtime = new EventRuntime({
  globalState,
  onError(error, meta) {
    // لاگ کردن خطا
    console.error('Event error:', {
      error,
      path: meta.path,
      eventName: meta.eventName,
      code: meta.code
    });
    
    // ذخیره در monitoring service
    if (window.Sentry) {
      window.Sentry.captureException(error, {
        extra: meta
      });
    }
  }
});

3. TypeScript Support

interface AppGlobalState {
  user: {
    id: string;
    name: string;
    isLoggedIn: boolean;
  };
  ui: {
    theme: 'light' | 'dark';
    language: 'en' | 'fa';
  };
}

const globalState = new GlobalStateManager<AppGlobalState>({
  user: {
    id: '',
    name: '',
    isLoggedIn: false
  },
  ui: {
    theme: 'light',
    language: 'fa'
  }
});

4. Cleanup در Components

useEffect(() => {
  const unsubscribe = globalState.subscribe(listener);
  
  // حتماً cleanup کنید
  return () => {
    unsubscribe();
  };
}, [globalState]);

مشکلات رایج

مشکل: تغییرات state اعمال نمی‌شود

// ❌ اشتباه - مستقیماً به object اصلی دسترسی
const state = globalState.getState();
state.counter = 10; // این کار نمی‌کند!

// ✅ درست - از setState استفاده کنید
globalState.setState('counter', 10);

مشکل: Nested objects به‌روز نمی‌شوند

// ✅ درست - از dot notation استفاده کنید
globalState.setState('user.profile.name', 'John');

// یا از merge استفاده کنید
globalState.merge({
  user: {
    ...globalState.getStateValue('user'),
    profile: {
      ...globalState.getStateValue('user.profile'),
      name: 'John'
    }
  }
});

مجوز

ISC

مشارکت

مشارکت‌ها استقبال می‌شود! لطفاً یک issue یا pull request باز کنید.