包详细信息

global-object-client

QWERN-9876r1MIT0.1.5

globalObject is a network communication protocol that allows client and server to interact reactively. The essence of global objects is that changing such an object on one device changes it everywhere. This allows you to write high-level code for network

globalobject, network protocol, reactivity, fast

自述文件

global-object-client

Try this

client

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <link rel="stylesheet" href="./src/style.css" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Chat on global objects</title>
    </head>
    <body>
        <div id="chats">
            <h1>Chats</h1>
            <section id="listOfChats">Loading...</section>
        </div>

        <div id="chat" style="display: none">
            <section class="messages">Loading...</section>
            <div class="inputSection">
                <input class="inputMessage" />
                <button class="sendBtn">send</button>
            </div>
        </div>
        <script type="module" src="/src/main.ts"></script>
    </body>
</html>

src/main.ts

import { GlobalObject } from 'global-object-client'

import { Chat } from './chat'

interface Chat {
    id: string
    name: string
}

;(async () => {
    const chatsSection = document.querySelector('#chats') as HTMLDivElement

    const listOfChats = document.querySelector('#listOfChats') as HTMLDivElement

    const chats = await GlobalObject.get<Chat[]>(SERVER_URL + '/chats')

    function render() {
        if (!Array.isArray(chats)) return

        listOfChats.innerHTML = ''

        chats.forEach(({ id, name }) => {
            const chat = document.createElement('button')

            chat.classList.add('chat')

            chat.textContent = name

            chat.addEventListener('click', () => {
                chatsSection.style.display = 'none'
                Chat(id)
            })

            listOfChats.appendChild(chat)
        })
    }

    render()

    chats.addEventListener('change', render)
})()

src/chats.ts

import { GlobalObject } from 'global-object-client'

import { SERVER_URL } from './env.json'

interface Message {
    author: string
    text: string
    time: number
}

const userName = localStorage.getItem('userName') || Math.random().toString()

localStorage.setItem('userName', userName)

const messages = document.querySelector('.messages') as HTMLDivElement
const inputMessage = document.querySelector('.inputMessage') as HTMLInputElement
const sendBtn = document.querySelector('.sendBtn') as HTMLButtonElement
const chat = document.querySelector('#chat') as HTMLDivElement

export function Chat(id: string) {
    chat.style.display = 'block'

    GlobalObject.get<Message[]>(SERVER_URL + `/chat/${id}`).then((gObj) => {
        function render() {
            if (!Array.isArray(gObj)) return
            if (GlobalObject.getState(gObj) !== 'added') return

            messages.innerHTML = ''

            gObj.forEach(({ text, time, author }) => {
                const messageDiv = document.createElement('div')
                const messageDivInner = document.createElement('div')
                const timeSpan = document.createElement('span')
                const textSpan = document.createElement('span')
                messageDiv.classList.add('message')
                if (author === userName) messageDiv.classList.add('myMessage')

                textSpan.classList.add('text')
                textSpan.textContent = text

                timeSpan.classList.add('time')
                const date = new Date(time)
                timeSpan.textContent =
                    date.getHours() +
                    ':' +
                    (date.getMinutes() < 10 ? '0' : '') +
                    date.getMinutes()

                messageDivInner.appendChild(textSpan)
                messageDivInner.appendChild(timeSpan)
                messageDiv.appendChild(messageDivInner)
                messages.appendChild(messageDiv)
            })
        }

        function sendMassage() {
            if (!Array.isArray(gObj) || !inputMessage.value.trim()) return

            const message: Message = {
                author: userName,
                text: inputMessage.value,
                time: Date.now(),
            }

            gObj.push(message)
            inputMessage.value = ''
        }

        render()

        gObj.addEventListener('change', render)
        gObj.addEventListener('remove', render)

        sendBtn.addEventListener('click', sendMassage)
        document.addEventListener(
            'keypress',
            ({ key }) => key === 'Enter' && sendMassage()
        )
    })
}

server

main.ts

import { GlobalObject } from 'global-object-server'

import express from 'express'
import { createServer } from 'node:http'

interface Message {
    author: string
    text: string
    time: number
}

interface Chat {
    id: string
    name: string
}

const app = express()

app.use(function (_, res, next) {
    res.header('Access-Control-Allow-Origin', '*')
    res.header('Access-Control-Allow-Headers', 'X-Requested-With')
    res.header('Access-Control-Allow-Headers', 'Content-Type')
    res.header(
        'Access-Control-Allow-Methods',
        'PUT, GET, POST, DELETE, OPTIONS'
    )
    next()
})

const server = createServer(app)

GlobalObject.config.server = server

const chats = GlobalObject.create<Chat[]>([])

for (let i = 1; i <= 10; i++) {
    chats[i - 1] = {
        name: String(i),
        id: String(i),
    }

    const chat = GlobalObject.create<Message[]>([
        {
            author: 'Server',
            text: `Chat ${i} started`,
            time: Date.now(),
        },
    ])

    GlobalObject.send(chat, PORT, `/chat/${i}`)
}

GlobalObject.send(chats, PORT, '/chats')