raycast / raycast/utils

Proposal: useObjectStore Hook

Open
#16 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
84
Forks
18
Avg merge
3m
Merged PRs (30d)
1

Description

Summary: A hook to simplify the creation and management of object dictionaries in LocalStorage, with a simple interface for CRUD operations. This would be useful for storing objects that populate List and Grid views, for example.

Details: This hook would create a LocalStorage entry containing a dictionary of objects as a JSON string, and it would provide easy access to methods for accessing, removing, and updating objects, as well as for performing object key migrations and batch-adding of new keys. A cached option could be provided.

Quite a few extensions store objects in this way and would benefit from a dedicated implementation, especially one that supports future development by providing methods for migrations (since the need/want to rename or delete keys is often unforeseen). Moreover, a standard implementation would allow additional features going forward, e.g. an option to use a JSON file in the extension's support directory rather than in LocalStorage, with minimal changes in extensions' code.

I'd be happy to work on this if there's support for it.

Proposed Interface:

interface LocalObjectStore<T> {
  allObjects: () => T[];

  // Add an object to the store, return the UUID for the object
  addObject: (object: T) => string;
  
  removeObject: (object: T) => void;
  getObject: (id: string) => T | undefined;
  setObject: (id: string, object: T) => void;
  updateObject(id: string, updateFunction: (oldObject: T) => T): void;
  removeObject: (id: string) => void;
  clear: () => void;

  // Rename a key within each object in the store, preserving the value
  renameKey: (oldKey: string, newKey: string) => void;

  // Add a key to each object in the store, using the provided function to generate the value
  addKey: (key: string, valueFunction: (object: T) => any) => void;

  // Delete a key from each object in the store
  deleteKey: (key: string) => void;
}

Example:

import { Action, ActionPanel, Grid } from "@raycast/api";
import { useObjectStore } from '@raycast/utils';

interface EmojiItem {
  name: string;
  emoji: string;
  description: string;
}

export default function Command() {

// Creates the store if it doesn't exist, or returns the existing store
const emojiStore = useObjectStore<EmojiItem>('emoji-items');

useEffect(() => {
  emojiStore.addObject({
    name: 'Smile',
    emoji: '😀',
    description: 'A happy face',
  });
}, []);

// Loads items once upon first render, updates when items are added/removed/modified
const emojiItems = emojiStore.allObjects();

return(
  <Grid>
    {emojiItems.map((item) => (
      <Grid.Item
        key={item.id} // Auto-generated UUID
        title={item.name}
        subtitle={item.description}
        content={item.emoji}
        actions={
          <ActionPanel>
            <Action
              title="Remove"
              onAction={() => emojiStore.removeObject(item.id)}
            />
          </ActionPanel>
        }
      />
    ))}
  </Grid>
);
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the proposed LocalObjectStore interface and the useObjectStore example in this issue. Resolve the CRUD and migration semantics, including the duplicate removeObject signatures and cached/storage options, then define tests for persistence and updates before considering the feature complete.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.