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 🙏

© 2025 – Pkg Stats / Ryan Hefner

transitus

v0.3.1-alpha0.0.1

Published

![NPM Version](https://img.shields.io/npm/v/transitus) ![NPM Unpacked Size : mjs and js](https://img.shields.io/npm/unpacked-size/transitus) ![NPM Last Update](https://img.shields.io/npm/last-update/transitus) ![NPM Downloads](https://img.shields.io/np

Downloads

41

Readme

fTutteS-Transitus

NPM Version NPM Unpacked Size : mjs and js NPM Last Update NPM Downloads NPM License npm package minimized gzipped size GitHub repo size GitHub branch status GitHub commit activity GitHub last commit X (formerly Twitter) URL

latest version -> [email protected]

Installation

このライブラリは単体でのセットアップは推奨していません。 代わりにtommandライブラリによるセットアップが推奨されています。

npx tommand create-transitus-ftuttes プロジェクト名

Usage

最初にTommandによってテンプレートプロジェクトが作成された後、以下のコマンドを実行します。

npm run dev

このコマンドを実行すると、nodeJsサーバーが起動します。 この時、index.htmlファイルはプロジェクトルートに置かれていかなければなりません。

Server Example

tommandライブラリでセットアップした場合、run.tsというファイルがsrc/にあるかと思います。 その中身は以下のようになります。

import { TransitusServer, DefaultRequestHandler, HotReload } from "./middlewares/defaultRequestHandler";

process.env.NODE_ENV = "development";

const middlewares = [
    new DefaultRequestHandler("index.html"),
];

const settings = [
    new HotReload({
        watchPaths: ["./src", "./config", "./public"],
        excludePatterns: ["node_modules", "dist", ".git", "*.log", "*.tmp"],
        debounceMs: 500,
        enabled: process.env.NODE_ENV === "development"
    }),
];

const server = new TransitusServer(middlewares, settings);

server.run();

Transitusサーバーを起動するにはTransitusServerクラスを作成して、runメソッドを実行します。 そして、tommandプロジェクトでデフォルトで規定されたnpm run devを実行します。

TransitusServerクラスは二つの引数を持ちます。

  • middlewares: MiddleWareクラスを継承したインスタンスの配列
  • serverSetting: ServerSettingクラスを継承したインスタンスの配列

MiddleWareクラス

MiddleWareクラスの実装は以下の通りです。

import { IncomingMessage, ServerResponse } from 'http';

export interface MiddleWare { 
    sequence(request: IncomingMessage, response: ServerResponse): void;
}

基本的にミドルウェアは、リクエストとレスポンスの間でそれらを処理する中間処理を行います。 transitusでは、DefaultRequestHandlerというミドルウェアを提供しています。

DefaultRequestHandler

DefaultRequestHandlerはミドルウェアの一種です。 このミドルウェアは、

  • DefaultRequestHandlerクラスはMiddleWareインターフェースを実装

  • HTTPリクエストとレスポンスの処理を担当

  • HTMLファイルパスのコンストラクタ注入による設定

  • URLパスの解析とファイルパス変換

  • コンテンツタイプの自動判定

  • HTMLルートと静的ファイルの区別処理

  • ファイルハンドリング

  • 静的ファイルの読み込みと提供

  • HTMLルートへの適切なレスポンス

  • エラーハンドリング(404, 500)

  • コンテンツ管理

  • 多様なファイル形式のサポート(HTML, JS, CSS, JSON, 画像など)

  • MIMEタイプの自動設定

  • SPAルーティング対応 などの基本的なNodeJSサーバーに必要な機能が含まれています。

ServerSettingクラス

ServerSettingクラスの実装は以下の通りです。

import { TransitusServer } from '../logic/server';
import { Server } from 'http';

export interface ITransitusServer {
    restart(): void;
    stop(): void;
    getServer(): Server | undefined;
}

export interface ServerSetting { 
    initialize(server: Server, tserver: TransitusServer): void;
    cleanup?(): void;
    name?: string;
}
HotReload

HotReloadはファイルの変更を検知した際に自動的にリビルドする機構を提供しています。 ただ、WebSocketを使用していないので、ブラウザ側は自身でリロードしなければなりません。 ※ただし、npm run devを実行してから、index.htmlをVSCode拡張機能のLiveServerで起動するといい感じです。。。

Component Example

最初にRouterクラスを作ります。

const router = new Router("/");

コンストラクタには最初に表示されるホームパスを文字列で代入します。

次にAppRouterコンポーネントを使用します。

const appRoutes = new Map<string, View>();
appRoutes.set("/", new HomePage());
appRoutes.set("/about", new AboutPage());
appRoutes.set("/contact", new ContactPage());

const appRouter = new AppRouter({
    routes: appRoutes,      // 定義したルートマップ
    page404: new NotFoundPage(), // 404ページ
    homePage: new HomePage(),    // ホームページ(パスが"/"の場合や、不正なパス形式の場合)
    startPageRoute: "/" // アプリケーション起動時の現在のパス
});

これをassembleViewでアセンブルします。

ページの遷移にはRouterpushメソッドとpopメソッドを使用します。 引数にはパスを入れます。

new ElevatedButton({
    onClick: () => {
        router.push("about");
    },
    child: new Text({
        text: "Go to the About page"
    })
});

new ElevatedButton({
    onClick: () => {
        router.pop();
    },
    child: new Text({
        text: "もどる"
    })
});

全体のコードを以下に記します。

import {
    View,
    Text,
    Column,
    ElevatedButton,
    BaseCSS,
    TextCSS,
    FontCSS,
    assembleView,
    BorderCSS,
    ProviderObserver,
} from 'ftuttes';

import { AppRouter, Router } from 'transitus';

new ProviderObserver().outLogs(true);

const router = new Router("/");

// --- 各ページのView定義 ---

/**
 * ホームページ View
 */
class HomePage extends View {
    override build(): View {
        return new Column({
            baseCSS: new BaseCSS({
                margin: "20px",
                padding: "20px",
                background: "#e0ffe0",
                borderCSS: new BorderCSS({borderSize: "1px", borderProperty: "solid", color: "#a0ffa0", radius: "8px"})
            }),
            children: [
                new Text({
                    text: "✨ ホームページへようこそ! ✨",
                    textCSS: new TextCSS({ fontCSS: new FontCSS({ fontSize: "30px", color: "green", fontWeight: "bold" }) })
                }),
                new Text({
                    text: "ここはアプリケーションの開始地点です。",
                    textCSS: new TextCSS({ fontCSS: new FontCSS({ fontSize: "16px", color: "#333" }) })
                }),
                new ElevatedButton({
                    child: new Text({
                        text: "アバウトページへ行く"
                    }),
                    onClick: () => {
                        router.push("/about");
                    }, // URLを変更してルーティング
                    baseCSS: new BaseCSS({ margin: "15px 0" })
                }),
                new ElevatedButton({
                    child: new Text({text: "お問い合わせページへ行く"},),
                    onClick: () => {
                        router.push("/contact");
                    }, // URLを変更してルーティング
                    baseCSS: new BaseCSS({ margin: "5px" })
                })
            ]
        });
    }
}

/**
 * アバウトページ View
 */
class AboutPage extends View {
    override build(): View {
        return new Column({
            baseCSS: new BaseCSS({
                margin: "20px",
                padding: "20px",
                background: "#e0e0ff",
                borderCSS: new BorderCSS({ borderSize: "1px", borderProperty: "solid", color: "#a0a0ff", radius: "8px" })
            }),
            children: [
                new Text({
                    text: "ℹ️ アバウトページ ℹ️",
                    textCSS: new TextCSS({ fontCSS: new FontCSS({ fontSize: "30px", color: "blue", fontWeight: "bold" }) })
                }),
                new Text({
                    text: "このアプリケーションについての情報です。",
                    textCSS: new TextCSS({ fontCSS: new FontCSS({ fontSize: "16px", color: "#333" }) })
                }),
                new ElevatedButton({
                    child: new Text({ text: "ホームへ戻る" }),
                    onClick: () => {
                        router.push("/");
                    }, // URLを変更してルーティング
                    baseCSS: new BaseCSS({ margin: "15px 0" })
                })
            ]
        });
    }
}

/**
 * お問い合わせページ View
 */
class ContactPage extends View {
    override build(): View {
        return new Column({
            baseCSS: new BaseCSS({
                margin: "20px",
                padding: "20px",
                background: "#ffffe0",
                borderCSS: new BorderCSS({ borderSize: "1px", borderProperty: "solid", color: "#ffffa0", radius: "8px" })
            }),
            children: [
                new Text({
                    text: "✉️ お問い合わせ ✉️",
                    textCSS: new TextCSS({ fontCSS: new FontCSS({ fontSize: "30px", color: "orange", fontWeight: "bold" }) })
                }),
                new Text({
                    text: "ご質問やご意見はこちらからどうぞ。",
                    textCSS: new TextCSS({ fontCSS: new FontCSS({ fontSize: "16px", color: "#333" }) })
                }),
                new ElevatedButton({
                    child: new Text({ text: "ホームへ戻る" }),
                    onClick: () => {
                        router.push("/");
                    }, // URLを変更してルーティング
                    baseCSS: new BaseCSS({ margin: "15px 0" })
                })
            ]
        });
    }
}

/**
 * 404 Not Found ページ View
 */
class NotFoundPage extends View {
    override build(): View {
        return new Column({
            baseCSS: new BaseCSS({
                margin: "20px",
                padding: "20px",
                background: "#ffe0e0",
                borderCSS: new BorderCSS({ borderSize: "1px", borderProperty: "solid", color: "#ffa0a0", radius: "8px" })
            }),
            children: [
                new Text({
                    text: "🚨 404 - ページが見つかりません 🚨",
                    textCSS: new TextCSS({ fontCSS: new FontCSS({ fontSize: "30px", color: "red", fontWeight: "bold" }) })
                }),
                new Text({
                    text: "お探しのページは見つかりませんでした。",
                    textCSS: new TextCSS({ fontCSS: new FontCSS({ fontSize: "16px", color: "#333" }) })
                }),
                new ElevatedButton({
                    child: new Text({ text: "ホームへ戻る" }),
                    onClick: () => {
                        router.push("/");
                    }, // URLを変更してルーティング
                    baseCSS: new BaseCSS({ margin: "15px 0" })
                })
            ]
        });
    }
}

// --- AppRouter の設定とアプリケーションのルート View ---

// ルート定義用のMapを作成
const appRoutes = new Map<string, View>();
appRoutes.set("/", new HomePage());
appRoutes.set("/about", new AboutPage());
appRoutes.set("/contact", new ContactPage());

/**
 * アプリケーションのルート View
 */
export class App extends View {
    override build(): View {
        return new Column({
            baseCSS: new BaseCSS({
                width: "100%",
                height: "95vh", // ページ全体をカバー
                background: "#f0f2f5"
            }),
            children: [
                // ここでAppRouterを配置し、現在のパスに基づいてページをレンダリングさせる
                new AppRouter({
                    routes: appRoutes,      // 定義したルートマップ
                    page404: new NotFoundPage(), // 404ページ
                    homePage: new HomePage(),    // ホームページ(パスが"/"の場合や、不正なパス形式の場合)
                    startPageRoute: window.location.pathname // アプリケーション起動時の現在のパス
                }),
                new ElevatedButton({
                    onClick: () => {
                        router.pop();
                    },
                    child: new Text({
                        text: "もどる"
                    })
                })
            ]
        });
    }
}

assembleView(new App());

ライセンス

MIT