A low learning curve anticore server, based on
npm i anticore-server
<!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>
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
})
<meta name="description" content="{view.description}" />
<title>{view.title}</title>
{view}
import { load } from 'anticore-server/renderer.js'
export default await load(import.meta, {}, {
view: null
})
<ins class="error" data-after="form [name='{name}']">{message}</ins>
import { load } from 'anticore-server/renderer.js'
export default await load(import.meta, {}, {
name: null,
message: null
})
<main class="{class}">
<h1>{title}</h1>
</main>
import { load } from 'anticore-server/renderer.js'
export default await load(import.meta, {}, {
class: 'home',
description: 'A homepage description',
title: 'A homepage title'
})
<meta name="description" content="{view.description}" />
<title>{view.title}</title>
{view}
import { load } from 'anticore-server/renderer.js'
export default await load(import.meta, {}, {
view: null
})
<ins class="error" data-after="form [name='{name}']">{message}</ins>
import { load } from 'anticore-server/renderer.js'
export default await load(import.meta, {}, {
name: null,
message: null
})
<main class="{class}">
<h1>{title}</h1>
</main>
import { load } from 'anticore-server/renderer.js'
export default await load(import.meta, {}, {
class: null,
contents: null,
description: null,
title: null
})
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'
}
import view from '../../components/view/view.js'
export default {
...view,
class: 'error error404',
contents: null,
description: 'Page not found',
title: 'Page not found'
}
import view from '../../components/view/view.js'
export default {
...view,
class: 'error error500',
contents: null,
description: 'Internal Server Error',
title: 'Internal Server Error'
}
<li class="message">{contents}</li>
import { load } from 'anticore-server/renderer.js'
export default await load(import.meta, {}, {
contents: null
})
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 })
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
*/
})
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
*/
})
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
*/
})
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
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)
})
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)
}
})
import './home.js'
import './messages.js'
import { serve } from 'anticore-server/server.js'
import app from './lib/app.js'
import './routes/index.js'
await serve(app)
node src.serve.js --open