From 6edab543549e06bf0ae19102622d66eeb057c896 Mon Sep 17 00:00:00 2001 From: Ayo Date: Thu, 4 Jun 2026 11:17:09 +0000 Subject: [PATCH] feat: new architecture to support server framework plugin - generic `server.serve` config - new demo workspace - new basic template - updated readme Reviewed-on: https://git.ayo.run/ayo/mcfly/pulls/3 Co-authored-by: Ayo Co-committed-by: Ayo --- .prettierignore | 2 +- CONTRIBUTING.md | 2 +- README.md | 2 +- eslint.config.mjs | 2 +- package.json | 1 - packages/config/README.md | 2 +- packages/config/package.json | 4 +- packages/core/README.md | 2 +- packages/core/package.json | 4 +- packages/create-mcfly/README.md | 2 +- .../create-mcfly/{src/index.ts => index.js} | 45 +- packages/create-mcfly/package.json | 10 +- packages/create-mcfly/tsconfig.json | 10 - packages/fastify/LICENSE | 21 + packages/fastify/README.md | 72 + packages/fastify/package.json | 2 +- pnpm-lock.yaml | 9037 ++++++++++++----- pnpm-workspace.yaml | 4 + site/README.md | 2 +- site/package.json | 2 +- site/src/pages/demo.html | 2 +- templates/{basic => basic-legacy}/.gitignore | 0 templates/{basic => basic-legacy}/README.md | 0 templates/basic-legacy/mcfly.config.mjs | 6 + templates/basic-legacy/package.json | 16 + .../{basic => basic-legacy}/src/api/users.js | 0 .../src/components/awesome-header.html | 0 .../src/components/code-block.js | 0 .../src/components/my-footer.html | 0 .../src/components/my-head.html | 0 .../src/components/my-hello-world.js | 0 templates/basic-legacy/src/pages/index.html | 53 + .../src/public/apple-touch-icon.png | Bin .../src/public/favicon.ico | Bin .../src/public/favicon.svg | 0 .../src/public/mask-icon.svg | 0 .../src/public/reset.css | 0 .../src/public/robots.txt | 0 .../src/public/touch-icon-large.png | Bin .../{basic => basic-legacy}/tsconfig.json | 0 templates/basic/mcfly.config.mjs | 8 +- templates/basic/package.json | 21 +- templates/basic/src/api/README.md | 29 + templates/basic/src/api/example/index.js | 6 + templates/basic/src/api/index.js | 5 + templates/basic/src/api/root.js | 6 + templates/basic/src/pages/index.html | 59 +- 47 files changed, 6961 insertions(+), 2478 deletions(-) rename packages/create-mcfly/{src/index.ts => index.js} (83%) delete mode 100644 packages/create-mcfly/tsconfig.json create mode 100644 packages/fastify/LICENSE create mode 100644 packages/fastify/README.md rename templates/{basic => basic-legacy}/.gitignore (100%) rename templates/{basic => basic-legacy}/README.md (100%) create mode 100644 templates/basic-legacy/mcfly.config.mjs create mode 100644 templates/basic-legacy/package.json rename templates/{basic => basic-legacy}/src/api/users.js (100%) rename templates/{basic => basic-legacy}/src/components/awesome-header.html (100%) rename templates/{basic => basic-legacy}/src/components/code-block.js (100%) rename templates/{basic => basic-legacy}/src/components/my-footer.html (100%) rename templates/{basic => basic-legacy}/src/components/my-head.html (100%) rename templates/{basic => basic-legacy}/src/components/my-hello-world.js (100%) create mode 100644 templates/basic-legacy/src/pages/index.html rename templates/{basic => basic-legacy}/src/public/apple-touch-icon.png (100%) rename templates/{basic => basic-legacy}/src/public/favicon.ico (100%) rename templates/{basic => basic-legacy}/src/public/favicon.svg (100%) rename templates/{basic => basic-legacy}/src/public/mask-icon.svg (100%) rename templates/{basic => basic-legacy}/src/public/reset.css (100%) rename templates/{basic => basic-legacy}/src/public/robots.txt (100%) rename templates/{basic => basic-legacy}/src/public/touch-icon-large.png (100%) rename templates/{basic => basic-legacy}/tsconfig.json (100%) create mode 100644 templates/basic/src/api/README.md create mode 100644 templates/basic/src/api/example/index.js create mode 100644 templates/basic/src/api/index.js create mode 100644 templates/basic/src/api/root.js diff --git a/.prettierignore b/.prettierignore index 68f3cc5..8888cda 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,6 +6,6 @@ **/*.yml **/*.yaml -templates +templates/** **/public/* \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f428d53..154633a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ After setting up `git send-email` you can now follow the steps below to start ha 1️⃣ Clone the repository to your local machine, then go into the project directory: ```bash -$ git clone https://git.sr.ht/~ayoayco/mcfly +$ git clone https://git.ayo.run/ayo/mcfly $ cd mcfly ``` diff --git a/README.md b/README.md index efcac10..d032fbb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- McFly logo + McFly logo

McFly

diff --git a/eslint.config.mjs b/eslint.config.mjs index 0490e0e..9016691 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -16,7 +16,7 @@ export default [ eslintPluginPrettierRecommended, includeIgnoreFile(gitignorePath), { - ignores: ['site/*', 'templates/*', '**/public/*', 'demo/*'], + ignores: ['site/*', 'templates/**', '**/public/*', 'demo/*'], }, { rules: { diff --git a/package.json b/package.json index dc9b539..5cf9ffb 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "build:site:preview": "pnpm -F site build:preview", "template:basic": "pnpm run build && pnpm -F basic-template start", "create:mcfly": "node ./packages/create-mcfly", - "create:component": "node ./packages/create-component", "cli": "node ./packages/core/cli/index.js", "test": "vitest --run", "lint": "eslint . --config eslint.config.mjs --cache", diff --git a/packages/config/README.md b/packages/config/README.md index 89f9fb1..9ed2883 100644 --- a/packages/config/README.md +++ b/packages/config/README.md @@ -1,5 +1,5 @@

- rRick & Morty cartoon + McFly Logo

McFly

diff --git a/packages/config/package.json b/packages/config/package.json index 2361018..77f3c3d 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@mcflyjs/config", - "version": "0.2.9", + "version": "0.3.0-alpha", "description": "Nitro configuration for McFly apps", "type": "module", "main": "./dist/index.js", @@ -19,7 +19,7 @@ }, "repository": { "type": "git", - "url": "https://git.sr.ht/~ayoayco/mcfly", + "url": "https://git.ayo.run/ayo/mcfly", "directory": "packages/config" }, "author": "Ayo Ayco", diff --git a/packages/core/README.md b/packages/core/README.md index 89f9fb1..9ed2883 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,5 +1,5 @@

- rRick & Morty cartoon + McFly Logo

McFly

diff --git a/packages/core/package.json b/packages/core/package.json index 3f8d7bd..21f4aa4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@mcflyjs/core", - "version": "0.8.8", + "version": "0.9.0-alpha", "description": "McFly core package", "type": "module", "main": "./dist/index.js", @@ -26,7 +26,7 @@ }, "repository": { "type": "git", - "url": "https://git.sr.ht/~ayoayco/mcfly", + "url": "https://git.ayo.run/ayo/mcfly", "directory": "packages/core" }, "author": "Ayo Ayco", diff --git a/packages/create-mcfly/README.md b/packages/create-mcfly/README.md index 20dbd69..6317444 100644 --- a/packages/create-mcfly/README.md +++ b/packages/create-mcfly/README.md @@ -1,5 +1,5 @@

- rRick & Morty cartoon + McFly Logo

Create McFly

diff --git a/packages/create-mcfly/src/index.ts b/packages/create-mcfly/index.js similarity index 83% rename from packages/create-mcfly/src/index.ts rename to packages/create-mcfly/index.js index 95f6eb8..8ca8da7 100755 --- a/packages/create-mcfly/src/index.ts +++ b/packages/create-mcfly/index.js @@ -7,15 +7,15 @@ import { spawnSync } from 'node:child_process' import path from 'node:path' const [, , directoryArg] = process.argv - -type PromptAction = { - prompt: string - info?: string - startMessage: string - command: string - subCommand: string - error: string -} +/** + * @typedef {Object} PromptAction + * @property {string} prompt - The prompt text to display + * @property {string} [info] - Additional information about the prompt + * @property {string} startMessage - Message to show when starting the action + * @property {string} command - The command to execute + * @property {string} subCommand - The subcommand to execute + * @property {string} error - Error message to display on failure + */ /** * Create McFly App @@ -42,7 +42,10 @@ async function create() { const hasErrors = await downloadTemplateToDirectory(directory) if (!hasErrors) { - const prompts: PromptAction[] = [ + /** + * @type {Array} + */ + const prompts = [ { prompt: `Would you like to install the dependencies to ${colorize( 'bold', @@ -80,7 +83,7 @@ async function create() { * @param {string} directory * @returns string */ -function getSafeDirectory(directory: string): string { +function getSafeDirectory(directory) { const { platform } = process const locale = path[platform === `win32` ? `win32` : `posix`] const localePath = directory.split(path.sep).join(locale.sep) @@ -92,16 +95,14 @@ function getSafeDirectory(directory: string): string { * @param {string} directory * @returns Promise hasErrors */ -async function downloadTemplateToDirectory( - directory: string -): Promise { +async function downloadTemplateToDirectory(directory) { let hasErrors = false try { consola.start( `Copying template to ${colorize('bold', getSafeDirectory(directory))}...` ) - await downloadTemplate('sourcehut:ayoayco/mcfly/templates/basic', { + await downloadTemplate('github:ayo-run/mcfly/templates/basic', { dir: directory, }) } catch (ㆆ_ㆆ) { @@ -123,11 +124,11 @@ async function downloadTemplateToDirectory( * @param {string} cwd * @returns Promise | undefined> */ -async function askPrompts( - prompts: PromptAction[], - cwd: string -): Promise { - const results: boolean[] = [] +async function askPrompts(prompts, cwd) { + /** + * @type {Array} + */ + const results = [] for (const p of prompts) { const userIntends = await consola.prompt(p.prompt, { @@ -169,7 +170,7 @@ async function askPrompts( * @param {string} directory * @param {boolean} installDeps */ -function showResults(directory: string, installDeps: boolean) { +function showResults(directory, installDeps) { let nextActions = [ `Go to your project by running ${colorize('yellow', `cd ${directory}`)}`, ] @@ -189,7 +190,7 @@ function showResults(directory: string, installDeps: boolean) { 'bold', 'McFly' )} app is ready: ${directory}\n\nNext actions: ${nextActions - .map((action, index) => `\n${++index}. ${action}`) + .map((action, index) => `\n${index}. ${action}`) .join('')}` consola.box(result) diff --git a/packages/create-mcfly/package.json b/packages/create-mcfly/package.json index 395aa65..28043ad 100644 --- a/packages/create-mcfly/package.json +++ b/packages/create-mcfly/package.json @@ -4,24 +4,22 @@ "description": "Create a new McFly app", "type": "module", "bin": { - "create-mcfly": "./dist/index.js" + "create-mcfly": "./index.js" }, - "main": "./dist/index.js", + "main": "./index.js", "exports": { ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "default": "./index.js" } }, "scripts": { - "build": "tsc --erasableSyntaxOnly", "version": "npm version", "publish": "npm publish", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", - "url": "https://git.sr.ht/~ayoayco/mcfly", + "url": "https://git.ayo.run/ayo/mcfly", "directory": "packages/create-mcfly" }, "author": "Ayo Ayco", diff --git a/packages/create-mcfly/tsconfig.json b/packages/create-mcfly/tsconfig.json deleted file mode 100644 index ab2dec0..0000000 --- a/packages/create-mcfly/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "include": ["src"], - "compilerOptions": { - "allowJs": true, - "emitDeclarationOnly": false, - "declarationDir": "./dist", - "outDir": "./dist" - } -} diff --git a/packages/fastify/LICENSE b/packages/fastify/LICENSE new file mode 100644 index 0000000..009a8d8 --- /dev/null +++ b/packages/fastify/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Ayo Ayco + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/fastify/README.md b/packages/fastify/README.md new file mode 100644 index 0000000..5c4547f --- /dev/null +++ b/packages/fastify/README.md @@ -0,0 +1,72 @@ +

+ McFly Logo +

+ +

McFly Fastify Adapter

+ +Use fastify as a server framework in McFly + +``` +npm create mcfly@latest +``` + +

McFly is a no-framework framework
that assists in building on the Web

+ +

+ + + +

+ +## Features + +The time has come for vanilla Web tech. 🎉 + +✅ Create web apps with vanilla custom elements
+✅ Write real .HTML files
+✅ Have no frameworks or reactivity libraries on the browser
+✅ Use server-side rendering
+✅ Deploy anywhere
+ +## Special directories + +**1. `./src/pages/`** + +- file-based routing for `.html` files +- directly use custom elements & static fragments (no imports or registry maintenance needed) +- use ` + + + + {{ project.name }} + {{ project.description }} + +
+

Welcome to {{ project.name }}

+

Server date time: {{new Date().toLocaleString()}}

+

+ Here's an interactive custom element: + +

+ +class MyHelloWorld extends WebComponent { + static props = { + myName: "World", + count: 0 + } + + updateLabel() { + this.props.myName = `Clicked ${++this.props.count}x`; + } + + get template() { + return html` + <button onClick=${() => this.updateLabel()} style="cursor:pointer"> + Hello ${this.props.myName}! + </button>`; + } +} +
+ + + Learn how to build components easily at WebComponent.io + + + + \ No newline at end of file diff --git a/templates/basic/src/public/apple-touch-icon.png b/templates/basic-legacy/src/public/apple-touch-icon.png similarity index 100% rename from templates/basic/src/public/apple-touch-icon.png rename to templates/basic-legacy/src/public/apple-touch-icon.png diff --git a/templates/basic/src/public/favicon.ico b/templates/basic-legacy/src/public/favicon.ico similarity index 100% rename from templates/basic/src/public/favicon.ico rename to templates/basic-legacy/src/public/favicon.ico diff --git a/templates/basic/src/public/favicon.svg b/templates/basic-legacy/src/public/favicon.svg similarity index 100% rename from templates/basic/src/public/favicon.svg rename to templates/basic-legacy/src/public/favicon.svg diff --git a/templates/basic/src/public/mask-icon.svg b/templates/basic-legacy/src/public/mask-icon.svg similarity index 100% rename from templates/basic/src/public/mask-icon.svg rename to templates/basic-legacy/src/public/mask-icon.svg diff --git a/templates/basic/src/public/reset.css b/templates/basic-legacy/src/public/reset.css similarity index 100% rename from templates/basic/src/public/reset.css rename to templates/basic-legacy/src/public/reset.css diff --git a/templates/basic/src/public/robots.txt b/templates/basic-legacy/src/public/robots.txt similarity index 100% rename from templates/basic/src/public/robots.txt rename to templates/basic-legacy/src/public/robots.txt diff --git a/templates/basic/src/public/touch-icon-large.png b/templates/basic-legacy/src/public/touch-icon-large.png similarity index 100% rename from templates/basic/src/public/touch-icon-large.png rename to templates/basic-legacy/src/public/touch-icon-large.png diff --git a/templates/basic/tsconfig.json b/templates/basic-legacy/tsconfig.json similarity index 100% rename from templates/basic/tsconfig.json rename to templates/basic-legacy/tsconfig.json diff --git a/templates/basic/mcfly.config.mjs b/templates/basic/mcfly.config.mjs index e158f3f..5d1a114 100644 --- a/templates/basic/mcfly.config.mjs +++ b/templates/basic/mcfly.config.mjs @@ -1,6 +1,6 @@ -// @ts-check -import { defineMcFlyConfig } from '@mcflyjs/config' +import { defineConfig } from '@mcflyjs/config' +import fastify from '@mcflyjs/fastify' -export default defineMcFlyConfig({ - components: 'js', +export default defineConfig({ + server: fastify(), }) diff --git a/templates/basic/package.json b/templates/basic/package.json index d259f59..d5cca9c 100644 --- a/templates/basic/package.json +++ b/templates/basic/package.json @@ -1,16 +1,17 @@ { - "name": "basic-template", - "description": "McFly starter project", + "name": "mcfly-basic", + "version": "1.0.0", + "description": "", + "main": "index.js", "scripts": { - "start": "mcfly serve", - "prepare": "mcfly prepare", - "dev": "mcfly serve", - "build": "mcfly build", - "preview": "node .output/server/index.mjs", - "build:preview": "npm run build && npm run preview" + "test": "echo \"Error: no test specified\" && exit 1", + "start": "mcfly serve" }, + "author": "", + "license": "ISC", "dependencies": { - "@mcflyjs/config": "^0.2.9", - "@mcflyjs/core": "^0.8.8" + "@mcflyjs/config": "^0.3.0-alpha", + "@mcflyjs/core": "^0.9.0-alpha", + "@mcflyjs/fastify": "^0.1" } } diff --git a/templates/basic/src/api/README.md b/templates/basic/src/api/README.md new file mode 100644 index 0000000..75b5658 --- /dev/null +++ b/templates/basic/src/api/README.md @@ -0,0 +1,29 @@ +# Routes Folder + +Routes define the pathways within your application. +Fastify's structure supports the modular monolith approach, where your +application is organized into distinct, self-contained modules. +This facilitates easier scaling and future transition to a microservice architecture. +In the future you might want to independently deploy some of those. + +In this folder you should define all the routes that define the endpoints +of your web application. +Each service is a [Fastify +plugin](https://fastify.dev/docs/latest/Reference/Plugins/), it is +encapsulated (it can have its own independent plugins) and it is +typically stored in a file; be careful to group your routes logically, +e.g. all `/users` routes in a `users.js` file. We have added +a `root.js` file for you with a '/' root added. + +If a single file becomes too large, create a folder and add a `index.js` file there: +this file must be a Fastify plugin, and it will be loaded automatically +by the application. You can now add as many files as you want inside that folder. +In this way you can create complex routes within a single monolith, +and eventually extract them. + +If you need to share functionality between routes, place that +functionality into the `plugins` folder, and share it via +[decorators](https://fastify.dev/docs/latest/Reference/Decorators/). + +If you're a bit confused about using `async/await` to write routes, you would +better take a look at [Promise resolution](https://fastify.dev/docs/latest/Reference/Routes/#promise-resolution) for more details. diff --git a/templates/basic/src/api/example/index.js b/templates/basic/src/api/example/index.js new file mode 100644 index 0000000..f0a706f --- /dev/null +++ b/templates/basic/src/api/example/index.js @@ -0,0 +1,6 @@ +export default async (fastify) => { + fastify.get('/', async function (request, reply) { + console.log({ request, reply }) + return 'This is an example' + }) +} diff --git a/templates/basic/src/api/index.js b/templates/basic/src/api/index.js new file mode 100644 index 0000000..ab7329b --- /dev/null +++ b/templates/basic/src/api/index.js @@ -0,0 +1,5 @@ +export default async (fastify) => { + fastify.get('/', async function (request, reply) { + return 'This is the API Index' + }) +} diff --git a/templates/basic/src/api/root.js b/templates/basic/src/api/root.js new file mode 100644 index 0000000..144eba9 --- /dev/null +++ b/templates/basic/src/api/root.js @@ -0,0 +1,6 @@ +export default async function (fastify, opts) { + fastify.get('/', async function (request, reply) { + console.log({ opts, request, reply }) + return { root: true } + }) +} diff --git a/templates/basic/src/pages/index.html b/templates/basic/src/pages/index.html index eab6b9c..aabfa89 100644 --- a/templates/basic/src/pages/index.html +++ b/templates/basic/src/pages/index.html @@ -1,53 +1,12 @@ - - - McFly: Back to the Basics. Into the Future. - - - - - {{ project.name }} - {{ project.description }} - -
-

Welcome to {{ project.name }}

-

Server date time: {{new Date().toLocaleString()}}

-

- Here's an interactive custom element: - -

- -class MyHelloWorld extends WebComponent { - static props = { - myName: "World", - count: 0 - } - - updateLabel() { - this.props.myName = `Clicked ${++this.props.count}x`; - } - - get template() { - return html` - <button onClick=${() => this.updateLabel()} style="cursor:pointer"> - Hello ${this.props.myName}! - </button>`; - } -} -
- - - Learn how to build components easily at WebComponent.io - - - + + + + WORK IN PROGRESS + + +

WORK IN PROGRESS

+

See the project repository for more info.

+ \ No newline at end of file