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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@bunpmjs/bunext

v0.8.11

Published

compatible Runtime: bun 1.1.0 - 1.1.34 compatible OS: Linux, WSL

Downloads

954

Readme

Compatibility

compatible Runtime: bun 1.1.0 - 1.1.34 compatible OS: Linux, WSL

N.B : Bun is in continuous change and compatibility between version is a

problem for Bunext there is possible crash over some new version of Bun.

I will keep up to date the framework for what it needs

bunext

  • Nextjs Framwork compatible with Bun Runtime

  • Facing problemes? Open an issue

Updating to a new Version

When an update of Bunext is made you must run:

#!/usr/bin/env bash
bun bunext init
bun run db:create # only create the types

What is planed

  • Documentation

  • SQlite performance & features

  • Database shema with union type and other useful type

  • Database merging ( bun db:merge )

  • SVG plugin stable

  • Windows compatibility

What is ready

  • Multi-Thread Http Worker ( bun ^1.1.25 & Linux only )

  • process.env ( Client + Server & Only Server )

  • SSR and CSR

  • layout stacking

  • React

  • Static assets

  • Server componants ("use server" & "use client")

  • Revalidate ( Beta )

  • Server action ( File, File[] and FormData can be uploaded )

  • Session Management ( public & private )

  • SQlite Management ( Beta )

  • Server componants ( Beta )

  • Devloppement mode with Hot Reload ( beta version )

  • Production mode ( Beta )

  • Links

  • SVG support ( Beta )

To install and run

#!/bin/env bash
bun i @bunpmjs/bunext || bunpm install bunext
bun bunext init
bun run dev

Run in Production mode

#!/bin/env bash
bun run build # this just make sure your build folder is created and ready to start
bun run start # Enjoy!!!

Documentation

Here is the summary of the framework docs. I will soon make a website making it more simple, clear and fun to read. Thanks to all people how are following my work!

Router

Like NextJs the routes are in src/pages.

  • index.tsx is the main page for the route
  • [id].tsx is a dynamic page loading and is a good oportunity to use getServerSideProps
  • layout.tsx is the layout for the current route and sub-directory routes
//index.tsx
export default function Page() {
  return <div>My page</div>
}

Session

Manage the session from your users by setting a session and optionaly make it accessible from the client side ( default to only Server Side ).

  • SetData only from the Server Side is allowed.

  • Delete Session data can be Client or Server Side

  • GetData can be Client or Server Side ( but Client only have access to what is made public )

    • useSession
    • will automaticaly update the element when the session is updated

Set Session data

import { GetSession, useSession } from "@bunpmjs/bunext/features/session";

export default function Page() {
  return (
    <div>
      <LoggedIndicator />
      <SetSession />
    </div>
  );
}

function SetSession() {
  const session = useSession({
    PreventRenderOnUpdate: true,
  });
  return (
    <button
      onClick={async () => {
        await ServerSetSession({
          username: "foo",
          password: "bar",
        });
        session.update();
/*
Will update every React Element using useSession
without PreventRenderOnUpdate
*/
      }}
    >
      Click to update Session
    </button>
  );
}

function LoggedIndicator() {
  const session = useSession();
  return (<span>
      {session.getData()?.username ? `logged as ${session.getData().username}` : "not logged"}
    </span>);
}

export async function ServerSetSession({
  username,
  password,
}: {
  usename: string;
  password: string;
}) {
  const Session = GetSession(arguments);
  Session.setData(
    {
      username: username,
    },
    true
  ); // accessed from Client & Server Side
  Session.setData(
    {
      password: password,
    },
    false
  ); // Only accessed from Server Side
}

Get Session data

import { useSession } from  "@bunpmjs/bunext/features/session";
export default function Page() {
	return <div>
		<ReactElement />
	</div>
}

function ReactElement() {
	const session = useSession();
	return <span>{session.getData()?.username || "not logged"}</span>
}

Delete Session

// index.tsx
import {
  useSession,
  GetSession
} from  "@bunpmjs/bunext/features/session";

export default function Page() {
	return <div>
		<ReactElement />
	</div>


}
// using a JS event from a React Element
function ReactElement() {
	const session = useSession();
	return <button onClick={() => session.delete()}>Click to delete the session</button>
}

// using a serverAction
export async function ServerDeleteSesion() {
	GetSession(arguments).delete();
	return "Session has been deleted by the server"
}

// using an API endpoint
export function GET(request: BunextRequest) {
  GetSession(arguments).delete();
  request.response = new Response("Session Deleted");
  return request;
}

Server Action

Like Next offer a ServerAction method Bunext does it as well. Key informations:

  • Works with use server and use client
  • Server Action name should always start with Server key word
  • Server Action must be exported async function
  • It can be called like a normal async function from the client side
  • File must be on the first level of params you cannot put a file in an object
  • File Array is supported
// index.tsx
export default function FormPage() {
  return (
    <form
      onSubmit={async (e) => {
        e.preventDefault();
        const form = new FormData(e.currentTarget);
        const res = await ServerUploadFile(
          {
            username: form.get("username") as string,
            password: form.get("password") as string,
          },
          form.get("file") as File
        );
        alert(JSON.stringify(res));
      }}
    >
      <input type="file" name="file" />
      <input type="text" placeholder="username" name="username" />
      <input type="text" placeholder="password" name="password" />
      <button type="submit">Send</button>
    </form>
  );
}

export async function ServerUploadFile(
  {
    username,
    password,
  }: {
    username: string;
    password: string;
  },
  file: File
) {
  // do stuff
  await Bun.write("path/" + file.name, file);
  return {
    success: true,
    message: "file saved successfuly",
  };
}

Server Componants

Bunext offer a Server Componants ability that is managed with revalidate. Will run only once at build time and when revalidate is ran.

  • unless "use client" directive is set, exported function will be verify as a server Componant.
  • Must be empty props.
  • Must be exported and can be async as well.
  • revalidate will invalidate every componants that are in the page.
// index.tsx

export default async function Page() {
  return (
    <div>
      {await Componants()}
      <NotValid />
    </div>
  );
}
// valid Server Componant
export async function Componants() {
  const res = await (await fetch("https://some-api.com/api")).json();
  return <div>{JSON.stringify(res)}</div>;
}

// not valid Server Componant
export function NotValid({ someProps }: { someProps: string }) {
  return <div></div>;
}

Revalidate a Server Componant

// index.tsx
import { revalidateEvery, revalidate } from "@bunpmjs/bunext/features/router";
export default function Page() {
  revalidateEvery("/", 3600);
  // will revalidate the page at every 3600 second
  return <div>
    <button onClick={() => ServerRevalidate("/")}>Revalidate / path</button>
  </div>;
}

export async function ServerRevalidate(path: string) {
  await revalidate(path);
  // will revalidate the page right now
}

GetServerSideProps

Load dynamic data directly into the main React Element.

// Request URL /informationID
// [id].tsx
export default function Page(data: {
  props: {
    foo: string,
    name: {
      john: string
      }
    },
  params: {
    id: string
  }
  }) {
    return <div>{data.props.foo + " - " + data.params.id}</div> // bar - informationID
  }


export async function getServerSideProps() {
  // go get some api data, database, etc...

  // return { redirect: "/path/to/another/location" };
  // will redirect to a diferent location
  return {
    foo: "bar",
    name: {
      john: "Doe"
    }
  };
}

Database

Configure the database

In /config/database.ts is for the database Shema.

this is pretty much a basic structure that will make type safe your database call.

Exemple:

const MyDatabaseShema: DBSchema = [
  {
    name: "Users",
    columns: [
      {
        name: "id",
        type: "number",
        unique: true,
        autoIncrement: true,
        primary: true,
      },
      {
        name: "username",
        unique: true,
        type: "string",
      },
      {
        name: "test",
        type: "boolean",
      },
      {
        name: "foo",
        type: "json",
        DataType: [
          {
            foo: "string",
            bar: ["number"],
          },
        ],
      },
    ],
  },
];


export default MyDatabaseShema;

Create the database and Type

run this script

#!/bin/bash
bun run db:create

Query the Database

Database is only allowed in Server Side

  • select => Array of rows containing what you selected ( default to everything )
  • delete => void
  • insert => void
  • update => void
// index.tsx
import { Database } from "@bunpmjs/bunext/database";

//in a Server Componant
export async function ReactElement() {
  const db = Database();

  return (
    <div>
      {db.tableName
        .select({
          select: {
            column1: true,
            column2: true,
          },
          where: {
            OR: [
              {
                column1: "foo",
                column2: "bar",
              },
              {
                column1: "fizz",
                column2: "buzz",
              },
            ],
          },
        })
        .map((row) => {
          /*...doStuff*/
        })}
    </div>
  );
}

Router

Navigate

two methods to navigate to another page

// index.tsx
import { navigate, Link } from "@bunpmjs/bunext/internal/router";
function NextPage() {
  return <>
    <button onClick={() => navigate("/new/location")}>Next page</button>
    <Link href="/new/location">
      <button>Next Page</button>
    </Link>
  </>;
}

Set Head meta data

  • set path to the wanted route or * for every routes
  • will be revalidate on build time ( can be dynamic )
// /index.tsx
import { Head } from "@bunpmjs/bunext/features/head";

Head.setHead({
  data: {
    author: "John Doe",
    title: "my Hompage",
    publisher: "Bunext",
    meta: [
      {
        name: "foo",
        content: "bar",
      },
    ],
    link: [
      {
        rel: "stylesheet",
        href: "main.css"
      }
    ]
  },
  path: "/otherPath",
});

Run Script at Startup

config/preload.ts will run at startup

Configure Server

config/server.ts contain server related configuration

Bypass request

To make a custom Response in config/onRequest.ts, return (Response or async Response) to bypass the default behaviour, or return undefined to use the default behaviour.

API Endpoint

  • access the Endpoint via src/pages as root
import type { BunextRequest } from "@bunpmjs/bunext/features/request";

// /src/pages/api/v1/index.ts
export function POST(request: BunextRequest) {
  request.response = new Response("POST");
  return request;
}

export function GET(request: BunextRequest) {
  request.response = new Response("GET");
  return request;
}

export function PUT(request: BunextRequest) {
  request.response = new Response("PUT");
  return request;
}

export function DELETE(request: BunextRequest) {
  request.response = new Response("DELETE");
  return request;
}


// Client request
await fetch("my.site.com/api/v1", {
  method: "POST",
  body: JSON.stringify({ foo: "bar" })
}); // return the post data

Process.env

An environement variable can be set as public and accessed in a client context if the key starts with PUBLIC

PUBLIC_API_KEY="some-public-api-key"
API_KEY="private-api-key"

Change Log

0.6.17

  • Fix Fetch cache no store now works

0.6.18

  • Fix SVG not showing completely
  • Fix async Layout error on SSR & CSR rendering
  • Fix ServerComponant style prop not showing correcly causing hydration error

0.6.19

  • Fix Regression build crash introduced in 0.6.18

0.7.0

  • Fix production mode not initializing ServerAction (sorry for that)
  • Multi-threading on production mode when ServerConfig HTTPServer.threads is set to more then 1 or all_cpu_core (default: 1)

0.7.1

  • Fix Missing Type for ServerConfig thread

0.7.2

  • Fix page not loading correcly when there is no layout
  • Fix async layout in the hydration step
  • Improve compatibility with the multi-thread feature (will skip multi-thread on windows or mac) and now the main thread is making build and send the builded info to the workers
  • Other small improvement

0.7.3

  • Fix server not waiting for the build to finish before sending the response causing hydration error
  • Other small improvement

0.7.4

  • Fix getServersideProps taking time before responding
  • Performance improvement

0.7.5

  • Head path param is now required
  • Head path param can be * and apply to every page

0.7.7

  • Head display order modified path * is overwriten by the current path
  • Head data is now deep merged now meta and links are stacked

0.7.8

  • env variables can be made public by adding PULIC keyword. Ex: PUBLIC_API_KEY="abcdefghijklmnop12345678" // can be accessed from client and server API_KEY="abcdefghijklmnop12345678" // only accessed from server side

  • css can now be loaded direcly in the page as a link in /static path

  • @static path is now accessible to direcly access /static path

0.7.9

  • Fix missing global
  • file[] as prop in Server Action is supported
  • FormData as single prop in Server Action is supported

0.7.10

  • Fix Database key with special char would break the types
  • node_modules files can be imported as link ts and tsx files is compiled to js files ( beta ) ( css works )
  • Fix import not working in Server Componants
  • Fix import problem in production mode ( bun changed something in the minifing feature that broke the build for some reason )

0.7.13

  • Database is no longer async
  • File and Blob can be returned from a Server Action
  • Fix Head data not loading with dynamic routes

0.7.15

  • Session can be hosted on the server as a token and remove the limit of the standard 4000 char, when serverConfig.session.type = "database:memory" | "database:hard" and "cookie" will set as JSON-Webtoken but is limited with 4000 encoded char ( database:hard is the most stable for performance )

0.7.22

  • getServerSideProps can access session with getSession
  • fix getServersideProps not hot reloading
  • fix session not loading correcly when a token is valid but not present in the session database
  • minify is working on production
  • fit jsx import for some tsx files that was not on the index but imported by it.
  • fix session delete client side
  • fix hot reload server can be set to a different number then 3001
  • ServerActions are 95% smaller in bundle size
  • fix hot reload on dev mode for ServerActions
  • head data is no longer merged
  • hope it's the final fix for the compiler!

0.7.23

  • fix serverAction not sending multiple props
  • fix database select where with key that value was undefined break the request

0.8.0

  • Production mode compatible with Bun v-1.1.34
  • Performance enhancement!
  • fix layout re import when NODE_ENV is in production

0.8.4

  • Prevent future compatibility issue
  • Performance enhancement in production mode for Dynamic page like [id].tsx

0.8.9 (tmp fix for bun import problem in production mode)

  • add a plugin to fix Bun import some time breaking the request

0.8.11

  • Fix crash on dev mode when a cold refresh is made
  • Add some tweek to the database shemas
  • little performance enhancement
  • Update Documentation process.env