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

anticore-server

v3.0.0

Published

A low learning curve anticore server

Downloads

26

Readme

anticore-server

A low learning curve anticore server, based on

Install

npm i anticore-server

Create the templates

Create the templates

A layout template

src/templates/layout/layout.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="description" content="{view.description}" />
  <title>{view.title} - anticore-demo</title>
</head>
<body>
<header>
  <h1>{branding}</h1>
  <ol class="messages"></ol>
</header>
{view}
</body>
</html>

src/templates/layout/layout.js

import { load } from 'anticore-server/renderer.js'

// loads the ./layout.html and associates the provided properties
export default await load(import.meta, {}, {
  branding: 'anticore-server',
  view: null // just to know which properties can be filled later, on every clone
})

A fragment template

src/templates/fragment/fragment.html

<meta name="description" content="{view.description}" />
<title>{view.title}</title>
{view}

src/templates/fragment/fragment.js

import { load } from 'anticore-server/renderer.js'

export default await load(import.meta, {},  {
  view: null
})

An error template

src/templates/error/error.html

<ins class="error" data-after="form [name='{name}']">{message}</ins>

src/templates/error/invalid.js

import { load } from 'anticore-server/renderer.js'

export default await load(import.meta, {}, {
  name: null,
  message: null
})

Some view templates

The home

src/templates/view/home/home.html
<main class="{class}">
  <h1>{title}</h1>
</main>
src/templates/views/home/home.js
import { load } from 'anticore-server/renderer.js'

export default await load(import.meta, {}, {
  class: 'home',
  description: 'A homepage description',
  title: 'A homepage title'
})

A fragment template

src/templates/fragment/fragment.html

<meta name="description" content="{view.description}" />
<title>{view.title}</title>
{view}

src/templates/fragment/fragment.js

import { load } from 'anticore-server/renderer.js'

export default await load(import.meta, {},  {
  view: null
})

An error template

src/templates/error/error.html

<ins class="error" data-after="form [name='{name}']">{message}</ins>

src/templates/error/invalid.js

import { load } from 'anticore-server/renderer.js'

export default await load(import.meta, {}, {
  name: null,
  message: null
})

A view component

src/templates/components/view/view.html
<main class="{class}">
  <h1>{title}</h1>
</main>
src/templates/components/view/view.js
import { load } from 'anticore-server/renderer.js'

export default await load(import.meta, {}, {
  class: null,
  contents: null,
  description: null,
  title: null
})

Some view templates

The home

src/templates/views/home/home.js
import view from '../../components/view/view.js'

export default {
  ...view,
  class: 'home',
  contents: 'A home view content',
  description: 'A homepage description',
  title: 'A homepage title'
}

The Not Found

src/templates/views/error404/error404.js
import view from '../../components/view/view.js'

export default {
  ...view,
  class: 'error error404',
  contents: null,
  description: 'Page not found',
  title: 'Page not found'
}

The Internal Server Error

src/templates/views/error500/error500.js
import view from '../../components/view/view.js'

export default {
  ...view,
  class: 'error error500',
  contents: null,
  description: 'Internal Server Error',
  title: 'Internal Server Error'
}

A sse template

src/templates/sse/message/message.html

<li class="message">{contents}</li>

src/templates/sse/message/message.js

import { load } from 'anticore-server/renderer.js'

export default await load(import.meta, {}, {
  contents: null
})

Create your own responder

src/lib/responder.js

import * as responder from 'anticore-server/responder.js'
import error from '../templates/error/error.js'
import fragment from '../templates/fragment/fragment.js'
import layout from '../templates/layout/layout.js'

// Used for the partials
export const partial = responder.partial({ error })

// Used for the views
export const view = responder.view({ error, fragment, layout })

// Used for the Server-Sent Events
export const sse = responder.sse({ error })

sse(reply)

Returns an async function to emit an event to the client

await event(eventName, id, template, {
  // Your dynamic data
  data: {},
  /*
  // Optional object, rendered using the error template
  errors: null
  */
})

partial(reply)

Returns an async function to reply a partial to the client

await partial(reply, template, {
  // Your dynamic data
  data: {},
  /*
  // Optional object, rendered using the error template
  errors: null,
  // optional code, resolved like this by default `errors ? 422 : 200`
  code: 200
  */
})

view(reply)

Returns an async function to emit a view to the client

await view(reply, template, {
  // Your dynamic data
  data: {},
  /*
  // Optional object, rendered using the error template
  errors: null,
  // optional code, resolved like this by default `errors ? 422 : 200`
  code: 200
  */
})

Create an app

src/lib/app.js

import createApp from 'anticore-server/app.js'
// import { resolve } from 'path'
// import { cwd } from 'process'
import { view } from '../lib/responder.js'
import error404 from '../templates/views/error404/error404.js'
import error500 from '../templates/views/error500/error500.js'

const app = createApp({
  /*
  // fastify options, no defaults
  app: {},
  // fastify-compress options, no defaults
  compress: {},
  // fastify-multipart options, with the following defaults
  multipart: {
    attachFieldsToBody: true
  },
  // fastify-static options, with the following defaults
  statics: {
    prefix: '/assets/',
    root: resolve(cwd(), `src/assets`)
  }
  */
})

app.setNotFoundHandler(async (request, reply) => {
  return view(reply, error404, {
    data: {
      contents: 'Unable to locate the requested page'
    },
    code: 404
  })
})

app.setErrorHandler(async (error, request, reply) => {
  request.log.error(error)

  return view(reply, error500, {
    data: {
      contents: 'Oops, an unexcpected error was thrown'
    },
    code: 500
  })
})

export default app

Create some routes

A default route (view)

src/routes/home.js

import app from '../lib/app.js'
import { view } from '../lib/responder.js'
import home from '../templates/views/home/home.js'

app.get('/', async (request, reply) => {
  return view(reply, home)
})

A messages route (sse)

src/routes/messages.js

import { setTimeout } from 'timers/promises'
import app from '../lib/app.js'
import { sse } from '../lib/responder.js'
import message from '../templates/sse/message/message.js'

app.get('/messages', async (request, reply) => {
  const event = sse(reply)

  let id = 0

  while (!reply.raw.writableEnded) {
    id += 1

    await event('ping', id, message, {
      data: {
        message: `Message ${id}`
      }
    })

    await setTimeout(1000)
  }
})

Index your routes

src/routes/index.js

import './home.js'
import './messages.js'

Serve your app

src/serve.js

import { serve } from 'anticore-server/server.js'
import app from './lib/app.js'
import './routes/index.js'

await serve(app)

Start it

node src.serve.js --open

Need some interactivity?

See it in action into the anticore demo

Changelog

changelog

License

MIT