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

@judo/actions

v0.1.1

Published

> Action handler system and REST API client for JUDO UI Runtime

Readme

@judo/actions

Action handler system and REST API client for JUDO UI Runtime

Purpose

Provides the complete action handler system — a registry of 40 built-in action handler hooks (navigation, CRUD, relation, operation, form, selector, autocomplete, table, and other), a full REST API client (JudoRestApi), transfer serialization, path building, a React context provider for the API, lifecycle composition for action overrides, and dispatcher/handler hooks for wiring actions to UI components.

Architecture Layer

Layer 4 (Features) — depends on model-api; consumed by components and app-shell.

Dependencies

  • @judo/model-api — model type definitions (Action, ActionDefinition, ClassType, RelationType, etc.)
  • react ^19 — React (peer dependency)

Note: While handlers conceptually use services from core (navigation, data store), feedback (dialogs, notifications), and i18n (translations), these are not package dependencies. Handlers receive these services at runtime through the TypedActionHandlerContext object passed to each handler invocation.

File Structure

src/
├── index.ts                          # Root barrel export
├── types.ts                          # Core action types, interfaces, context shapes
├── api/
│   ├── types.ts                      # REST API types (HTTP, serialization, validation, query)
│   ├── constants.ts                  # REST header names and URL suffixes
│   ├── transfer-serializer.ts          # Default transfer serializer (strips internal props)
│   ├── judo-rest-api.ts              # JudoRestApi class (~870 lines) - full REST client
│   ├── model-converters.ts           # Convert model types → REST metadata (internal)
│   └── path-builder.ts              # REST URL path construction
├── hooks/
│   ├── use-action-dispatcher.ts      # useActionDispatcher hook
│   └── use-action-handler.ts         # useActionHandler hook + hasActionHandler
├── provider/
│   └── api-context.tsx               # ApiProvider + useApi context
├── registry/
│   └── action-handler-registry.ts    # Maps 40 action types → handler hooks
├── lifecycle/
│   └── execute-with-lifecycle.ts     # Lifecycle composition engine (before/execute/after/onError)
└── handlers/
    ├── navigation/                   # 4 handlers
    ├── form/                         # 3 handlers
    ├── selector/                     # 5 handlers
    ├── crud/                         # 7 handlers
    ├── relation/                     # 8 handlers
    ├── table/                        # 3 handlers
    ├── operation/                    # 5 handlers
    ├── autocomplete/                 # 3 handlers
    └── other/                        # 2 handlers

Exports Summary

Core Action Types

| Export | Kind | Description | | --------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ActionType | type | Union of 40 string literals — all action definition type names. | | DialogCloseResultType | type | "cancelled" \| "created" \| "updated" \| "deleted" \| "selected" \| "submitted" | | DialogCloseResult | type | Discriminated union for dialog/action outcomes. | | TypedActionHandlerContext | interface | Runtime context: transfer, selectedRows, closeDialog, navigation, data, registry, validation, notifications, isEager, pageType, isEditMode, isPageAction, createDialog, onDialogClose. | | ActionHandlerHookWithMeta | interface | Typed handler hook with .actionType metadata property for registration. | | ActionHandlerFactoryProperties | interface | Custom handler registration properties (by sourceId). | | BuiltInActionHandlerFactoryProperties | interface | Built-in handler registration properties (by actionType). | | ACTION_HANDLER_FACTORY | symbol | Service symbol for DI registration (re-exported from model-api). |

Lifecycle

| Export | Kind | Description | | ---------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------- | | executeWithLifecycle(defaultHandler, overrides, baseContext, action) | function | Composes lifecycle overrides (before/execute/after/onError) around a default handler. |

REST API Client

| Export | Kind | Description | | --------------------------- | --------- | ---------------------------------------------------------------------------------------------- | | JudoRestApi (class) | class | Full REST client (~870 lines) with 25+ methods covering all JUDO REST operations. | | createJudoRestApi(config) | function | Factory function for JudoRestApi. | | JudoRestApiConfig | interface | Config: baseUrl, application: Application, optional interceptors, serializer/deserializer. |

Key REST methods:

| Method | REST Endpoint | Description | | ------------------------------------------------------- | -------------------------------------- | --------------------------------------------- | | getTemplate(classType) | GET /{classPath}/~template | Fetch template for new transfer | | refresh(classType, target, qc?) | POST /{classPath}/~get | Refresh stored transfer by signed ID | | update(classType, target, mask?) | POST /{classPath}/~update | Update existing transfer | | validateUpdate(classType, target) | POST /{classPath}/~validate | Server-side update validation | | delete(classType, target) | POST /{classPath}/~delete | Delete transfer | | listRelation(relation, owner?, qc?, countRecords?) | POST /…/{relation}/~list | List transfers in relation | | getRelation(relation, owner, qc?) | POST /…/{relation}/~get | Get single-valued relation | | refreshAccessRelation(relation, qc?) | POST /…/{relation}/~get | Get non-collection access relation (no owner) | | getRelationRange(relation, owner?, qc?) | POST /…/{relation}/~range | Fetch range for selectors | | getRelationTemplate(relation) | GET /{targetClassPath}/~template | Get template for relation target | | createRelation(relation, owner, data, mask?) | POST /…/~create | Create transfer in relation | | validateCreateRelation(relation, owner, data) | POST /…/~validate | Validate create before persisting | | setRelation(relation, owner, selected) | POST /…/~update/{relation}/~set | Set single-valued relation | | unsetRelation(relation, owner) | POST /…/~update/{relation}/~unset | Clear single-valued relation | | addToRelation(relation, owner, selected) | POST /…/~update/{relation}/~add | Add to collection relation | | removeFromRelation(relation, owner, selected) | POST /…/~update/{relation}/~remove | Remove from collection relation | | exportRelation(relation, owner?, qc?) | POST /…/{relation}/~export | Export relation data as blob | | invokeOperation(classType, op, owner?, input?) | POST /{classPath}/{opName} | Invoke operation | | validateOperationInput(classType, op, owner?, input?) | POST /{classPath}/{opName}/~validate | Validate operation input | | getOperationInputTemplate(operation) | GET /{inputClassPath}/~template | Get template for operation input | | getOperationInputRange(classType, op, owner?, qc?) | POST /{classPath}/{opName}/~range | Fetch range for operation selector | | getPrincipal() | GET /{actorPath}/~principal | Get current principal | | getMetadata() | GET /{actorPath}/~meta | Get application metadata | | uploadFile(attributePath, file) | Two-step upload with token | Upload binary data | | downloadFile(downloadToken, disposition?) | GET /download?disposition=… | Download binary data | | findInstance(relation, identifier, mask?) | POST /…/{relation}/~list | Find transfer by business identifier |

Transfer Serialization (internal to api/ module)

These are exported from api/index.ts but not from the package's main entry point:

| Export | Kind | Description | | ------------------------------- | ------------ | ---------------------------------------------------------------------------------------------- | | BACKEND_PROPERTIES | constant Set | __identifier, __entityType, __deleteable, __updateable, __version — never send back. | | FRONTEND_PROPERTIES | constant Set | __tempId, __isNew, __items — client-only, never serialize. | | INTERNAL_PROPERTIES | constant Set | Union of both sets. | | isInternalProperty(key) | function | Returns true for any internal prop (keeps __signedIdentifier). | | stripInternalProperties(data) | function | Creates a new object without internal props. | | defaultTransferSerializer | constant | Serializer that strips top-level internal properties (handles arrays by mapping). |

Path Building

| Function | Description | | ------------------------------------------------------------------- | ---------------------------------------------------- | | getPathForActor(application, path?) | Builds /{modelName}/{actorPath}{path} | | getRelationPath(relation, application, suffix) | REST path for relation read endpoints | | getClassPath(classType, application, suffix) | REST path for class endpoints | | getMutationRelationPath(relation, application, suffix, isAccess?) | Mutation path with /~update/ prefix for non-access | | getOperationPath(classType, operationName, application, suffix?) | REST path for operation invocations |

API Validation

| Export | Kind | Description | | ------------------------- | --------- | ----------------------------------------------------------------------------- | | ValidationError (class) | class | Extends Error with status, feedbackItems, and toFieldErrors() method. | | FeedbackItem | interface | { code, level, location, message } from server responses. |

React Hooks

| Hook | Description | | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | useActionDispatcher(options) | Returns { dispatch, canHandle }. Resolves handlers from registry, builds context, calls handlers. Supports lifecycle overrides via actionOverrides option. | | useActionHandler(action) | Returns the handler function for a single action. Throws if no handler found. | | hasActionHandler(action) | Checks whether a handler exists in the registry. |

React Provider

| Export | Kind | Description | | ------------- | --------- | ----------------------------------------------------- | | ApiProvider | component | Provides JudoRestApi via React context. | | useApi() | hook | Consumes the API context; throws if outside provider. |

Built-in Action Handler Hooks (40 total)

Navigation (4)

| Handler | Action Type | Description | | ----------------------------- | ----------------------------- | --------------------------------------------------------------------- | | useBackActionHandler | BackActionDefinition | Closes dialog if open, otherwise goBack | | useOpenPageActionHandler | OpenPageActionDefinition | Navigates to target page with transfer params; forwards eager context | | useRowOpenPageActionHandler | RowOpenPageActionDefinition | Same as above but for table row clicks | | useCancelActionHandler | CancelActionDefinition | Closes dialog → or resets transfer (VIEW edit mode) → or goBack |

Form (3)

| Handler | Action Type | Description | | ---------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------- | | useOpenFormActionHandler | OpenFormActionDefinition | Opens form dialog for editing | | useOpenCreateFormActionHandler | OpenCreateFormActionDefinition | Opens create form dialog; supports eager/lazy modes with onDialogClose | | useOpenOperationInputFormActionHandler | OpenOperationInputFormActionDefinition | Opens form for operation input parameters |

Selector (5)

| Handler | Action Type | Description | | -------------------------------------------- | -------------------------------------------- | ------------------------------------------------ | | useOpenSelectorActionHandler | OpenSelectorActionDefinition | Opens single-selection dialog | | useOpenAddSelectorActionHandler | OpenAddSelectorActionDefinition | Opens multi-selection dialog for add | | useOpenSetSelectorActionHandler | OpenSetSelectorActionDefinition | Opens selection dialog for set | | useOpenOperationInputSelectorActionHandler | OpenOperationInputSelectorActionDefinition | Opens selector for operation input | | useSelectorRangeActionHandler | SelectorRangeActionDefinition | Fetches range data via REST (or legacy callback) |

CRUD (7)

| Handler | Action Type | Description | | ----------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | useRefreshActionHandler | RefreshActionDefinition | Four modes: access relation list, transfer relation list, selector range, single transfer refresh. Eager mode seeds from parent store. | | useCreateActionHandler | CreateActionDefinition | Eager (local with validation) or lazy (REST) create with validation flow | | useUpdateActionHandler | UpdateActionDefinition | Eager (parent update) or lazy (REST update + refresh). Reads transfer from data store via pageTransferId. | | useDeleteActionHandler | DeleteActionDefinition | REST delete, clears from store, navigates back | | useBulkDeleteActionHandler | BulkDeleteActionDefinition | Deletes all selected rows via parallel REST calls | | useRowDeleteActionHandler | RowDeleteActionDefinition | Eager (remove from parent) or lazy (REST delete) single row | | useGetTemplateActionHandler | GetTemplateActionDefinition | Fetches default values via REST; stores at pageTransferId |

Relation (8)

| Handler | Action Type | Description | | --------------------------------- | --------------------------------- | ------------------------------------------------------------ | | useSetActionHandler | SetActionDefinition | Sets single-valued relation; closes dialog with "selected" | | useUnsetActionHandler | UnsetActionDefinition | Clears single-valued relation | | useAddActionHandler | AddActionDefinition | Adds to collection relation; closes dialog with "selected" | | useRemoveActionHandler | RemoveActionDefinition | Eager (remove from parent array) or lazy (REST remove) | | useBulkRemoveActionHandler | BulkRemoveActionDefinition | Eager or lazy removal of multiple selected transfers | | useClearActionHandler | ClearActionDefinition | Clears all transfers from relation via unsetRelation | | useRefreshRelationActionHandler | RefreshRelationActionDefinition | Refreshes relation data (list or get based on cardinality) | | useFilterRelationActionHandler | FilterRelationActionDefinition | Signals filter intent via onFilterRelation callback |

Table (3)

| Handler | Action Type | Description | | --------------------------------- | --------------------------------- | ------------------------------------------------------------ | | useFilterActionHandler | FilterActionDefinition | Signals filter intent via onFilterRequest callback | | useExportActionHandler | ExportActionDefinition | Exports via REST, triggers browser download | | useInlineCreateRowActionHandler | InlineCreateRowActionDefinition | Signals inline row creation via onInlineCreateRow callback |

Operation (5)

| Handler | Action Type | Description | | -------------------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------- | | useCallOperationActionHandler | CallOperationActionDefinition | Invokes bound operation via REST; opens output dialog if result + targetPage | | useBulkCallOperationActionHandler | BulkCallOperationActionDefinition | Invokes operation on each selected row in parallel | | useInputFormCallOperationActionHandler | InputFormCallOperationActionDefinition | Invokes operation with form input; closes dialog only on success | | useInputSelectorCallOperationActionHandler | InputSelectorCallOperationActionDefinition | Invokes operation with selected transfer; closes dialog only on success | | useParameterlessCallOperationActionHandler | ParameterlessCallOperationActionDefinition | Invokes operation with no input |

Autocomplete (3)

| Handler | Action Type | Description | | ----------------------------------- | ----------------------------------- | ----------------------------------------------- | | useAutocompleteRangeActionHandler | AutocompleteRangeActionDefinition | Fetches range for autocomplete with search text | | useAutocompleteSetActionHandler | AutocompleteSetActionDefinition | Sets single-valued relation via autocomplete | | useAutocompleteAddActionHandler | AutocompleteAddActionDefinition | Adds to collection via autocomplete |

Other (2)

| Handler | Action Type | Description | | -------------------------- | -------------------------- | ------------------------------------------ | | usePreFetchActionHandler | PreFetchActionDefinition | Pre-fetches data via onPreFetch callback | | useCustomActionHandler | CustomActionDefinition | Delegates to onCustomAction callback |

Key Patterns

  • Hook factory pattern: Every handler is (action) => (context) => Promise<void>. React hooks at the outer level; async handler at the inner level.
  • Discriminated union dispatch: Internal registry maps @type → handler hook. 40 entries cover all action types.
  • Eager vs Lazy: CRUD and relation handlers distinguish between eager (local aggregated, no REST) and lazy (REST-persisted) modes.
  • Transfer serialization: defaultTransferSerializer strips all __* properties except __signedIdentifier.
  • Validation error flow: ValidationError auto-parses 400 responses. Handlers set field errors on ValidationContext.
  • Path construction: getRelationPath/getClassPath/getMutationRelationPath compose REST URLs from model metadata.
  • Context casting: Handlers cast TypedActionHandlerContext to local interfaces for mode-specific properties (eager, selector, API, legacy callbacks).
  • React context for API: ApiProvider/useApi decouple handler instantiation from API configuration.
  • Lifecycle composition: executeWithLifecycle wraps built-in handlers with before/execute/after/onError hooks for customization.
  • Legacy callback support: All handlers support both legacy callbacks (on*) and API mode, enabling incremental migration.