0.1.1 • Published 9 months ago

@ajukno/sakura v0.1.1

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

Sakura Framework

Key Features

  • Custom Element Management: Add, define, and manage custom elements seamlessly.
  • Plugin Support: Extend the framework with plugins that add extra functionality.
  • Lazy Loading: Efficiently load elements and plugins when needed.
  • Event Handling (Pub/Sub System): Built-in pub/sub system for event-driven interactions.
  • Debug Mode: Enable detailed logging for development and debugging.
  • Asynchronous Support: Handle initialization and plugin management asynchronously.

Installation

To install Sakura via npm, run the following command:

npm install @ajukno/sakura

Usage

Importing Sakura

First, import Sakura into your project:

import { sakura } from '@ajukno/sakura';

Initializing Sakura

Initialize Sakura with your custom elements, plugins, and configuration options:

await sakura.init({
  elements: [
    { tagName: 'custom-element', element: CustomElementClass },
  ],
  plugins: [
    CustomPlugin,
  ],
  debugMode: true,
});

You can add more custom elements and plugins later using the init method:

await sakura.init({
  elements: [
    { tagName: 'another-element', element: AnotherElementClass },
  ],
  plugins: [
    AnotherPlugin,
  ],
});

Custom Element Manager

The Custom Element Manager is responsible for defining and managing custom elements within Sakura. You can define, get, and clear custom elements, as well as redefine them as needed.

define(tag: string, element: ElementProvider): Promise<void>

Defines a custom element using the provided tag and element provider. It validates the element and handles lazy loading if necessary.

await sakura.elementManager.define('custom-element', CustomElementClass);

get(tag: string): ElementProvider | undefined

Retrieves a defined element by its tag.

const element = sakura.elementManager.get('custom-element');

clear(): void

Clears all registered custom elements from the manager.

sakura.elementManager.clear();

redefine(): Promise<void>

Redefines all elements currently registered in the manager.

await sakura.elementManager.redefine();

Plugin Manager

The Plugin Manager is responsible for installing, uninstalling, and managing plugins within Sakura. Plugins can be installed asynchronously and can be lazy-loaded as needed.

install(plugin: PluginProvider): Promise<void>

Installs a plugin by creating an instance of the plugin and calling its install method. Supports lazy loading of plugins.

await sakura.pluginManager.install(CustomPlugin);

uninstall(name: string): void

Uninstalls a plugin by its name, calling the uninstall method of the plugin instance.

sakura.pluginManager.uninstall('CustomPlugin');

reset(): void

Clears all installed plugins from the manager.

sakura.pluginManager.reset();

reinstall(): Promise<void>

Reinstalls all plugins currently registered in the manager.

await sakura.pluginManager.reinstall();

Lazy Loading and Code Splitting

Sakura supports lazy loading for both elements and plugins, which is particularly useful when dealing with large components or plugins that should only be loaded when needed. To further optimize your project, you can use lazy loading in combination with code splitting.

Lazy Element Provider

A lazy provider is a function that loads the element or plugin asynchronously when it's needed. Sakura will automatically handle this process for you.

lazy<T>(provider: () => Promise<{ default: T }>): LazyProvider<T>

Defines a lazy provider that returns the default export from an asynchronous module. Use this function to lazily load custom elements or plugins. This feature should be used in combination with code splitting to split your bundle and improve loading times for your application.

Example of Lazy Loading with Code Splitting

For lazy loading, tools like Webpack or Vite handle code splitting automatically when dynamic import() is used. Here’s how you can define a custom element or plugin with lazy loading:

import { lazy } from '@ajukno/sakura';

// Lazy load a custom element with code splitting
await sakura.elementManager.define(
  'lazy-element',
  lazy(() => import(/* ESbuild chunk: "LazyElement-chunk" */ './components/LazyElement'))
);

// Lazy load a plugin with code splitting
await sakura.pluginManager.install(
  lazy(() => import(/* ESbuild chunk: "LazyPlugin-chunk" */ './plugins/LazyPlugin'))
);

By utilizing code splitting with lazy loading, only the required elements and plugins will be loaded when needed, reducing the initial load time of your application.

PubSub API

Sakura includes a publish-subscribe (pub/sub) system that allows communication between custom elements, plugins, and other components using strongly typed events.

Event Definition

Events in Sakura are defined using the SakuraEvent type. Each event includes:

  • type: A string representing the event's name.
  • payload: The associated data passed with the event.
  • source (optional): A string representing the event's source (optional).

Example event types:

type CursorStateRemoveEvent = SakuraEvent<'cursor:state:remove', CursorStateRemove>;
type SakuraRefreshElementsEvent = SakuraEvent<'sakura:refresh-elements'>;

You can combine multiple event types into a union to allow Sakura's pubsub system to manage all events seamlessly:

type Events = CursorStateRemoveEvent | SakuraRefreshElementsEvent;
const sakura = new Sakura<Events>();

PubSub Methods

The PubSub system provides three key methods: subscribe, unsubscribe, and publish. Each method is fully typed, ensuring type safety and autocompletion in your editor.

1. subscribe

Subscribes to one or more events, providing a callback that is invoked when the event is published.

sakura.pubsub.subscribe('cursor:state:remove', (event) => {
  console.log('Cursor state removed:', event.payload);
});
  • Parameters:
    • events: A string or array of strings representing the event types to subscribe to.
    • callback: A function that is called when the specified event is published, receiving the event object as an argument.

2. unsubscribe

Unsubscribes a callback from one or more events.

const handleRemove = (event) => {
  console.log('Cursor state removed:', event.payload);
};

sakura.pubsub.subscribe('cursor:state:remove', handleRemove);
sakura.pubsub.unsubscribe('cursor:state:remove', handleRemove);  // Unsubscribe the callback
  • Parameters:
    • events: A string or array of strings representing the event types to unsubscribe from.
    • callback: The function that was previously subscribed to the event.

3. publish

Publishes an event, notifying all listeners subscribed to that event.

sakura.pubsub.publish('cursor:state:remove', { stateId: '123' });
  • Parameters:
    • event: The event type (string) to be published.
    • payload: The payload data to pass along with the event. The type is automatically inferred based on the event type.
    • source (optional): An optional string representing the source of the event.

Example Usage

Here’s an example demonstrating how to use the PubSub system to handle events:

// Define the events
type CursorStateRemoveEvent = SakuraEvent<'cursor:state:remove', { stateId: string }>;
type SakuraRefreshElementsEvent = SakuraEvent<'sakura:refresh-elements'>;
type Events = CursorStateRemoveEvent | SakuraRefreshElementsEvent;

const sakura = new Sakura<Events>();

// Subscribe to events
sakura.pubsub.subscribe('cursor:state:remove', (event) => {
  console.log('Cursor state removed:', event.payload.stateId);
});

// Publish an event
sakura.pubsub.publish('cursor:state:remove', { stateId: '123' });

// Unsubscribe from the event
const removeHandler = (event) => console.log('Cursor state removed:', event.payload.stateId);
sakura.pubsub.subscribe('cursor:state:remove', removeHandler);
sakura.pubsub.unsubscribe('cursor:state:remove', removeHandler);

In this example:

  • CursorStateRemoveEvent has a payload that includes stateId.
  • SakuraRefreshElementsEvent has no payload.
  • The subscribe, publish, and unsubscribe methods are used to handle events and their associated data.

Automatic Type Inference

Sakura's PubSub system automatically infers event names and payload types, ensuring type safety at compile time. This makes the development process smoother, as you don’t need to manually manage event typing.

Testing

Sakura includes a suite of tests that ensure the framework behaves as expected. You can run the tests using Vitest:

npm run test

License

Sakura is licensed under the MIT License.