Skip to content

Latest commit

 

History

History
2369 lines (1841 loc) · 68 KB

File metadata and controls

2369 lines (1841 loc) · 68 KB

CLAUDEDB - API Quick Reference

Purpose: Common functions/hooks with signatures + direct links Rule: Function signature + link to documentation


Reactium API

Window & Breakpoint Utilities

conditionalWindow()
// Returns window or undefined (SSR-safe)
// Returns: Window | undefined

Window/Breakpoint: SSR-Safe Accessors

conditionalDocument()
// Returns document or undefined (SSR-safe)
// Returns: Document | undefined

Window/Breakpoint: SSR-Safe Accessors

isWindow(iWindow?)
// Checks if window exists
// Returns: boolean

Window/Breakpoint: Window Existence Check

isElectronWindow(iWindow?)
// Detects Electron environment
// Returns: boolean

Window/Breakpoint: Electron Detection

breakpoint(width?, iWindow?, iDocument?)
// Returns current breakpoint name for given width
// width: number (optional, defaults to window.innerWidth)
// Returns: 'xs' | 'sm' | 'md' | 'lg' | 'xl'

Window/Breakpoint: Determine Current Breakpoint

breakpoints(iWindow?)
// Returns breakpoint configuration object
// Returns: { xs: number, sm: number, md: number, lg: number, xl: number }

Window/Breakpoint: Runtime Breakpoint Access

useWindow()
// React hook for context-aware window access
// Returns: Window | undefined

Window/Breakpoint: useWindow Hook

useDocument()
// React hook for context-aware document access
// Returns: Document | undefined

Window/Breakpoint: useDocument Hook

useBreakpoints()
// React hook for breakpoint configuration
// Returns: { xs: number, sm: number, md: number, lg: number, xl: number }

Window/Breakpoint: useBreakpoints Hook

useBreakpoint(width)
// React hook to get breakpoint for specific width
// width: number
// Returns: 'xs' | 'sm' | 'md' | 'lg' | 'xl'

Window/Breakpoint: useBreakpoint Hook

useWindowSize({ defaultWidth?, defaultHeight?, delay? })
// React hook for reactive window dimensions and breakpoint
// defaultWidth: number (default: 1) - Width when window undefined
// defaultHeight: number (default: 1) - Height when window undefined
// delay: number (default: 0) - Debounce delay in ms
// Returns: { width, height, breakpoint, scrollX?, scrollY? }

Window/Breakpoint: useWindowSize Hook

Component Registration

Reactium.Component.register(name, component);
// Registers component in global Component Registry

hookableComponent: Registration Pattern

Reactium.Component.get(name, defaultComponent?)
// Retrieves component from registry
// Returns: Component or defaultComponent

hookableComponent: Component Registry

Reactium.Component.unregister(name);
// Removes component from registry

hookableComponent: Component Registry

useHookComponent(name, defaultComponent?)
// Hook that retrieves component (non-reactive)
// Returns: Component from registry or defaultComponent

hookableComponent: useHookComponent Hook

hookableComponent(name);
// Factory that creates wrapper component
// Returns: Component that dynamically retrieves from registry

hookableComponent: hookableComponent Factory

Events & Communication

// ComponentEvent - Type-safe custom event with payload flattening
new ComponentEvent<T>(type, payload?)
// Creates CustomEvent where payload properties are flattened onto event
// Access: event.myProp instead of event.detail.myProp
// Prototype pollution protection: filters __proto__ and proto__
// Property collision: prefixes conflicting keys with __

ComponentEvent System: Overview

useEventEffect<Target>(target, handlers, deps?)
// Manages addEventListener/removeEventListener with automatic cleanup
// handlers: { eventName: callback, ... }
// Returns: void

ComponentEvent: useEventEffect Hook

isTarget(target);
// Checks if target has addEventListener/removeEventListener
// Returns: boolean

ComponentEvent: isTarget Helper

State Management

// ReactiumSyncState - Observable state (EventTarget-based)
new ReactiumSyncState<T>(initialState, options?)
state.get<T>(path, defaultValue?)        // Get value at path
state.set(path, value, update?, forceMerge?)  // Set value with merge
state.del(path, update?)                 // Delete path
state.insert(path, value, index, update?)     // Array insertion
state.reset()                            // Reset to initial
state.extend(prop, method)               // Add custom method
state.dispatch(type, payload?)           // Manual event dispatch (uses ComponentEvent)
state.addEventListener(type, listener, options?, id?)  // Subscribe
state.removeEventListenerById(type, id)  // Unsubscribe by ID
// Events: before-set, set, change, before-del, del, before-insert, insert

ReactiumSyncState ArchitectureReactiumSyncState: Core APIReactiumSyncState: Event System

useSyncState < T > (initialState, (updateEvent = 'set'));
// Returns: ReactiumSyncState<T> (with get/set methods)

Reactium: useSyncStateReactiumSyncState: useSyncState IntegrationGotchas: useSyncState Is Not useState

Reactium.State.get(key);
Reactium.State.set(key, value);
useGlobalState(key);

Reactium: Global StateReactiumSyncState: Global State Singleton

Preferences (LocalStorage)

// Prefs - Simple localStorage wrapper with object-path addressing
Reactium.Prefs.get<T>(key?, defaultValue?)
// Get preference by object-path or all prefs
// key: 'admin.sidebar.status' or 'my.nested.value'
// Returns: T (preference value or defaultValue)

Prefs System: get() method

Reactium.Prefs.set < T > (key, value);
// Set preference at object-path, persists to localStorage
// key: 'admin.sidebar.status' or 'my.nested.value'
// Returns: PrefsType (entire prefs object)

Prefs System: set() method

Reactium.Prefs.clear(key?)
// Clear specific path or entire prefs
// key?: Optional object-path to clear
// Returns: PrefsType (updated prefs object)

Prefs System: clear() method

Reactium.Prefs.create < PrefsType > storageKey;
// Factory for isolated Prefs instance with custom localStorage key
// Returns: PrefsClass<PrefsType>

Prefs System: create() method

Important: Prefs is NOT reactive. Changes don't trigger React re-renders. → Prefs System: Common Gotchas

Handle System

new Handle(id, initialState)
Handle.register(id, handle)
Handle.get(id)
useHandle(id)  // No subscription
useSyncHandle(id)  // With subscription
useSelectHandle(id, selector, defaultValue?)  // Optimized - only re-renders on selected value change
// Returns: { handle, selected }

Reactium: HandlesGotchas: useHandle vs useSyncHandleFAQ: useSelectHandle Performance

Reactium.Pulse.on(event, callback);
Reactium.Pulse.emit(event, data);
Reactium.Pulse.off(event, callback);

Reactium: Pulse

Browser Utilities

Reactium.Prefs.get(key, defaultValue?)
Reactium.Prefs.set(key, value)
Reactium.Prefs.clear(key)
// LocalStorage wrapper with reactivity

Reactium: The Reactium SDK

Reactium.Fullscreen.isFullScreen()
Reactium.Fullscreen.enter(element?)
Reactium.Fullscreen.exit()
Reactium.Fullscreen.toggle(element?)

Reactium: The Reactium SDK

// Window size & breakpoint utilities
Reactium.Window.get('width');
Reactium.Window.get('height');
Reactium.breakpoint; // Current breakpoint name

Reactium: The Reactium SDK

// cxFactory - Namespaced classname generation
const cx = Reactium.Utils.cxFactory('my-component');
cx()                         // → 'my-component'
cx('header')                 // → 'my-component-header'
cx('title', { active: true}) // → 'my-component-title my-component-active'

Utility Helpers: cxFactory APIUtility Helpers: cxFactory Usage

// SplitParts - Token-based string templates
const template = Reactium.Utils.splitParts('Hello %name%, you have %count% messages');
template.replace('name', 'Alice');
template.replace({ count: 5 });
template.toString();     // → 'Hello Alice, you have 5 messages'
template.value();        // → Part[] array for React rendering
template.reset();        // Reset to original

Utility Helpers: SplitParts APIUtility Helpers: SplitParts Usage

Utility Hooks

// useAsyncEffect - Async side effects with mount safety
useAsyncEffect(async (isMounted) => {
    const data = await fetch('/api');
    if (!isMounted()) return;
    setData(data);
}, [deps]);

Utility Hooks: useAsyncEffect

// useEventEffect - Event listener management
useEventEffect(
    target,
    {
        click: (e) => console.log('clicked'),
        keydown: (e) => console.log('key:', e.key)
    },
    [deps]
);

Utility Hooks: useEventEffect

// useFulfilledObject - Wait for object properties
const [ready, obj, attempts] = useFulfilledObject(
    stateRef.current,
    ['user.profile', 'settings.loaded'],
    100 // poll interval ms
);

Utility Hooks: useFulfilledObject

// useIsContainer - DOM hierarchy checking
const isInside = useIsContainer(element, container);
if (!isInside) closePopover();

Utility Hooks: useIsContainer

// useScrollToggle - Body scroll control
const scroll = useScrollToggle();
scroll.disable(); // Freeze scroll (for modals)
scroll.enable();  // Restore scroll
scroll.toggle();  // Toggle state

Utility Hooks: useScrollToggle

Internationalization (i18n)

// __() - Singular translation
import { __ } from '@atomic-reactor/reactium-core/sdk';

const translated = __('Welcome to Reactium');
// Returns: Translated string or original if no translation
// param text: string literal (must NOT be a variable)
// Returns: string

i18n System: __() Singular Translation

// _n() - Plural translation
import { _n } from '@atomic-reactor/reactium-core/sdk';

const label = _n('%s item', '%s items', count);
// Params:
//   singular: string literal (singular form)
//   plural: string literal (plural form)
//   count: number
// Returns: string (appropriate plural form for locale)

i18n System: _n() Plural Translation

// Integration with SplitParts for dynamic content
const template = Reactium.Utils.splitParts(__('Hello %name%, you have %count% messages'));
template.replace({ name: 'Alice', count: 5 });
template.toString();
// → "Hello Alice, you have 5 messages" (translated)

i18n System: Integration with SplitParts

// CLI extraction command
// npx reactium i18n
// Extracts all __() and _n() strings to src/reactium-translations/template.pot

i18n System: CLI Extraction Command

// set-default-locale hook - Customize locale detection
Reactium.Hook.register('set-default-locale', async (i18nInstance) => {
    // Override locale from URL query param or user preference
    i18nInstance.locale = 'fr_FR';
});

i18n System: Hook Integration

SDK Extension

// Pattern 1: Direct SDK extension
Reactium.Hook.register(
  'sdk-init',
  async (SDK) => {
    const { default: MyFeature } = await import('./sdk');
    Reactium.MyFeature = MyFeature;
  },
  Reactium.Enums.highest,
  'MY-SDK-EXTENSION-ID'
);

SDK Extension: Direct Extension

// Pattern 2: APIRegistry extension
Reactium.API.register('MyAPI', { api: apiClient, config: apiConfig });
// Access via:
Reactium.API.MyAPI; // → apiClient
Reactium.API.MyAPIConfig; // → apiConfig
Reactium.MyAPI; // → fallback via Proxy

SDK Extension: APIRegistry ExtensionSDK Extension: SDK Proxy Fallback Chain

Hooks

Reactium.Hook.register(
  name, // string
  callback, // async function
  priority, // number (default: Enums.priority.neutral)
  id, // string (optional, auto-generated)
  domain // string (default: 'default')
);
// Returns: hookId (string)

Reactium: Hook RegistrationHook Domains Deep Dive

Reactium.Hook.registerSync(name, callback, priority, id, domain);

Reactium: Hook Registration

await Reactium.Hook.run(name, ...args);
// Returns: context object

Reactium: Hook Execution

Reactium.Hook.runSync(name, ...args);

Reactium: Hook Execution

Reactium.Hook.unregister(hookId);
// Unregister single hook by ID

Reactium.Hook.unregisterDomain(hookName, domain);
// Unregister all hooks in domain for specific hook name

Reactium.Hook.flush(hookName, (type = 'async'));
// Remove ALL hooks for a hook name (use sparingly)

Hook Domains Deep Dive: API Reference

Routing

// Route object specification
{
    id: 'unique-route-id',
    path: '/path/:param',
    exact: true,
    component: MyComponent,
    order: Enums.priority.neutral,
    loadState: async ({ route, params, search }) => ({ data }),
    handleId: 'MyHandleId',
    persistHandle: false,
    transitions: true,
    transitionStates: [
        { state: 'EXITING', active: 'previous' },
        { state: 'LOADING', active: 'current' },
        { state: 'ENTERING', active: 'current' },
        { state: 'READY', active: 'current' }
    ]
}

Reactium: Route Object SpecificationRouting System: Overview

await Reactium.Routing.register(routeObject, (update = true));
// Returns: routeId (string)

Routing System: Route Registration Method

Reactium.Routing.unregister(routeId, (update = true));

Routing System: Advanced Features

// Transition state management
Reactium.Routing.nextState();
Reactium.Routing.jumpCurrent();

Routing System: Advancing States

// Access routing state
const routing = useRouting();
// Returns: {
//   current: currentRoute,
//   previous: previousRoute,
//   active: activeRoute,
//   transitionState: 'EXITING' | 'LOADING' | 'ENTERING' | 'READY',
//   transitionStates: [],
//   changes: {}
// }

Routing System: Listening to Transitions

// Data loading pattern
Component.loadState = async ({ route, params, search }) => {
  return { data, loading: false };
};
Component.handleId = 'HandleId';

Routing System: loadState Pattern

Zone System

<Zone zone="zone-name" prop1={value} />

Zone System Quick Ref

Reactium.Zone.addComponent({
  id: 'COMPONENT-ID',
  zone: 'zone-name' | ['zone1', 'zone2'],
  component: MyComponent | 'ComponentName',
  order: 100,
  ...additionalProps,
});

Zone System Quick Ref: Component Registration

Reactium.Zone.updateComponent(id, updates);
Reactium.Zone.removeComponent(id);

Zone System Quick Ref: Component Registration

Reactium.Zone.addFilter(
  zoneName,
  filterFunction, // (component) => boolean
  priority
);
// Returns: filterId

Zone System Quick Ref: Filters

Reactium.Zone.addMapper(
  zoneName,
  mapperFunction, // (component) => transformedComponent
  priority
);
// Returns: mapperId

Zone System Quick Ref: Mappers

Reactium.Zone.addSort(
  zoneName,
  propertyName, // default: 'order'
  reverse, // default: false
  priority
);
// Returns: sortId

Zone System Quick Ref: Sorters

Reactium.Zone.getZoneComponents(zoneName, (raw = false));
Reactium.Zone.getZoneComponent(zoneName, componentId);
Reactium.Zone.hasZoneComponent(zoneName, componentId);

Zone System Quick Ref: Query Functions

const unsubscribe = Reactium.Zone.subscribe(zoneName, callback);
useZoneComponents(zoneName, (dereference = true));

Zone System Quick Ref: Subscription

Priority Constants

Reactium.Enums.priority.core; // -2000 (runs first)
Reactium.Enums.priority.highest; // -1000
Reactium.Enums.priority.high; // -500
Reactium.Enums.priority.neutral; // 0 (default)
Reactium.Enums.priority.low; // 500
Reactium.Enums.priority.lowest; // 1000 (runs last)

Actinium Quick Ref: Priority ConstantsGotchas: Priority Numbers Are Counterintuitive

Note: Enums.priority.normal does NOT exist (common bug) → Gotchas: Enums.priority.normal Does Not Exist


Server Hooks

ReactiumBoot.Hook.registerSync('Server.ResponseHeaders', (responseHeaders, req, res) => {
    // Add custom HTTP headers
    responseHeaders['X-Frame-Options'] = 'SAMEORIGIN';
    responseHeaders['Cache-Control'] = 'public, max-age=3600';
});

Server Routing: Custom Response Headers

await ReactiumBoot.Hook.run('Server.ResponseHeaders', responseHeaders, req, res);
// Async version of Server.ResponseHeaders hook
// Both sync and async hooks run during SSR

Server Routing: Server.ResponseHeaders Hook


Content Type & Field Type APIs

Reactium.ContentType.FieldType.register(id, definition)
// Register custom field type for Content Type Editor
// id: string (field type ID, e.g., 'Text', 'MyCustomField')
// definition: { label, icon, tooltip, component, order }

Field Type Plugin System: Registration Pattern

Reactium.ContentType.FieldType.get(id)
// Get field type definition by ID
// id: string
// Returns: FieldType definition object

Field Type Plugin System: SDK Reference

Reactium.ContentType.FieldType.list
// Get all registered field types
// Returns: Array of FieldType objects

Field Type Plugin System: SDK Reference

Reactium.Content.Editor.register(id, { component })
// Register content editor component for field type
// id: string (field type ID)
// component: React component for editing field value

Field Type Plugin System: Editor Component

Reactium.Component.register(componentId, Component)
// Register configuration component for field type
// componentId: string (matches fieldType.component property)
// Component: React component for field settings UI

Field Type Plugin System: Configuration Component


Registry API

Factory & Constructor

import { registryFactory } from '@atomic-reactor/reactium-sdk-core';

const registry = registryFactory(name, idField?, mode?)
// name: string (registry name)
// idField: string (default: 'id')
// mode: Registry.MODES.CLEAN | Registry.MODES.HISTORY (default: CLEAN)

Registry System: Constructor & Factory

Registration

registry.register(id, item);
// id: string (unique identifier)
// item: object (must contain idField property matching id)

registry.register(item);
// Auto-uses item[idField] as id

Registry System: Registration

Retrieval

registry.get(path, defaultValue?)
// path: string (id or 'id.nested.property') | array
// Returns: item or property value

registry.list
// Returns: Array (all active items, sorted by 'order' property)

registry.listById
// Returns: Object (items indexed by ID)

Registry System: Retrieval

Unregistration

registry.unregister(id);
// Removes from active list (memory behavior depends on mode)

registry.isRegistered(id);
// Returns: boolean

registry.isUnRegistered(id);
// Returns: boolean

Registry System: Unregistration

Protection & Banning

registry.protect(id);
// Prevents unregistration and replacement

registry.unprotect(id);
// Removes protection

registry.ban(id);
// Prevents registration (preemptive blocking)

registry.unban(id);
// Removes ban

Registry System: ProtectionRegistry System: Banning

Subscriptions

const unsubscribe = registry.subscribe((registry, notification) => {
    // notification.type: 'register' | 'unregister' | 'protect' | 'ban' | etc.
    // notification.id: item ID
    // notification.data: item data (on register)
}, subscriberId?)
// Returns: unsubscribe function

Registry System: Notifications

Memory Management

registry.cleanup(id);
// Remove item from memory (manual cleanup in HISTORY mode)

registry.flush();
// Clear entire registry

Registry System: Cleanup & Flush


Reactium CLI (ARCLI) API

ActionSequence - Sequential Workflow Execution

ActionSequence({ actions, options })
// Executes actions sequentially with shared context
// actions: Object of { actionId: actionFunction }
// options: Object spread into each action parameter
// Returns: Promise<context> with all action results

ActionSequence: Core API

// Action function signature
actionFunction({ params, props, action, context, prevAction })
// params: User parameters from options
// props: Framework properties from options
// action: String - current action ID
// context: Object - accumulated results from previous actions
// prevAction: String - previous action ID (undefined for first)
// Returns: Any value (stored in context[actionId])

ActionSequence: Action Function Signature

Common Pattern:

const actions = {
  init: ({ params }) => { /* setup */ },
  process: ({ params, context }) => {
    const initResult = context.init; // Access previous action
    return processedData;
  },
  finalize: ({ context }) => { /* cleanup */ }
};

await ActionSequence({ actions, options: { params, props } });

ActionSequence: Pattern 1 - Generator Wrapper

Command Exports

// Root command (appears in npx reactium --help)
export const NAME = 'mycommand';
export const COMMAND = ({ program, props }) => {
  return program
    .command(NAME)
    .description('Command description')
    .action((opt) => ACTION({ opt, props }))
    .option('-f, --flag [value]', 'Flag description');
};

CLI: Command Module Structure

// Subcommand (namespaced with dot notation)
export const ID = 'parent.child'; // Or 'namespace:command'
export const COMMAND = ({ program, props }) => {
  /* ... */
};

CLI: Command Module Structure

Global arcli Object

// Available utilities in all commands
const {
  chalk, // Terminal colors
  fs, // fs-extra
  path, // Node path
  globby, // Fast globbing
  inquirer, // Prompts
  Spinner, // ora spinner
  ActionSequence, // Multi-step actions
  handlebars, // Template engine
  op, // object-path
  moment, // Date utilities
  semver, // Version utilities
  props, // CLI properties (cwd, root, config)
} = arcli;

CLI: Bootstrap Process

Plugin CLI Extensibility

// arcli-install.js - Post-install actions
module.exports = (spinner, arcli, params, props) => {
  return {
    init: async ({ params }) => {
      const dir = params.pluginDirectory; // Injected by install command
    },
    prompt: async () => {
      spinner.stop(); // MUST stop before prompts
      // Interactive setup
    },
  };
};

Plugin CLI Extensibility: arcli-install.js Pattern

// arcli-publish.js - Pre-publish actions
module.exports = (spinner) => {
  return {
    compileCSS: async () => {
      spinner.text = 'Compiling...';
      await buildAssets();
    },
  };
};

Plugin CLI Extensibility: arcli-publish.js Pattern

Available in arcli-install.js:

  • spinner - ora spinner instance
  • arcli - Global utilities (passed as param, but use global)
  • params - Includes pluginDirectory (injected by install)
  • props - CLI props (cwd, config)

Available in arcli-publish.js:

  • spinner - ora spinner instance
  • Access arcli, params, props via action parameters
  • props.cwd - Plugin root directory

Plugin CLI Extensibility: API Reference

CLI Hooks

// Global hooks (arcli-hooks.js)
Hook.register('arcli-before-command', async ({ command, params }) => {
  // Runs before any command
});

// Command-specific hooks (reactium-arcli.js)
Reactium.Hook.register(
  'arcli-component-input',
  async ({ inquirer, params }) => {
    // Modify component command input prompts
  }
);

Reactium.Hook.register('arcli-component-conform', async ({ params }) => {
  // Transform parameters before execution
});

Reactium.Hook.register('arcli-component-actions', ({ actions }) => {
  // Add file generation actions
  actions['my-action'] = async ({ params, props }) => {
    /* ... */
  };
});

CLI: Hook-Driven Extensibility

ActionSequence Pattern

import { ActionSequence } from 'action-sequence';

const actions = {
  'create-dir': async ({ params, props }) => {
    fs.ensureDirSync(params.destination);
  },
  'generate-files': async ({ params, props, spinner }) => {
    spinner.text = 'Generating files...';
    // File generation logic
  },
};

await ActionSequence({
  actions,
  options: { params, props, spinner },
});

CLI: ActionSequence Pattern

Configuration Access

// Access CLI config
const { config } = arcli.props;
const customValue = op.get(config, 'custom.key');

// Configuration hierarchy (later overrides earlier):
// 1. CLI/config.json (base)
// 2. [cwd]/CLI/.cli/config.json (app legacy, rarely exists)
// 3. [homedir]/.arcli/config.json (user)
// 4. [cwd]/.cli/config.json (project - highest priority)

CLI: Configuration Customization


ReactiumWebpack SDK

Webpack Configuration

const sdk = new WebpackSDK(name, dddFilename, context);
// name: 'reactium'
// dddFilename: 'reactium-webpack.js'
// context: config object from webpack.config.js

ReactiumWebpack: WebpackSDK Class

Core Methods

// Add module rule (loader)
sdk.addRule(id, rule, order?)
// Example: sdk.addRule('sass-loader', { test: /\.scss$/, use: ['sass-loader'] }, 100)

ReactiumWebpack: addRule

// Add webpack plugin
sdk.addPlugin(id, pluginInstance);
// Example: sdk.addPlugin('compression', new CompressionPlugin())

ReactiumWebpack: addPlugin

// Ignore files
sdk.addIgnore(id, resourceRegExp, contextRegExp?)
// Example: sdk.addIgnore('test-files', /\.test\.js$/)

ReactiumWebpack: addIgnore

// Add module alias
sdk.addResolveAlias(id, path);
// Example: sdk.addResolveAlias('components', './src/app/components')

ReactiumWebpack: addResolveAlias

// Add external dependency
sdk.addExternal(id, config);
// Example: sdk.addExternal('react', { key: 'react', value: 'React' })

ReactiumWebpack: addExternal

// Transpile node_modules package
sdk.addTranspiledDependency(moduleName);
// Example: sdk.addTranspiledDependency('my-es6-package')

ReactiumWebpack: addTranspiledDependency

// Add context replacement
sdk.addContext(id, { from: RegExp, to: string });
// Example: sdk.addContext('translations', { from: /translations$/, to: './src/translations' })

ReactiumWebpack: addContext

Optimization Methods

// Enable aggressive code splitting
sdk.setCodeSplittingOptimize(env);

// Use webpack default optimization
sdk.setWebpackDefaultOptimize(env);

// Disable code splitting (single bundle)
sdk.setNoCodeSplitting(env);

ReactiumWebpack: Optimization Methods

Properties

sdk.mode = 'development' | 'production' | 'none';
sdk.entry = { main: './src/index.js' };
sdk.target = 'web' | 'node';
sdk.output = { path, publicPath, filename };
sdk.devtool = 'source-map' | false;
sdk.optimization = { minimize, splitChunks };
sdk.extensions = ['.js', '.jsx', '.json'];
sdk.overrides = {
  /* direct webpack config */
};

ReactiumWebpack: Properties

Webpack Hooks

// Modify SDK before config generation
Hook.registerSync(
  'before-config',
  (sdk) => {
    sdk.addRule('my-loader', rule);
  },
  'my-plugin-id'
);

// Modify final config after generation
Hook.registerSync(
  'after-config',
  (config, sdk) => {
    config.resolve.fallback = {
      /* ... */
    };
  },
  'my-plugin-id'
);

// Modify registries
Hook.registerSync(
  'rules',
  (rulesRegistry, name, context) => {
    // Inspect or modify rules
  },
  'my-plugin-id'
);

Hook.registerSync(
  'plugins',
  (pluginsRegistry, name, context) => {
    // Inspect or modify plugins
  },
  'my-plugin-id'
);

ReactiumWebpack: Hook System Integration

DDD Pattern

// File: src/my-feature/reactium-webpack.js
const { Hook } = require('@atomic-reactor/reactium-sdk-core/core');

Hook.registerSync(
  'before-config',
  (sdk) => {
    sdk.addRule('my-rule', {
      /* ... */
    });
  },
  'my-feature-webpack'
);

ReactiumWebpack: DDD Discovery Pattern


Actinium API

WebSocket (Socket.io)

// Server-side: Actinium.IO object
Actinium.IO.server
// Socket.io Server instance attached to HTTP server
// Type: Server (socket.io)

Actinium IO: Socket.io Server Configuration

Actinium.IO.clients
// Registry of connected clients (CLEAN mode)
// Type: Registry<{ id: string, client: Socket }>

Actinium IO: Client Registry Pattern

// Hooks for Socket.io lifecycle
Actinium.Hook.register('io.config', async (socketConfig) => {
    // Modify Socket.io server configuration before creation
    socketConfig.cors = { origin: allowedOrigins };
});

Actinium IO: Server Configuration

Actinium.Hook.register('io.init', async (IO) => {
    // Runs after IO.server created
    // Add middleware, authentication, etc.
});

Actinium IO: Lifecycle Hooks

Actinium.Hook.register('io.connection', async (client) => {
    // Fires for each client connection
    // client: Socket (socket.io client object)
});

Actinium IO: Connection Handler

Actinium.Hook.register('io.disconnecting', async (client) => {
    // Fires when client disconnects
});

Actinium IO: Disconnection Handler

// Browser-side: Actinium.IO client (auto-configured)
import { api as Actinium } from '@atomic-reactor/reactium-api';

Actinium.IO.connect()
// Manually connect to Socket.io server

Actinium.IO.on(eventName, handler)
// Listen for server events

Actinium.IO.emit(eventName, data)
// Send event to server

Actinium IO: Browser Integration

Collection Registration

Actinium.Collection.register(collection, publicSetting, schema?, indexes?)
// Registers Parse collection with CLP, schema, and indexes
// collection: String - Collection name
// publicSetting: { create, retrieve, update, delete, addField } - Boolean flags
// schema: Object - Parse field definitions (optional)
// indexes: Array<string> - Fields to index (optional)

Collection Registration: Core API

// Schema field types
{
    fieldName: {
        type: 'String' | 'Number' | 'Boolean' | 'Date' | 'Array' | 'Object' |
              'Pointer' | 'Relation' | 'File' | 'GeoPoint' | 'Polygon',
        targetClass?: string,    // Required for Pointer/Relation
        required?: boolean,
        defaultValue?: any,
        delete?: boolean         // Mark for deletion
    }
}

Collection Registration: Schema Field Management

Actinium.Collection.load(collection?)
// Loads/reloads schema and CLPs for collection(s)
// collection: String (optional) - Specific collection, or all if omitted

Collection Registration: Collection Lifecycle

Actinium.Collection.unregister(collection);
// Resets collection to default (private) permissions
// collection: String - Collection name

Email (Mailer System)

await Actinium.Mail.send(message);
// Sends email via configured transport (SMTP, Mailgun, SES, or sendmail)
// message: nodemailer.MailOptions - Standard nodemailer message object
// Returns: Promise<SentMessageInfo>

Mailer System: Actinium.Mail.send()

// Message options (nodemailer)
{
    from: 'noreply@example.com' | { name: string, address: string },
    to: string | string[],
    cc?: string | string[],
    bcc?: string | string[],
    subject: string,
    text?: string,        // Plain text body
    html?: string,        // HTML body
    attachments?: [{
        filename: string,
        path?: string,
        content?: Buffer | string,
        contentType?: string
    }],
    replyTo?: string,
    priority?: 'high' | 'normal' | 'low'
}

Mailer System: Message Options

// Hook: mailer-transport (choose email provider)
Actinium.Hook.register(
    'mailer-transport',
    async (context) => {
        context.transport = nodemailer.createTransport(config);
    },
    priority  // 0 = sendmail, 1+ = plugins
);

Mailer System: Hook Integration

Collection Registration: Core API

Express Settings

Actinium.Exp.init(app, options?)
// Configures Express app settings via app.set(key, value)
// app: Express.Application - Express instance
// options: Object (optional) - Settings object (overrides ENV.EXPRESS_OPTIONS)

Express Settings: Core Implementation

// Environment configuration
ENV.EXPRESS_OPTIONS = {
  'view engine': 'ejs', // Template engine
  views: '/path/to/views', // Template directory
  'trust proxy': true, // Enable proxy trust
  'x-powered-by': false, // Disable Express header
  etag: 'weak', // ETag generation
  'json spaces': 2, // JSON pretty-print
  'case sensitive routing': false,
  'strict routing': false,
};

Express Settings: Configuration

// Runtime configuration via Actinium.init()
await Actinium.init({
  'trust proxy': 1,
  'view engine': 'pug',
});

Express Settings: Runtime Configuration

// Hook integration for dynamic configuration
Actinium.Hook.register('init', async (app, options) => {
  app.set('trust proxy', process.env.NODE_ENV === 'production' ? 1 : false);
  app.set('view cache', process.env.NODE_ENV === 'production');
});

Express Settings: Hook Integration

Environment Configuration

// Environment file resolution (priority order)
process.env.ACTINIUM_ENV_FILE; // 1. Explicit file path
process.env.ACTINIUM_ENV_ID; // 2. Environment ID → src/env.{id}.json
// Default: src/env.json        // 3. Default file

Environment Config: File Resolution

// Configuration merge strategy
const ENV = {
  ...JSON.parse(fs.readFileSync(envFile)), // 1. Load JSON file
  ...process.env, // 2. process.env overrides
  PORT, // 3. Computed values
  SERVER_URI,
  PUBLIC_SERVER_URI,
};

Environment Config: Merge Strategy

// PORT resolution logic (fallback chain)
// Standard mode:
// 1. process.env.APP_PORT
// 2. process.env.PORT
// 3. env.APP_PORT (from JSON)
// 4. env.PORT (from JSON)
// 5. DEFAULT_PORT (9000)

// PORT_VAR mode (cloud platforms):
const PORT_VAR = process.env.PORT_VAR || env.PORT_VAR;
const PORT = process.env[PORT_VAR] || env[PORT_VAR];

Environment Config: PORT Resolution

// TLS/HTTPS configuration
ENV.APP_TLS_CERT_FILE = '/path/to/cert.pem'; // Certificate file path
ENV.APP_TLS_KEY_FILE = '/path/to/key.pem'; // Private key file path
// ENV.TLS_MODE auto-enabled if both files exist and readable

Environment Config: TLS Configuration

// Security: Master key IP whitelisting (CIDR notation)
ENV.MASTER_KEY_IPS = [
  '10.0.0.5', // Single IP
  '192.168.1.0/24', // IP range
  '::1', // IPv6 localhost
];

Environment Config: Master Key IP Whitelisting

// Feature flags
ENV.NO_PARSE = false; // Disable Parse Server entirely
ENV.NO_DOCS = false; // Disable API documentation
ENV.LIVE_QUERY_SERVER = true; // Enable Live Query subscriptions

Environment Config: Feature Flags

// Common environment variables
ENV.DATABASE_URI; // MongoDB connection string
ENV.APP_ID; // Parse Server app ID
ENV.MASTER_KEY; // Parse Server master key
ENV.SERVER_URI; // Internal server URL
ENV.PUBLIC_SERVER_URI; // Public-facing URL
ENV.PARSE_MOUNT; // Parse Server mount path (e.g., "/api")
ENV.PARSE_DASHBOARD; // Enable Parse Dashboard
ENV.MAX_UPLOAD_SIZE; // File upload size limit

Environment Config: Complete Variable Reference

Content Management

Actinium.Content.save(params, options)
// Create or update content
// params: { type, title, slug?, uuid?, status?, user?, data?, meta?, ... }
// options: Parse options (sessionToken or useMasterKey)
// Returns: Promise<Parse.Object>

Content System: save() API

Actinium.Content.find(params, options)
// Query content with filters and pagination
// params: { uuid?, objectId?, title?, status?, user?, type?, slug?, limit?, page? }
// Returns: Promise<{ count, page, pages, limit, index, results }>

Content System: find() API

Actinium.Content.retrieve(params, options, create = false)
// Retrieve single content by uuid/objectId/type+slug
// params: { uuid?, objectId?, type?, slug? }
// create: Boolean - return new object if not found
// Returns: Promise<Parse.Object | undefined>

Content System: retrieve() API

Actinium.Content.delete(params, options)
// Soft delete (sets status='DELETE')
// Returns: Promise<{ items: Parse.Object[] }>

Content System: delete() API

Actinium.Content.purge(params, options)
// Hard delete (permanent removal)
// Returns: Promise<{ items: Parse.Object[] }>

Content System: purge() API

Actinium.Content.exists({ type, slug }, options)
// Check if content exists
// Returns: Promise<boolean>

Content System: exists() API

Content Syndication

Actinium.Syndicate.Client.create(req, options)
// Create syndication client with refresh token
// req.params: { client, user? }
// Returns: Promise<{ objectId, token, client, user }>

Syndicate: Client.create()

Actinium.Syndicate.Client.token(req)
// Exchange refresh token for access token (60s expiration)
// req.params: { token } // refresh token
// Returns: Promise<{ token }> // access token

Syndicate: Client.token()

Actinium.Syndicate.Client.verify(req)
// Verify access token validity
// req.params: { token } // access token
// Returns: Promise<Object | false> // JWT payload or false

Syndicate: Client.verify()

Actinium.Syndicate.Content.list(req)
// Get syndicated content (requires valid access token)
// Auto-enriches with URLs via hook
// Returns: Promise<PaginatedResults>

Syndicate: Content.list()

Actinium.Syndicate.Content.types(req)
// Get whitelisted content types (requires valid access token)
// Filtered by 'Syndicate.types' setting
// Returns: Promise<Type[]>

Syndicate: Content.types()

Parse Object Serialization

Actinium.Utils.serialize(data)
// Convert Parse Object to plain JavaScript
// - Calls toJSON() on data and nested objects
// - Strips __type: 'Pointer' metadata
// - Preserves ACL objects
// - Null-safe (returns null/undefined/primitives as-is)
// Returns: PlainObject | null | undefined | Primitive

Serialization: API

Middleware Registration

Actinium.Middleware.register(id, callback, (order = 100));
// id: String - Unique middleware identifier
// callback: (app: Express.Application) => Promise<void>
// order: Number - Priority (lower = earlier, default 100)

Actinium Middleware: register API

Actinium.Middleware.registerHook(id, path?, order = 100)
// Creates hook-driven middleware ({id}-middleware hook)
// id: String - Hook name
// path: String (optional) - Express route path to scope middleware
// order: Number - Priority

Actinium Middleware: registerHook API

Actinium.Middleware.replace(id, callback);
// Replaces previously registered middleware
// id: String - Middleware ID to replace
// callback: (app: Express.Application) => Promise<void>

Actinium Middleware: replace API

Actinium.Middleware.unregister(id);
// Removes middleware from execution
// id: String - Middleware ID to remove

Actinium Middleware: unregister API

// Hook listener for hook-driven middleware
Actinium.Hook.register('{id}-middleware', async (mw) => {
  // mw.req - Express request
  // mw.res - Express response
  // mw.use(callback) - Chain middleware
  // mw.next() - Execute chain
  const router = express.Router();
  router.get('/route', (req, res) => {
    /* ... */
  });
  mw.req.app.use(router); // Access app via mw.req.app
});

Actinium Middleware: Pattern 4 - Hook-Driven

Common priority values:

-100000; // Very early (body-parser, CORS, cookies, static)
0; // Parse Server middleware
100; // Default (most middleware)

Actinium Middleware: Priority-Based Ordering

Plugin Registration

// info.js
const PLUGIN = {
  ID: 'PluginId',
  name: 'Plugin Name',
  description: 'Description',
  version: '1.0.0',
  order: 100,
};
export default PLUGIN;

Actinium Quick Ref: Essential Plugin Structure

// plugin.js
const MOD = () => {
  Actinium.Plugin.register(PLUGIN, active);
};
export default MOD(); // Must call immediately

Actinium: Plugin RegistrationGotchas: Plugin Function Must Execute

Hooks

Actinium.Hook.register(
  name, // string
  callback, // async function
  priority, // number (default: Enums.priority.neutral)
  id // string (optional)
);

Actinium Quick Ref: Hook Registration Patterns

Actinium.Hook.registerSync(name, callback, priority, id);

Actinium Quick Ref: Hook Registration Patterns

await Actinium.Hook.run(name, ...args);
Actinium.Hook.runSync(name, ...args);

Actinium Quick Ref: Hook Registration Patterns

Common Lifecycle Hooks

Actinium.Hook.register('init', async (app, options) => {});
Actinium.Hook.register('start', async () => {});
Actinium.Hook.register('running', async () => {});

Actinium Quick Ref: Common Lifecycle Hooks

Actinium.Hook.register('install', async (plugin, req) => {});
Actinium.Hook.register('activate', async (plugin, req) => {});
Actinium.Hook.register('schema', async (plugin, req) => {});
Actinium.Hook.register('update', async (plugin, req, oldPlugin) => {});

Actinium Quick Ref: Common Lifecycle Hooks

Actinium.Hook.register('beforeSave', async (req) => {});
Actinium.Hook.register('beforeSave_Collection', async (req) => {});
Actinium.Hook.register('afterSave_Collection', async (req) => {});

Actinium Quick Ref: Common Lifecycle Hooks

Cloud Functions

Actinium.Cloud.define(
  PLUGIN.ID, // Plugin ID (enables plugin gating)
  'functionName', // Function name
  async (req) => {
    // req.params  - client parameters
    // req.user    - Parse.User (or undefined)
    // req.master  - boolean (master key in use)
    return result;
  }
);

Cloud Functions: Registration Pattern

// Parse Server triggers
Actinium.Cloud.beforeSave(COLLECTION, async (req) => {});
Actinium.Cloud.afterSave(COLLECTION, async (req) => {});
Actinium.Cloud.beforeDelete(COLLECTION, async (req) => {});
Actinium.Cloud.afterDelete(COLLECTION, async (req) => {});
Actinium.Cloud.afterFind(COLLECTION, async (req) => {});
Actinium.Cloud.beforeLogin(async (req) => {});

Cloud Functions: Hook Integration

// Client-side call
const result = await Actinium.Cloud.run('functionName', params, options);
// options: { useMasterKey: boolean, sessionToken: string }

Cloud Functions: Testing Strategies

Content Type System

// Create content type
const type = await Actinium.Type.create(params, options);
// params: { type, machineName?, namespace?, fields, regions?, meta? }
// Returns: Type object with uuid, machineName, collection, fields, regions, meta

Content Type: Create Type

// Retrieve content type
const type = await Actinium.Type.retrieve(params, options);
// params: { machineName | uuid | objectId | collection }
// Returns: Type object

Content Type: Retrieve Type

// Update content type
const updated = await Actinium.Type.update(params, options);
// params: { machineName | uuid, fields?, regions?, meta? }
// Returns: Updated type object

Content Type: Update Type

// Delete content type (config only, not content)
const trash = await Actinium.Type.delete(params, options);
// params: { machineName | uuid }
// Returns: Recycle bin entry

Content Type: Delete Type

// List all types
const list = await Actinium.Type.list(params, options);
// params: { page?, limit?, refresh? }
// Returns: { timestamp, limit, page, pages, types: [...] }

Content Type: List Types

// Get type status (collection, count, fields)
const status = await Actinium.Type.status(params, options);
// params: { machineName | uuid }
// Returns: { collection, count, fields: [...] }

Content Type: Type CRUD Operations

Pagination Utilities

// Skip-based pagination with hookedQuery
const result = await Actinium.Utils.hookedQuery(
  {
    page: 1, // Page number (1-indexed), or -1 for all pages
    limit: 50, // Items per page
    orderBy: 'createdAt',
    order: 'descending',
    queryParams: [
      // Declarative query constraints
      { method: 'equalTo', params: ['status', 'PUBLISHED'] },
      { method: 'greaterThan', params: ['createdAt', date] },
    ],
  },
  options,
  'Content_article', // Collection name
  'query-hook', // Hook to modify query
  'output-hook', // Hook to modify results
  'results', // Results key
  'ARRAY' // Results as ARRAY or OBJECT
);
// Returns: { count, page, pages, limit, prev?, next?, results }

Pagination: HookedQuery Utility

// Load all pages (batch processing)
const allResults = await Actinium.Utils.hookedQuery(
  { page: -1, limit: 100 }, // page: -1 triggers load-all
  options,
  'MyCollection'
);
// Returns all records in result.results

Pagination: Load-All Pattern

Note: For cursor-based pagination (large datasets), see manual implementation pattern: → Pagination: Cursor-Based Pattern

Cloud Function Security

✅ CORRECT - Import from Actinium.Utils:

const {
  CloudRunOptions,
  MasterOptions,
  CloudCapOptions,
  CloudHasCapabilities,
} = Actinium.Utils;

// Or deep import (also valid):
import { CloudRunOptions } from '@atomic-reactor/actinium-core/lib/utils/options.js';

❌ NEVER DO THIS - Don't reimplement framework utilities:

// WRONG - Don't copy-paste the implementation!
const CloudRunOptions = (req) => {
    const options = {};
    if (req.master) { options.useMasterKey = true; }
    else if (req.user) {
        options.sessionToken = req.user.getSessionToken();
        const userId = req.user.id || req.user.objectId;
        if (Actinium.Roles.User.is(userId, 'super-admin')) {
            options.useMasterKey = true;
        }
    }
    return options;
}; // DON'T DO THIS - Use Actinium.Utils instead!

❌ CRITICAL: Node.js Client Session Token Anti-Pattern

When using Parse SDK from Node.js clients (NOT browser), you MUST capture and pass session token after login:

// ❌ WRONG - Missing session token in Node.js client:
const user = await Parse.User.logIn(username, password);
await Parse.Cloud.run('someFunction', { params });  // FAILS - No session!

// ✅ CORRECT - Capture session token, pass to all subsequent calls:
const user = await Parse.User.logIn(username, password);
const sessionToken = user.getSessionToken();
await Parse.Cloud.run('someFunction', { params }, { sessionToken });  // Works!

// ✅ CORRECT - Pattern for multiple calls:
const user = await Parse.User.logIn(username, password);
const sessionToken = user.getSessionToken();

// Pass to all Cloud.run calls
await Parse.Cloud.run('function1', params1, { sessionToken });
await Parse.Cloud.run('function2', params2, { sessionToken });

// Pass to queries
const query = new Parse.Query('MyClass');
const results = await query.find({ sessionToken });

// Pass to save/delete operations
const obj = new Parse.Object('MyClass');
await obj.save(null, { sessionToken });

Why this matters:

  • Browser Parse SDK: Session automatically maintained in cookies/localStorage
  • Node.js Parse SDK: NO automatic session persistence - must pass explicitly
  • Without session token: Server treats you as anonymous (not logged in)
  • This is the #1 cause of "Permission denied" errors in Node.js clients

Cloud Functions: User Context Propagation

Usage:

// CloudRunOptions - Use session token, escalate for super-admin
const options = CloudRunOptions(req);
// options = { sessionToken: 'xxx' } OR { useMasterKey: true }

// CloudRunOptions with level requirement
const options = CloudRunOptions(req, '>1000');
// Escalates if user level > 1000

// MasterOptions - Force master key (use sparingly)
const options = MasterOptions();
// options = { useMasterKey: true }

// CloudCapOptions - Escalate if user has capabilities
const options = CloudCapOptions(
  req,
  ['Setting.retrieve', 'setting.site-get'],
  false
);
// Escalates if user has EITHER capability (false = OR logic)

// CloudHasCapabilities - Check without escalation (permission gate)
if (!CloudHasCapabilities(req, ['Setting.update'], false)) {
  return Promise.reject('Permission denied.');
}

Cloud Functions: Security & AuthorizationActinium Quick Ref: Capability Checking

// CloudACL - Generate ACL with capability-based role access
const { CloudACL } = Actinium.Utils;

const acl = await CloudACL(
  [
    { permission: 'read', type: 'public', allow: true },
    { permission: 'write', type: 'user', objectId: user.id, allow: true },
  ],
  'read-score', // Roles with this capability get read access
  'write-score' // Roles with this capability get write access
);

object.setACL(acl);

Cloud Functions: CloudACL

// AclTargets - Get users and roles for ACL selectors
const { AclTargets } = Actinium.Utils;

const targets = await AclTargets({
  master: true,
  params: { search: 'admin', cache: true },
});
// Returns: { roles: [...], users: [...] }

Cloud Functions: AclTargets

// Capability Registration
Actinium.Capability.register(
  'capability.name',
  {
    allowed: ['role1', 'role2'],
    excluded: ['role3'],
  },
  priority
);

Actinium: Capabilities System

Database & Schema

Actinium.Collection.register(
  'CollectionName',
  {
    // Actions (maps to capabilities)
    create: true,
    retrieve: true,
    update: true,
    delete: true,
    addField: false,
  },
  {
    // Schema definition
    fieldName: {
      type: 'String',
      required: true,
      default: 'value',
    },
    pointerField: {
      type: 'Pointer',
      targetClass: '_User',
    },
  }
);

Actinium Quick Ref: Database Schema Definition

const query = new Actinium.Query('CollectionName');
query.equalTo('field', value);
query.limit(10);
const results = await query.find({ useMasterKey: true });

Actinium: Framework Architecture

✅ CORRECT - One-line instantiation:

const obj = new Actinium.Object('ClassName');
obj.set('field', value);
await obj.save(null, { useMasterKey: true });

❌ NEVER DO THIS - Verbose two-line pattern:

// WRONG - Unnecessary extend + instantiate
const MyClass = Actinium.Object.extend('ClassName');
const obj = new MyClass();
// DON'T DO THIS - Use one-line pattern above!

Actinium: Framework Architecture

Middleware

Actinium.Middleware.register(
  'middleware-name',
  (app) => {
    app.use(middlewareFunction);
  },
  priority,
  'unique-id'
);

Patterns: Middleware Priority Pattern

Global Variables

Actinium; // Main framework object
ENV; // Environment configuration
PORT; // Server port
BASE_DIR; // Project root
SRC_DIR; // src/ directory
APP_DIR; // src/app/ directory
CORE_DIR; // actinium-core directory
CLOUD_FUNCTIONS; // Cloud function registry

Actinium Quick Ref: Global Variables Available

DEBUG(...args); // Threshold: 1000
INFO(...args); // Threshold: 500
BOOT(...args); // Threshold: 0
WARN(...args); // Threshold: -500
ERROR(...args); // Threshold: -1000
LOG(...args); // Alias for BOOT

Actinium Quick Ref: Global Variables Available


Integration API

Parse SDK (Frontend)

// Initialize Parse
Parse.initialize(APP_ID, JS_KEY);
Parse.serverURL = 'http://localhost:9000/parse';

Integration: Authentication

// Login
const user = await Parse.User.logIn(username, password);

// Signup
const user = new Parse.User();
user.set('username', username);
user.set('password', password);
await user.signUp();

// Current user
const currentUser = Parse.User.current();

// Logout
await Parse.User.logOut();

Integration: Authentication

// Query
const query = new Parse.Query('ClassName');
query.equalTo('field', value);
query.limit(20);
const results = await query.find();

// Get by ID
const obj = await query.get(objectId);

// First match
const first = await query.first();

// Count
const count = await query.count();

Integration: Data Flow Patterns

// Save object
const MyClass = Parse.Object.extend('ClassName');
const obj = new MyClass();
obj.set('field', value);
await obj.save();

// Update
obj.set('field', newValue);
await obj.save();

// Delete
await obj.destroy();

Integration: Data Flow Patterns

// Cloud function call
const result = await Parse.Cloud.run('functionName', {
  param1: 'value1',
  param2: 'value2',
});

Integration: Cloud Function Integration

Parse Live Query (Real-Time)

// Enable Live Query (backend)
Actinium.Hook.register('live-query-classnames', (context) => {
  context.classNames.push('MyCollection');
});

Integration: Real-Time Communication

// Subscribe to changes (frontend)
const query = new Parse.Query('MyCollection');
const subscription = await query.subscribe();

subscription.on('create', (object) => {
  console.log('Created:', object);
});

subscription.on('update', (object) => {
  console.log('Updated:', object);
});

subscription.on('delete', (object) => {
  console.log('Deleted:', object);
});

// Unsubscribe
subscription.unsubscribe();

Integration: Real-Time Communication


Common Patterns

Component with Data Loading

// Component
export const MyComponent = () => {
  const handle = useSyncHandle(MyComponent.handleId);
  const data = handle?.get('data');

  return <div>{data}</div>;
};

MyComponent.loadState = async ({ route, params, search }) => {
  const data = await fetchData(params);
  return { data, loading: false };
};

MyComponent.handleId = 'MyComponentHandle';

export default MyComponent;

Reactium: Data Loading with loadStatePatterns: Static Method Data Loading

Plugin Registration (Reactium)

(async () => {
  const { Hook, Enums, Component } = await import(
    '@atomic-reactor/reactium-core/sdk'
  );

  Hook.register(
    'plugin-init',
    async () => {
      const { MyComponent } = await import('./MyComponent');
      Component.register('MyComponent', MyComponent);
    },
    Enums.priority.neutral,
    'plugin-init-MyComponent'
  );
})();

Reactium: Creating a Plugin

Plugin with SDK (Actinium)

// sdk.js
export default {
    doSomething: async (param) => { /* ... */ }
};

// plugin.js
import Actinium from '@atomic-reactor/actinium-core';
import PLUGIN from './info.js';
import SDK from './sdk.js';

const MOD = () => {
    Actinium.Plugin.register(PLUGIN, true);
    Actinium.MyPlugin = SDK;

    Actinium.Cloud.define(PLUGIN.ID, 'myFunction', async (req) => {
        return SDK.doSomething(req.params.param);
    });
};

export default MOD();

Patterns: Plugin SDK Pattern


Usage: Find function → Check signature → Click link for details Coverage: 60+ most commonly used API functions with signatures