# `supplierAutomat` > **Source File**: [`src/automats/supplierAutomat.js`](file:///home/seb/src/dashfront/src/automats/supplierAutomat.js) > **Registration Key**: `'supplier'` (`Automat.get('supplier')` / `window.__AUTOMATS__.get('supplier')`) --- ## 1. Overview & Purpose `supplierAutomat` manages the supplier directory for the active company (`GET /api/supplier`). Suppliers are used when receiving deliveries, reconciling purchase invoices, and organizing supplier-specific article catalogs. ### Core Responsibilities - **Company Scoping & Auth Sync**: Caches suppliers for the selected company and automatically invalidates or re-fetches when switching companies or logging out. - **In-flight Deduplication**: Multiple components invoking `load()` concurrently share a single HTTP request promise (`inflightLoad`). - **Full CRUD Support**: Creating, updating (renaming), and deleting suppliers with automatic cache refresh. - **Silent Background Refreshes**: `reload()` updates supplier lists in the background without clearing current state. --- ## 2. State Structure ```ts interface Supplier { id: string | number; name: string; [key: string]: any; } interface SupplierState { /** Company suppliers list. */ suppliers: Array; /** Async lifecycle phase. */ status: 'idle' | 'loading' | 'ready' | 'failed'; /** Last error object if load failed. */ error: Error | null; } ``` ### Initial State ```js const initialState = { suppliers: [], status: 'idle', error: null, }; ``` --- ## 3. Configuration & Options ```js new Automat(initialState, actions, { name: 'supplier' }); ``` - **`name`**: `'supplier'` - **`persist`**: `false` --- ## 4. Actions & Methods Access actions via `supplierAutomat.actions.()`. ### `load(): Promise>` Loads the supplier list via `GET /api/supplier`. Deduplicates concurrent callers: if a request is already in flight, it returns the existing promise. Sets `status` to `'ready'` on success. ### `reload(): Promise>` Silently re-fetches the supplier list without setting `status` back to `'loading'`. Preserves the current list until the new response arrives. ### `create(body: { name: string }): Promise` Creates a new supplier via `POST /api/supplier`, waits for `reload()`, and returns the newly created supplier object. ### `update(id: string | number, body: { name: string }): Promise` Updates supplier details via `PATCH /api/supplier/:id`, waits for `reload()`, and returns the updated supplier. ### `remove(id: string | number): Promise` Deletes a supplier via `DELETE /api/supplier/:id` and triggers `reload()`. ### `setSuppliers(suppliers: Array): void` Directly replaces the cached supplier array without a network round-trip. ### `clear(): void` Resets the state back to `initialState`. --- ## 5. Cross-Automat Subscriptions `supplierAutomat` tracks `authAutomat` through `syncWithAuth`: ```js function authKey(authState) { if (authState?.status !== 'authed' || !authState.user) return null; const companyId = authState.user.selectedCompanyId; return companyId == null ? null : String(companyId); } function syncWithAuth(authState) { const key = authKey(authState); if (key === lastAuthKey) return; lastAuthKey = key; if (key == null) { supplierAutomat.actions.clear(); } else { void supplierAutomat.actions.load().catch(() => {}); } } authAutomat.subscribe(syncWithAuth); syncWithAuth(authAutomat.state); ``` Whenever the user authenticates with a company, suppliers load automatically; when logging out, they clear. --- ## 6. Usage Examples ### A. React `PureComponent` Supplier Dropdown ```jsx import { PureComponent } from 'react'; import PropTypes from 'prop-types'; import supplierAutomat from '../automats/supplierAutomat'; export class SupplierDropdown extends PureComponent { static propTypes = { value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), onChange: PropTypes.func.isRequired, }; constructor(props) { super(props); this.state = { suppliers: supplierAutomat.state.suppliers, status: supplierAutomat.state.status, }; } componentDidMount() { this.unsub = supplierAutomat.subscribe(this, ['suppliers', 'status']); if (this.state.status === 'idle') { supplierAutomat.actions.load().catch(console.error); } } componentWillUnmount() { this.unsub?.(); } render() { const { suppliers, status } = this.state; const { value, onChange } = this.props; if (status === 'loading') { return ; } return ( ); } } ``` ### B. Creating a Supplier ```js import supplierAutomat from '../automats/supplierAutomat'; async function addNewSupplier(name) { try { const supplier = await supplierAutomat.actions.create({ name }); console.log('Supplier created:', supplier); } catch (err) { console.error('Failed to create supplier:', err); } } ``` --- ## 7. Best Practices & Gotchas 1. **Automatic Refresh**: `create`, `update`, and `remove` automatically call `reload()`, so subscribers will receive the updated list without manual re-querying. 2. **Inflight Safety**: You can safely call `supplierAutomat.actions.load()` in multiple components mounted at the same time without causing duplicate HTTP requests.