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

@lumina-study/block-store

v0.1.2

Published

Redux Toolkit store for managing lumina.json configurations from GitHub and GitLab repositories

Readme

@lumina-study/block-store

A Redux Toolkit store for managing lumina.json files from GitHub and GitLab repositories. Block types are defined by @lumina-study/block-schema (single source of truth).

Features

  • 🔄 Redux Toolkit Integration: Modern Redux state management with built-in best practices
  • 📋 Block Schema Compliance: Uses @lumina-study/block-schema as the single source of truth for block types
  • 🌐 Multi-Provider Support: Fetch lumina.json files from GitHub and GitLab repositories
  • 📦 TypeScript First: Full TypeScript support with comprehensive type definitions
  • 🔍 Commit Tracking: Automatically tracks the commit SHA for each lumina.json source
  • Simple API: Easy-to-use actions and selectors for managing sources and accessing blocks
  • 🧪 Well Tested: 24 tests passing with comprehensive coverage

What is lumina.json?

A lumina.json file contains an array of blocks following the @lumina-study/block-schema specification. This package manages the retrieval and storage of these files from Git repositories.

Installation

npm install @lumina-study/block-store
# or
pnpm add @lumina-study/block-store
# or
yarn add @lumina-study/block-store

Quick Start

1. Create the Store

import { createBlockStore } from '@lumina-study/block-store'

const store = createBlockStore()

2. Add a lumina.json Source

import { addLuminaJson } from '@lumina-study/block-store'

// Fetch from GitHub
await store.dispatch(
  addLuminaJson({
    provider: 'github',
    organization: 'luminastudy',
    repository: 'my-project',
    token: 'optional-github-token', // For private repos
  })
)

// Fetch from GitLab
await store.dispatch(
  addLuminaJson({
    provider: 'gitlab',
    organization: 'my-group',
    repository: 'my-project',
    token: 'optional-gitlab-token', // For private repos
  })
)

3. Access Data

import {
  selectAllSources,
  selectAllBlocks,
  selectBlockById,
  selectBlocksFromSource,
} from '@lumina-study/block-store'

// Get all lumina.json sources
const sources = selectAllSources(store.getState())

// Get all blocks from all sources (flattened)
const allBlocks = selectAllBlocks(store.getState())

// Get a specific block by ID across all sources
const block = selectBlockById('block-uuid')(store.getState())

// Get blocks from a specific source
const sourceBlocks = selectBlocksFromSource('github:luminastudy:my-project')(
  store.getState()
)

API Reference

Store Factory

createBlockStore()

Creates and configures a Redux store for managing lumina.json sources.

import { createBlockStore } from '@lumina-study/block-store'

const store = createBlockStore()

Returns: BlockStore - Configured Redux store

Actions

addLuminaJson(params: AddLuminaJsonParams)

Async thunk that fetches a lumina.json file from a Git provider and adds it to the store.

Parameters:

interface AddLuminaJsonParams {
  provider: 'github' | 'gitlab'
  organization: string // Organization or user name
  repository: string // Repository name
  token?: string // Optional auth token for private repos
}

Example:

import { addLuminaJson } from '@lumina-study/block-store'

await store.dispatch(
  addLuminaJson({
    provider: 'github',
    organization: 'luminastudy',
    repository: 'block-store',
  })
)

Behavior:

  • Fetches lumina.json from the repository root
  • Validates that the file contains a blocks array
  • Stores the source with provider, org, repo, commitSha, and content
  • Tracks when the source was added

removeLuminaJson(key: string)

Removes a lumina.json source from the store by its key.

Example:

import { removeLuminaJson } from '@lumina-study/block-store'

store.dispatch(removeLuminaJson('github:luminastudy:block-store'))

clearSources()

Clears all lumina.json sources from the store.

import { clearSources } from '@lumina-study/block-store'

store.dispatch(clearSources())

clearError()

Clears any error state.

import { clearError } from '@lumina-study/block-store'

store.dispatch(clearError())

Selectors

selectAllSources(state)

Returns all lumina.json sources as an array.

import { selectAllSources } from '@lumina-study/block-store'

const sources = selectAllSources(store.getState())
// Returns: LuminaJsonSource[]

Returns:

interface LuminaJsonSource {
  provider: 'github' | 'gitlab'
  organization: string
  repository: string
  commitSha: string
  luminaJson: LuminaJson // Contains blocks array
  addedAt: string // ISO timestamp
}

selectSourceByKey(key)(state)

Returns a specific source by its key.

import { selectSourceByKey } from '@lumina-study/block-store'

const source = selectSourceByKey('github:luminastudy:my-project')(
  store.getState()
)

Key Format: "provider:organization:repository"

selectSourcesByProvider(provider)(state)

Returns all sources for a specific Git provider.

import { selectSourcesByProvider } from '@lumina-study/block-store'

const githubSources = selectSourcesByProvider('github')(store.getState())
const gitlabSources = selectSourcesByProvider('gitlab')(store.getState())

selectAllBlocks(state)

Returns all blocks from all sources (flattened).

import { selectAllBlocks } from '@lumina-study/block-store'

const allBlocks = selectAllBlocks(store.getState())
// Returns: Block[]

Returns:

interface Block {
  id: string // UUID
  title: {
    he_text: string
    en_text: string
  }
  prerequisites: string[] // Array of block IDs
  parents: string[] // Array of block IDs
  [key: string]: unknown // Additional properties
}

selectBlocksFromSource(sourceKey)(state)

Returns blocks from a specific source.

import { selectBlocksFromSource } from '@lumina-study/block-store'

const blocks = selectBlocksFromSource('github:luminastudy:my-project')(
  store.getState()
)

selectBlockById(blockId)(state)

Finds a block by ID across all sources.

import { selectBlockById } from '@lumina-study/block-store'

const block = selectBlockById('550e8400-e29b-41d4-a716-446655440000')(
  store.getState()
)
// Returns: Block | undefined

selectLoading(state)

Returns the loading state.

import { selectLoading } from '@lumina-study/block-store'

const isLoading = selectLoading(store.getState())
// Returns: boolean

selectError(state)

Returns the current error message, if any.

import { selectError } from '@lumina-study/block-store'

const error = selectError(store.getState())
// Returns: string | null

Types

All TypeScript types are exported for use in your application:

import type {
  // Core types
  GitProvider,
  Block,
  LuminaJson,
  LuminaJsonSource,

  // State types
  BlockStoreState,

  // Parameter types
  AddLuminaJsonParams,

  // Store types
  BlockStore,
  RootState,
  AppDispatch,
} from '@lumina-study/block-store'

Utilities

generateSourceKey(provider, organization, repository)

Generates a unique key for a lumina.json source.

import { generateSourceKey } from '@lumina-study/block-store'

const key = generateSourceKey('github', 'luminastudy', 'block-store')
// Returns: "github:luminastudy:block-store"

parseSourceKey(key)

Parses a source key into its components.

import { parseSourceKey } from '@lumina-study/block-store'

const { provider, organization, repository } = parseSourceKey(
  'github:luminastudy:block-store'
)

Services (Advanced)

For advanced use cases, you can access the underlying services directly:

import {
  fetchLuminaJsonFromGitHub,
  fetchLuminaJsonFromGitLab,
} from '@lumina-study/block-store'

// Fetch directly without Redux
const { luminaJson, commitSha } = await fetchLuminaJsonFromGitHub(
  'luminastudy',
  'my-project'
)

Integration with React

import { Provider, useDispatch, useSelector } from 'react-redux'
import {
  createBlockStore,
  addLuminaJson,
  selectAllSources,
  selectAllBlocks,
  selectBlockById,
} from '@lumina-study/block-store'
import type { AppDispatch } from '@lumina-study/block-store'

const store = createBlockStore()

function App() {
  return (
    <Provider store={store}>
      <LuminaJsonManager />
    </Provider>
  )
}

function LuminaJsonManager() {
  const dispatch = useDispatch<AppDispatch>()
  const sources = useSelector(selectAllSources)
  const allBlocks = useSelector(selectAllBlocks)

  const handleAddSource = () => {
    dispatch(
      addLuminaJson({
        provider: 'github',
        organization: 'luminastudy',
        repository: 'my-project',
      })
    )
  }

  return (
    <div>
      <button onClick={handleAddSource}>Add Source</button>

      <h2>Sources ({sources.length})</h2>
      <ul>
        {sources.map(source => (
          <li key={`${source.provider}:${source.organization}:${source.repository}`}>
            {source.organization}/{source.repository}
            ({source.luminaJson.blocks.length} blocks, SHA: {source.commitSha.substring(0, 7)})
          </li>
        ))}
      </ul>

      <h2>All Blocks ({allBlocks.length})</h2>
      <ul>
        {allBlocks.map(block => (
          <li key={block.id}>
            {block.title.en_text} / {block.title.he_text}
          </li>
        ))}
      </ul>
    </div>
  )
}

Data Structure

State Shape

{
  luminaJson: {
    sources: {
      "github:luminastudy:my-project": {
        provider: "github",
        organization: "luminastudy",
        repository: "my-project",
        commitSha: "abc123...",
        luminaJson: {
          blocks: [
            {
              id: "550e8400-e29b-41d4-a716-446655440000",
              title: {
                he_text: "בלוק לדוגמה",
                en_text: "Example Block"
              },
              prerequisites: [],
              parents: []
            }
          ]
        },
        addedAt: "2024-01-01T00:00:00.000Z"
      }
    },
    loading: false,
    error: null
  }
}

lumina.json File Format

{
  "blocks": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "title": {
        "he_text": "בלוק לדוגמה",
        "en_text": "Example Block"
      },
      "prerequisites": ["another-block-uuid"],
      "parents": ["parent-block-uuid"]
    }
  ]
}

Error Handling

The store handles errors gracefully and stores them in the state:

import {
  selectError,
  selectLoading,
  clearError,
} from '@lumina-study/block-store'

const error = selectError(store.getState())
const loading = selectLoading(store.getState())

if (loading) {
  console.log('Loading...')
} else if (error) {
  console.error('Error:', error)
  // Clear the error
  store.dispatch(clearError())
}

Block Schema

Blocks follow the @lumina-study/block-schema specification (v0.1):

  • id: Unique identifier (UUID format)
  • title: Object with he_text (Hebrew) and en_text (English)
  • prerequisites: Array of prerequisite block IDs (UUIDs)
  • parents: Array of parent block IDs (UUIDs)
  • Additional custom properties are allowed

Development

# Install dependencies
pnpm install

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Build
pnpm build

# Lint
pnpm lint

# Format
pnpm format

Contributing

See CONTRIBUTING.md for contribution guidelines.

License

MIT © Lumina Study

Related Packages

Support