Sapphire Utilities

repository·main·Indexed 41 days ago

https://github.com/sapphiredev/utilities

A monorepo of common NodeJS utility packages including @sapphire/bitfield for bitwise operations, @sapphire/iterator-utilities for advanced iterable transformations and calculations, and @sapphire/string-store for packing raw data into UTF-16 strings to bypass character limits.

Tokens
69.8K
Snippets
248
Records
336
Agent score
50%

What's inside Sapphire Utilities

  1. Overview of @sapphire/utilities

    main

    The @sapphire/utilities package is a collection of common JavaScript and TypeScript utilities designed for the Sapphire Community. It aims to provide high-quality, well-tested, and optimized functions and type augmentations to reduce boilerplate in various projects.

    Key Features

    • TypeScript Native: Written in TypeScript for excellent type safety.
    • Universal Compatibility: Bundled with esbuild, making it compatible with both Node.js and browser environments.
    • Multiple Formats: Offers CommonJS, ESM, and UMD bundles.
  2. Overview of @sapphire/string-store

    main

    @sapphire/string-store is a high-capacity raw data storage utility designed to pack data into UTF-16 strings. It is optimized for scenarios where you need to store significant amounts of information in locations with strict character limits, such as Discord message component custom_id fields.

    Key Features:

    • Written in TypeScript.
    • Bundled with esbuild for compatibility with both Node.js and browser environments.
    • Provides CommonJS, ESM, and UMD bundles.
  3. Overview of Sapphire Utilities packages

    main
    Sapphire Utilities is a collection of common NodeJS packages designed for Sapphire Repositories and general use. The repository contains various specialized utility packages for tasks such as async queuing, bitfields, cron scheduling, Discord integration, and more. Each package is available independently via npm.
  4. How SchemaStore serialization works

    main

    The serialized string is encoded in UTF-16, allowing for 16 bits of storage per character. This is highly efficient for constrained environments like Discord's custom_id field (which allows up to 100 UTF-16 characters, or 1600 bits).

    Key storage details:

    • The schema ID is stored as a 16-bit integer.
    • Property names are NOT stored; only the values are serialized based on the schema order.
    • Each type consumes a specific number of bits (e.g., a single character can hold 16 booleans or 2 8-bit unsigned integers).
  5. Quickstart: Using SchemaStore to serialize data

    main

    To use @sapphire/string-store, define a set of unique IDs (using an enum, as const object, or Object.freeze), create a SchemaStore instance, and register Schema objects for each ID. Each schema defines the fields and their types. You can then use store.serialize(id, data) to convert an object into a serialized string.

    // Require the store classes
    const { SchemaStore, Schema, t } = require('@sapphire/string-store');
    
    // Define the enum with the IDs and export it
    export const Id = Object.freeze({
    	AgeUpdate: 0,
    	StrengthUpdate: 1,
    	Planet: 2,
    	User: 3
    });
    
    // Create the store in a file and export it
    export const store = new SchemaStore()
    	// Add a schema with an age field stored as a int32:
    	// Schema<Id.AgeUpdate, { age: number }>
    	.add(new Schema(Id.AgeUpdate).int32('age'))
    	// Add a schema with a strength field stored as a float32:
    	// Schema<Id.StrengthUpdate, { strength: number }>
    	.add(new Schema(Id.StrengthUpdate).float32('strength'));
    
    // Serialize an `Id.AgeUpdate` object into a string containing:
    // - The schema ID (0)
    // - The age field (20)
    const buffer = store.serialize(Id.AgeUpdate, { age: 20 }).toString();
  6. Importing @sapphire/iterator-utilities

    main

    You can import utilities from the main index file or import them directly from their specific module paths to optimize bundle size.

    From the index file:

    import { append } from '@sapphire/iterator-utilities';
    const { append } = require('@sapphire/iterator-utilities');

    Directly from module paths:

    import { append } from '@sapphire/iterator-utilities/append';
    const { append } = require('@sapphire/iterator-utilities/append');
    import { append } from '@sapphire/iterator-utilities';
  7. Importing @sapphire/utilities

    main

    You can import individual utility functions from subpaths for better tree-shaking or import the entire library.

    Note for TypeScript users: Subpath imports (e.g., @sapphire/utilities/isFunction) are only supported when using --moduleResolution node16 or --moduleResolution nodenext.

    import { isFunction } from '@sapphire/utilities/isFunction';
    // or
    import { isFunction } from '@sapphire/utilities';
  8. Initialize a BitField

    main

    To use @sapphire/bitfield, instantiate the BitField class with an object containing flag names as keys and their corresponding bit values (numbers or bigints) as values.

    Note: If you are using a TypeScript enum of numbers, use the enumToObject utility to convert it into a compatible object for the constructor.

    Warning: The constructor will throw an exception if the input is not an object, is null, is empty, or contains mixed types (some numbers and some bigints).

    import { BitField, enumToObject } from '@sapphire/bitfield';
    
    // Using a standard object
    const PermissionFlags = {
    	Read: 1 << 0,
    	Write: 1 << 1,
    	Edit: 1 << 2,
    	Delete: 1 << 3
    };
    const PermissionsBitField = new BitField(PermissionFlags);
    
    // Using BigInts
    const DetailedPermissionsFlags = {
    	ReadMessages: 1n << 0n,
    	ReadChannels: 1n << 1n,
    	CreateMessages: 1n << 2n,
    	CreateChannels: 1n << 3n
    };
    const DetailedPermissionsBitField = new BitField(DetailedPermissionsFlags);
    
    // Using enumToObject for TypeScript enums
    const PermissionsBitFieldFromEnum = new BitField(enumToObject(SomeEnum));