From b7e4f015131586c8e362807c736d7f139d74d728 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Mon, 13 May 2024 12:49:43 -0400 Subject: [PATCH 01/32] Added Development Server --- .gitignore | 1 + package-lock.json | 80 ++++++++-- package.json | 1 + src/cli/index.ts | 37 +++++ src/compiler/bundler/platforms/abstract.ts | 6 +- src/compiler/bundler/platforms/local/index.ts | 8 +- src/compiler/index.ts | 31 ++-- src/server-development/index.ts | 150 ++++++++++++++++++ src/server-local/index.ts | 16 +- .../endpoints/server/routes/regular/index.ts | 2 +- 10 files changed, 293 insertions(+), 39 deletions(-) create mode 100644 src/server-development/index.ts diff --git a/.gitignore b/.gitignore index 1ac4fed..49124ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ **/.vercel/ **/.sherpa/ +**/.sherpa-dev/ **/sherpa.TS_VALIDATION_BUFFER.ts /node_modules /dist diff --git a/package-lock.json b/package-lock.json index 4644f40..aad2e4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "checksum": "^1.0.0", + "chokidar": "^3.6.0", "colorette": "^2.0.20", "commander": "^11.1.0", "es-module-lexer": "^1.5.0", @@ -33,7 +34,7 @@ "ts-jest": "^29.1.2" }, "engines": { - "node": ">=16" + "node": ">=20" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2114,7 +2115,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -2276,6 +2276,17 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2290,7 +2301,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -2431,6 +2441,40 @@ "checksum": "bin/checksum-cli.js" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -3073,7 +3117,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3127,7 +3170,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -3384,6 +3426,17 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -3400,7 +3453,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3427,7 +3479,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -3439,7 +3490,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -4344,7 +4394,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4543,7 +4592,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -4728,6 +4776,17 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5089,7 +5148,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, diff --git a/package.json b/package.json index 32412ae..f1e0874 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "license": "ISC", "dependencies": { "checksum": "^1.0.0", + "chokidar": "^3.6.0", "colorette": "^2.0.20", "commander": "^11.1.0", "es-module-lexer": "^1.5.0", diff --git a/src/cli/index.ts b/src/cli/index.ts index 4b0da5e..a001a1b 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -20,6 +20,7 @@ import { getEnvironmentFiles, getAbsolutePath, getKeyValuePairs, getVersion } fr import { Logger } from "../compiler/utilities/logger/index.js"; import { Path } from "../compiler/utilities/path/index.js"; import { Level } from "../compiler/utilities/logger/model.js"; +import { ServerDevelopment } from "../server-development/index.js"; let CLI = new Command(); @@ -98,6 +99,42 @@ CLI.command("start") }); +CLI.command("dev") + .description("Start SherpaJS Development Server") + .option("-i, --input ", "path to SherpaJS server, defaults to current directory") + .option("-o, --output ", "path to server output, defaults to input directory") + .option("-v, --variable [keyvalue...]", "Specify optional environment variables as key=value pairs") + .option("-p, --port ", "port number", (3000).toString()) + .action((options) => { + let input = getAbsolutePath(options.input, process.cwd()); + let output = getAbsolutePath(options.output, input); + let variables = getKeyValuePairs(options.variable); + + if (Logger.hasError(variables.logs)) { + Logger.display(variables.logs); + Logger.exit(); + } + + new ServerDevelopment({ + input: input, + output: output, + bundler: BundlerType.local, + developer: { + bundler: { + esbuild: { + minify: options.dev ? false : true + } + }, + environment: { + files: getEnvironmentFiles(input), + variables: variables.values + } + } + }, parseInt(options.port)); + }); + + + CLI.parse(); diff --git a/src/compiler/bundler/platforms/abstract.ts b/src/compiler/bundler/platforms/abstract.ts index a48d8a1..68f2103 100644 --- a/src/compiler/bundler/platforms/abstract.ts +++ b/src/compiler/bundler/platforms/abstract.ts @@ -37,9 +37,9 @@ export abstract class Bundler { constructor(endpoints:Structure, options:BuildOptions, errors?:Message[]) { - this.endpoints = endpoints.endpoints; - this.assets = endpoints.assets; - this.sever = endpoints.server; + this.endpoints = endpoints.endpoints as EndpointStructure; + this.assets = endpoints.assets as AssetStructure; + this.sever = endpoints.server as ServerConfigFile; this.options = options; this.errors = errors; } diff --git a/src/compiler/bundler/platforms/local/index.ts b/src/compiler/bundler/platforms/local/index.ts index d8b339c..6dd89cf 100644 --- a/src/compiler/bundler/platforms/local/index.ts +++ b/src/compiler/bundler/platforms/local/index.ts @@ -14,7 +14,7 @@ import { Endpoint } from "../../../models.js"; import { Tooling } from "../../../utilities/tooling/index.js"; import { Path } from "../../../utilities/path/index.js"; -import { Bundler } from "../abstract.js"; +import { Bundler, View } from "../abstract.js"; import { RequestUtilities } from "../../../../native/request/utilities.js"; @@ -37,7 +37,6 @@ export class Local extends Bundler { private getBuffer() { - // FIXME - load view from static return ` import path from "path"; import { ServerLocal } from "${Path.join(Path.getRootDirectory(), "dist/src/server-local/index.js")}"; @@ -45,7 +44,8 @@ export class Local extends Bundler { const portArg = process.argv[2]; const port = portArg && !isNaN(parseInt(portArg)) ? parseInt(portArg) : 3000; - const server = new ServerLocal(port); + const silent = process.argv.includes("--silent-startup"); + const server = new ServerLocal(port, silent); const dirname = import.meta.dirname; ${this.endpoints.list.map((endpoint:Endpoint, index:number) => { return ` @@ -54,7 +54,7 @@ export class Local extends Bundler { `const endpoint_${index} = {};` } ${this.views[index] ? - `const view_${index} = "${encodeURIComponent(this.views[index].html)}";` : + `const view_${index} = "${encodeURIComponent((this.views[index] as View).html)}";` : `const view_${index} = "";` } import import_context_${index} from "${endpoint.module.contextFilepath}"; diff --git a/src/compiler/index.ts b/src/compiler/index.ts index 8ffb026..490547c 100644 --- a/src/compiler/index.ts +++ b/src/compiler/index.ts @@ -18,6 +18,7 @@ import { NewBundler, clean } from "./bundler/index.js"; import { BuildOptions, BundlerType } from "./models.js"; import { Level, Message } from "./utilities/logger/model.js"; import { Path } from "./utilities/path/index.js"; +import chokidar from "chokidar"; export { BundlerType }; @@ -32,22 +33,24 @@ export class Compiler { if (errorsOptions.length) { return this.display({ logs: errorsOptions, verbose, success: false }); } - - let structure = await getStructure(options.input); - let logs = structure.logs; - if (!structure.endpoints || !structure.server || !structure.assets) { - logs.push({ - level: Level.ERROR, - text: "Failed to generate endpoints." - }); - return this.display({ logs, verbose, success: false }); - } - if (Logger.hasError(logs)) { - return this.display({ logs, verbose, success: false }); - } - + let logs:Message[] = []; try { + let structure = await getStructure(options.input); + logs.push(...structure.logs); + + if (!structure.endpoints || !structure.server || !structure.assets) { + logs.push({ + level: Level.ERROR, + text: "Failed to generate endpoints." + }); + return this.display({ logs, verbose, success: false }); + } + + if (Logger.hasError(logs)) { + return this.display({ logs, verbose, success: false }); + } + await NewBundler(structure, options, logs).build(); } catch (error) { logs.push({ diff --git a/src/server-development/index.ts b/src/server-development/index.ts new file mode 100644 index 0000000..9421d52 --- /dev/null +++ b/src/server-development/index.ts @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2024 Sellers Industries, Inc. + * distributed under the MIT License + * + * author: Evan Sellers + * date: Mon May 13 2024 + * file: index.ts + * project: SherpaJS - Module Microservice Platform + * purpose: Local Development Server + * + */ + + +import fs from "fs"; +import chokidar from "chokidar"; +import { BuildOptions, Compiler } from "../compiler/index.js"; +import { Path } from "../compiler/utilities/path/index.js"; +import { ChildProcessWithoutNullStreams, spawn } from "child_process"; +import { Logger } from "../compiler/utilities/logger/index.js"; +import { cyan, green, red } from "colorette"; + + +export class ServerDevelopment { + + + private readonly options:BuildOptions; + private readonly port:number|undefined; + private server:ChildProcessWithoutNullStreams; + private initial:boolean; + + + constructor (options:BuildOptions, port?:number) { + this.options = options; + this.port = port; + this.initial = true; + this.makeTempDir(); + this.start(); + } + + + private start() { + this.refresh(); + chokidar.watch(this.options.input, { + persistent: true, + ignored: /(^|[\/\\])\../, // note: . files are ignored + }).on("change", (path, stats) => { + if (path && stats) { + this.refresh(); + } + }); + } + + + private async refresh() { + if (!this.initial) { + console.log(cyan("SherpaJS detected change, rebuilding...")); + } + + this.removeTempDir(); + this.makeTempDir(); + + let { success, logs } = await Compiler.build({ + ...this.options, + output: this.getTempDir() + }, false); + + if (success) { + this.copyFromTempDir(); + if (this.server) { + this.server.kill(); + } + this.server = spawn("node", [ + Path.join(this.options.output, "/.sherpa/index.js"), + this.port ? this.port.toString() : "", + !this.initial ? "--silent-startup" : "" + ]); + this.server.stdout.on("data", (data) => console.log(data.toString().replace("\n", ""))); + this.server.stderr.on("data", (data) => console.log(data.toString().replace("\n", ""))); + this.server.on("close", (data) => { if (data) console.log(data.toString().replace("\n", "") )}); + if (!this.initial) { + console.log(green("SherpaJS Server Rebuilt Successfully.")); + } else { + this.initial = false; + } + } else { + this.removeTempDir(); + Logger.display(logs); + console.log(red("SherpaJS Failed to Build Server.") + " See logs for more information.") + } + } + + + private copyFromTempDir() { + let filepath = Path.join(this.options.output, ".sherpa"); + if (fs.existsSync(filepath)) { + fs.rmSync(filepath, { recursive: true }); + } + this.copyDirectory( + Path.join(this.getTempDir(), ".sherpa"), + Path.join(this.options.output, ".sherpa") + ) + this.removeTempDir(); + } + + + private copyDirectory(source:string, destination:string) { + if (!fs.existsSync(destination)) { + fs.mkdirSync(destination, { recursive: true }); + } + + fs.readdirSync(source).forEach(file => { + let sourcePath = Path.join(source, file); + let destPath = Path.join(destination, file); + + if (fs.statSync(sourcePath).isDirectory()) { + this.copyDirectory(sourcePath, destPath); + } else { + fs.copyFileSync(sourcePath, destPath); + } + }); + } + + + private makeTempDir() { + let filepath = this.getTempDir(); + if (!fs.existsSync(filepath)) { + fs.mkdirSync(filepath); + } + } + + + private removeTempDir() { + let filepath = this.getTempDir(); + if (fs.existsSync(filepath)) { + fs.rmSync(filepath, { recursive: true }); + } + } + + + private getTempDir() { + return Path.join(this.options.output, ".sherpa-dev"); + } + + +} + + +// Teach me your way, Lord, that I may rely on your faithfulness; give me an +// undivided heart, that I may fear your name. +// - Psalm 86:11 diff --git a/src/server-local/index.ts b/src/server-local/index.ts index daf051b..cc0ed8e 100644 --- a/src/server-local/index.ts +++ b/src/server-local/index.ts @@ -29,15 +29,17 @@ type endpoint = { export class ServerLocal { - private port: number; + private readonly port: number; + private readonly silentStartup:boolean; private server: HTTPServer|null; private endpoints:endpoint[]; - constructor(port:number) { - this.endpoints = []; - this.port = port; - this.server = null; + constructor(port:number, silentStartup:boolean=false) { + this.endpoints = []; + this.port = port; + this.server = null; + this.silentStartup = silentStartup; } @@ -48,7 +50,9 @@ export class ServerLocal { this.server = createServer(this.handleRequest.bind(this)); this.server.listen(this.port, () => { - console.log(`${green("SherpaJS Server is started at")} ${cyan(`http://localhost:${bold(this.port)}`)}${green(".")}`); + if (!this.silentStartup) { + console.log(`${green("SherpaJS Server is started at")} ${cyan(`http://localhost:${bold(this.port)}`)}${green(".")}`); + } }); } diff --git a/tests/endpoints/server/routes/regular/index.ts b/tests/endpoints/server/routes/regular/index.ts index a062d3c..c556020 100644 --- a/tests/endpoints/server/routes/regular/index.ts +++ b/tests/endpoints/server/routes/regular/index.ts @@ -2,7 +2,7 @@ import { Response } from "../../../../../index.js"; export function GET(request:Request, context:unknown) { - return Response.JSON({ + return Response.JSON({ request: request, context: context, env: process.env From 4514b561e667a0102e7ae8ce815ad85b3aa744c0 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Mon, 13 May 2024 13:12:26 -0400 Subject: [PATCH 02/32] Updated Clean Command --- src/cli/index.ts | 8 ++++---- src/compiler/index.ts | 12 ++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/cli/index.ts b/src/cli/index.ts index a001a1b..0e5cf90 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -30,7 +30,7 @@ CLI.name("sherpa") CLI.command("build") - .description("Build SherpaJS Server") + .description("Creates a production build of your application.") .option("-i, --input ", "path to SherpaJS server, defaults to current directory") .option("-o, --output ", "path to server output, defaults to input directory") .option("--dev", "enable development mode, do not minify output") @@ -68,7 +68,7 @@ CLI.command("build") CLI.command("clean") - .description("Remove SherpaJS Build Directories") + .description("Removes all build directories of your application.") .option("-i, --input ", "path to SherpaJS build directories, defaults to current directory") .action((options) => { Compiler.clean(getAbsolutePath(options.input, process.cwd())); @@ -76,7 +76,7 @@ CLI.command("clean") CLI.command("start") - .description("Start SherpaJS Server Locally") + .description("Start a production build of your application. Ensure you have created a local build, with \"sherpa build\" first.") .option("-i, --input ", "path to SherpaJS build directories, defaults to current directory") .option("-p, --port ", "port number", (3000).toString()) .action((options) => { @@ -100,7 +100,7 @@ CLI.command("start") CLI.command("dev") - .description("Start SherpaJS Development Server") + .description("Start a server in development mode with hot-reload.") .option("-i, --input ", "path to SherpaJS server, defaults to current directory") .option("-o, --output ", "path to server output, defaults to input directory") .option("-v, --variable [keyvalue...]", "Specify optional environment variables as key=value pairs") diff --git a/src/compiler/index.ts b/src/compiler/index.ts index 490547c..8eb2fed 100644 --- a/src/compiler/index.ts +++ b/src/compiler/index.ts @@ -18,7 +18,6 @@ import { NewBundler, clean } from "./bundler/index.js"; import { BuildOptions, BundlerType } from "./models.js"; import { Level, Message } from "./utilities/logger/model.js"; import { Path } from "./utilities/path/index.js"; -import chokidar from "chokidar"; export { BundlerType }; @@ -66,7 +65,16 @@ export class Compiler { public static clean(filepath:string) { - clean(filepath); + [ + ".sherpa", + ".sherpa-dev", + ".vercel" + ].forEach(dirName => { + let dirPath = Path.join(filepath, dirName); + if (fs.existsSync(dirPath)) { + fs.rmSync(dirPath, { recursive: true, force: true }); + } + }) } From 061a6acc04cbff8988f34a7065038828a6176d1e Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Mon, 13 May 2024 13:12:35 -0400 Subject: [PATCH 03/32] Updated Docs --- docs/api/cli.mdx | 41 ++++++++++++++++++++++++++++++----------- docs/installation.mdx | 2 +- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/docs/api/cli.mdx b/docs/api/cli.mdx index bbfc427..da9b9f5 100644 --- a/docs/api/cli.mdx +++ b/docs/api/cli.mdx @@ -38,14 +38,15 @@ CLI for SherpaJS - Modular Microservices Framework sherpa [options] [command] ``` -#### Options: +**Options:** - `-V`, `--version` output the version number - `-h`, `--help` display help for command -#### Commands: - - `build [options]` Build SherpaJS Server - - `start [options]` Start SherpaJS Server Locally - - `clean [options]` Remove SherpaJS Build Directories +**Commands:** + - `build [options]` Creates a production build of your application + - `start [options]` Start a production build of your application + - `clean [options]` Removes all build directories of your application + - `dev [options]` Start a server in development mode with hot-reload - `help [command]` display help for command @@ -53,12 +54,12 @@ sherpa [options] [command] ### Build Command -Build SherpaJS Server. +Creates a production build of your application. ```bash sherpa build [options] ``` -#### Options: +**Options:** - `-i`, `--input ` path to SherpaJS server, defaults to current directory - `-o`, `--output ` path to server output, defaults to input directory - `-b`, `--bundler ` platform bundler ("**Vercel**", "*local**", *default: "local"*) @@ -72,12 +73,13 @@ sherpa build [options] ### Start Command -Start SherpaJS Server Locally. Ensure you have created a [local build](/api/cli#build-command). +Start a production build of your application. Ensure you have created a local +build, with [\"sherpa build\"](/api/cli#build-command) first. ```bash sherpa start [options] ``` -#### Options: +**Options:** - `-i`, `--input ` path to SherpaJS server, defaults to current directory - `-p`, `--port ` port number (default: "3000") - `-h`, `--help` display help for command @@ -87,12 +89,29 @@ sherpa start [options] ### Clean Command -Remove SherpaJS Build Directories. +Removes all build directories of your application. ```bash sherpa clean [options] ``` -#### Options: +**Options:** - `-i`, `--input ` path to SherpaJS build directories, defaults to current directory - `-h`, `--help` display help for command + +
+ + +### Dev Command +Start a server in development mode with hot-reload. +```bash +sherpa dev [options] +``` + +**Options:** + - `-i`, `--input ` path to SherpaJS server, defaults to current directory + - `-o`, `--output ` path to server output, defaults to input directory + - `-v`, `--variable [key values...]` Specify optional environment variables as key=value pairs Ex. `foo=bar test="1234 HI"` + - `-p`, `--port ` port number (default: "3000") + - `-h`, `--help` display help for command + diff --git a/docs/installation.mdx b/docs/installation.mdx index d9f0022..eeb41f6 100644 --- a/docs/installation.mdx +++ b/docs/installation.mdx @@ -53,7 +53,7 @@ the following properties. "build": "sherpa build -b Vercel", "build-local": "sherpa build -b local", "start": "sherpa start", - "dev": "npm run build-local && npm run start" + "dev": "sherpa dev" } } ``` From 572801505f10e4e607331253a70708e63e8a654e Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Tue, 14 May 2024 15:51:10 -0400 Subject: [PATCH 04/32] Added Test Bench Support --- tests/endpoints/index.test.ts | 165 +++++++++++++++++- .../regular/response/html/basic/index.ts | 2 + tests/endpoints/server/sherpa.server.ts | 10 +- tests/endpoints/suite/bench.ts | 103 +++++++++++ tests/endpoints/suite/helpers.ts | 6 + tests/endpoints/suite/index.ts | 4 +- tests/endpoints/suite/model.ts | 10 +- tests/endpoints/suite/suite.ts | 101 +++++++---- tests/endpoints/suite/tester.ts | 8 +- 9 files changed, 366 insertions(+), 43 deletions(-) create mode 100644 tests/endpoints/suite/bench.ts diff --git a/tests/endpoints/index.test.ts b/tests/endpoints/index.test.ts index bbf167a..2b7e6a4 100644 --- a/tests/endpoints/index.test.ts +++ b/tests/endpoints/index.test.ts @@ -1,18 +1,173 @@ -import { Suite, BodyType, Method, equals } from "./suite/index.js"; +import { Suite, BodyType, Method, equals, includes } from "./suite/index.js"; // NOTE: Separate from Jest Tests executed by running `npm run test-server {host}` -const suite = new Suite("http://localhost:3000"); +const suite = new Suite(); + +//! FIXME - check for args of host, if none provided then... +suite.bench("Local", { + host: "http://localhost:3000", + setup: [ + "%sherpa-cli% build" + ], + start: "%sherpa-cli% start", + teardown: [] +}); -suite.test("Example 1", { +suite.test("Basic Get - GET /regular", { method: Method.GET, path: "/regular" }).expect((response) => { - console.log(response.body); - equals(response.bodyType, BodyType.JSON); + equals(BodyType.JSON, response.bodyType); + equals("/regular", response?.body?.["request"]["url"]); + equals(Method.GET, response?.body?.["request"]["method"]); +}); + + +suite.test("Basic Post - POST /regular", { + method: Method.POST, + path: "/regular" +}).expect((response) => { + equals(BodyType.JSON, response.bodyType); + equals("/regular", response?.body?.["request"]["url"]); + equals(Method.POST, response?.body?.["request"]["method"]); +}); + + +suite.test("Basic Put - PUT /regular", { + method: Method.PUT, + path: "/regular" +}).expect((response) => { + equals(BodyType.JSON, response.bodyType); + equals("/regular", response?.body?.["request"]["url"]); + equals(Method.PUT, response?.body?.["request"]["method"]); +}); + + +suite.test("Basic Patch - PATCH /regular", { + method: Method.PATCH, + path: "/regular" +}).expect((response) => { + equals(BodyType.JSON, response.bodyType); + equals("/regular", response?.body?.["request"]["url"]); + equals(Method.PATCH, response?.body?.["request"]["method"]); +}); + + +suite.test("Basic Delete - DELETE /regular", { + method: Method.DELETE, + path: "/regular" +}).expect((response) => { + equals(BodyType.JSON, response.bodyType); + equals("/regular", response?.body?.["request"]["url"]); + equals(Method.DELETE, response?.body?.["request"]["method"]); }); +suite.test("Not Found - Regular - GET /hello-world", { + method: Method.GET, + path: "/hello-world" +}).expect((response) => { + equals(404, response.status); + equals("Not Found", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("Not Found - 1 Deep Segment - POST /regular/foo", { + method: Method.POST, + path: "/regular/foo" +}).expect((response) => { + equals(404, response.status); + equals("Not Found", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("Not Found - 3 Deep Segment - PUT /regular/response/html/foo", { + method: Method.PUT, + path: "/regular/response/html/foo" +}).expect((response) => { + equals(404, response.status); + equals("Not Found", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("Not Found - Module - DELETE /module/m1/foo", { + method: Method.DELETE, + path: "/module/m1/foo" +}).expect((response) => { + equals(404, response.status); + equals("Not Found", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("Method Not Allowed - POST /regular/response/html/standalone", { + method: Method.POST, + path: "/regular/response/html/standalone" +}).expect((response) => { + equals(405, response.status); + equals("Method Not Allowed", response.statusText); + equals(BodyType.None, response.bodyType); +}); + + +suite.test("HTML Response - Regular - GET /regular/response/html/basic", { + method: Method.GET, + path: "/regular/response/html/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.HTML, response.bodyType); + includes(response?.body as string, ""); + includes(response?.body as string, "Hello"); + includes(response?.body as string, ""); +}); + + +suite.test("HTML Response - Additional Method - POST /regular/response/html/basic", { + method: Method.POST, + path: "/regular/response/html/basic" +}).expect((response) => { + equals(201, response.status); + equals("Created", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + +suite.test("HTML Response - Standalone - GET /regular/response/html/standalone", { + method: Method.GET, + path: "/regular/response/html/standalone" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.HTML, response.bodyType); + includes(response?.body as string, ""); + includes(response?.body as string, "Hello"); + includes(response?.body as string, ""); +}); + + +// - Response types - with custom headers and status code +// - error page +// - ENVIRONMENT VARIABLES +// - SHERPA_PLATFORM +// - CONTEXT +// - context modules +// - query parameters + + (async () => { suite.run(); })(); diff --git a/tests/endpoints/server/routes/regular/response/html/basic/index.ts b/tests/endpoints/server/routes/regular/response/html/basic/index.ts index 209668e..eecf945 100644 --- a/tests/endpoints/server/routes/regular/response/html/basic/index.ts +++ b/tests/endpoints/server/routes/regular/response/html/basic/index.ts @@ -9,6 +9,8 @@ export function POST() { "object": { "numbers": [3, -4] } + }, { + status: 201 }); } diff --git a/tests/endpoints/server/sherpa.server.ts b/tests/endpoints/server/sherpa.server.ts index 458491e..9a4e74a 100644 --- a/tests/endpoints/server/sherpa.server.ts +++ b/tests/endpoints/server/sherpa.server.ts @@ -3,7 +3,15 @@ import { SherpaJS } from "../../../index"; export default SherpaJS.New.server({ - context: "foo" + context: { + foo: "bar", + exampleNum: 3, + exampleBool: true, + exampleArray: [1, 2, 3], + deeperNested: { + example: "foo" + } + } }); diff --git a/tests/endpoints/suite/bench.ts b/tests/endpoints/suite/bench.ts new file mode 100644 index 0000000..5551fa0 --- /dev/null +++ b/tests/endpoints/suite/bench.ts @@ -0,0 +1,103 @@ +// FIXME - Add Headers + Footers + +import { Path } from "../../../src/compiler/utilities/path/index.js"; +import { ChildProcess, spawn } from "child_process"; + + +export class Bench { + + + private name:string; + private host:string; + private setupCmds:string[]; + private teardownCmds:string[]; + private startCmd:string|undefined; + private server:ChildProcess; + + + constructor(name:string, host:string, start?:string, setup:string[]=[], teardown:string[]=[]) { + this.name = name; + this.host = host; + this.setupCmds = setup; + this.teardownCmds = teardown; + this.startCmd = start; + } + + + public getName():string { + return this.name; + } + + + public getHost():string { + return this.host; + } + + + public async setup() { + for (const command of this.setupCmds) { + await this.execute(command); + } + } + + + public async start() { + if (this.startCmd) { + let args = this.getArguments(this.startCmd); + this.server = spawn(args[0], args.slice(1), { cwd: this.getCWD() }); + await this.wait(1000); + } + } + + + public async teardown() { + if (this.server) { + this.server.kill(); + } + for (const command of this.teardownCmds) { + await this.execute(command); + } + } + + + private async execute(command:string):Promise { + return new Promise((resolve) => { + let args = this.getArguments(command); + let process = spawn(args[0], args.slice(1), { cwd: this.getCWD(), shell: true }); + + process.stderr.on("data", (data) => { + throw new Error(`Failed to execute command "${command}" for "${this.name}" test bench.\n${args.join(" ")}\n${data}`); + }); + + process.on("close", (code) => { + if (code === 0) { + resolve(); + } else { + throw new Error(`Failed to execute command "${command}" for "${this.name}" test bench.\n${args.join(" ")}\ncode: ${code}`); + } + }); + }); + } + + + private getCWD():string { + return Path.join(Path.getDirectory(import.meta.url), "../../../../tests/endpoints/server"); + } + + + private getArguments(command:string):string[] { + return command.replace(/^\%sherpa-cli\%/, "node ../../../dist/src/cli/index.js").split(" "); + } + + + private async wait(ms:number):Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, ms); + }); + } + + +} + diff --git a/tests/endpoints/suite/helpers.ts b/tests/endpoints/suite/helpers.ts index 26081d3..65c4daf 100644 --- a/tests/endpoints/suite/helpers.ts +++ b/tests/endpoints/suite/helpers.ts @@ -14,3 +14,9 @@ export function equals(expect:unknown, actual:unknown) { } +export function includes(buffer:string, searchString:string) { + if (!buffer.includes(searchString)) { + throw new Fail(`Expected "${buffer.slice(0, 10)}..." to include "${searchString}"`); + } +} + diff --git a/tests/endpoints/suite/index.ts b/tests/endpoints/suite/index.ts index 26fc99c..1f90e24 100644 --- a/tests/endpoints/suite/index.ts +++ b/tests/endpoints/suite/index.ts @@ -3,9 +3,9 @@ import { Suite } from "./suite.js"; import { Method, BodyType, Body } from "../../../index.js"; -import { equals } from "./helpers.js"; +import { equals, includes } from "./helpers.js"; export type { Body }; -export { Suite, equals, Method, BodyType }; +export { Suite, equals, includes, Method, BodyType }; diff --git a/tests/endpoints/suite/model.ts b/tests/endpoints/suite/model.ts index 9e3f54a..39c4136 100644 --- a/tests/endpoints/suite/model.ts +++ b/tests/endpoints/suite/model.ts @@ -3,13 +3,21 @@ import { Method, Body } from "../../../index.js"; -export type Options = { +export type TestOptions = { method:Method, path:string, body?:Body } +export type BenchOptions = { + host:string; + start?:string; + setup?:string[]; + teardown?:string[]; +} + + export type TestResults = { name:string, success:boolean, diff --git a/tests/endpoints/suite/suite.ts b/tests/endpoints/suite/suite.ts index 3f4488b..53f10a2 100644 --- a/tests/endpoints/suite/suite.ts +++ b/tests/endpoints/suite/suite.ts @@ -1,28 +1,24 @@ // FIXME - Add Headers + Footers import { Tester } from "./tester.js"; -import { Options, TestResults } from "./model.js"; +import { BenchOptions, TestOptions, TestResults } from "./model.js"; import { bold, green, red, gray } from "colorette"; +import { Bench } from "./bench.js"; export class Suite { - private host:string; private tests:Tester[] = []; - private results:TestResults[] = []; + private benches:Bench[] = []; + private results:{ [name:string]:TestResults[] } = {}; - constructor(host:string) { - this.host = host; - } - - - test(name:string, options:Options):Tester { + test(name:string, options:TestOptions):Tester { let test = new Tester( name, options.method, - new URL(options.path, this.host).toString(), + options.path, options.body ); this.tests.push(test); @@ -30,37 +26,82 @@ export class Suite { } + bench(name:string, options:BenchOptions):Bench { + let bench = new Bench( + name, + options.host, + options.start, + options.setup || [], + options.teardown || [] + ); + this.benches.push(bench); + return bench; + } + + async run() { - for (let test of this.tests) { - this.results.push(await test.invoke()); - } + + await Promise.all(this.benches.map(async (bench) => { + if (this.results[bench.getName()]) { + throw new Error(`Test bench name duplicate: "${bench.getName()}"`); + } + this.results[bench.getName()] = []; + + await bench.setup(); + await bench.start(); + await Promise.all(this.tests.map(async (test) => { + this.results[bench.getName()].push(await test.invoke(bench.getHost())); + })); + await bench.teardown(); + })); + this.display(); } private display() { - let passed = this.results.filter((result) => result.success).length; - let failed = this.results.filter((result) => !result.success).length; - let total = this.results.length; - - for (let test of this.results) { - if (test.success) { - console.log(`${green("√")} ${gray(test.name)}`); - } else { - console.log(`${red("×")} ${gray(test.name)}`); - if (test.message) { - console.log(` ${red(test.message)}\n`); - } - if (test.stack) { - for (let line of test.stack.split("\n")) { - console.log(` ${gray(line)}`); + for (let bench of this.benches) { + let _passed = this.results[bench.getName()].filter((result) => result.success).length; + let _failed = this.results[bench.getName()].filter((result) => !result.success).length; + let _total = this.results[bench.getName()].length; + + console.log("\n============ " + bold(bench.getName()) + " ============="); + + for (let test of this.results[bench.getName()]) { + if (test.success) { + console.log(`${green("√")} ${gray(test.name)}`); + } else { + console.log(`${red("×")} ${gray(test.name)}`); + if (test.message) { + console.log(` ${red(test.message)}\n`); } + if (test.stack) { + for (let line of test.stack.split("\n")) { + console.log(` ${gray(line)}`); + } + } + console.log(""); } - console.log(""); } + + console.log(`${bold("Tests:")} ${green(`${_passed} passed,`)} ${red(`${_failed} failed,`)} total ${_total}`); } - console.log(`${bold("Tests:")} ${green(`${passed} passed,`)} ${red(`${failed} failed,`)} total ${total}`); + let passed = 0; + let failed = 0; + let total = 0; + + console.log("\n============ " + bold("Overview") + " ============="); + for (let bench of this.benches) { + let _passed = this.results[bench.getName()].filter((result) => result.success).length; + let _failed = this.results[bench.getName()].filter((result) => !result.success).length; + let _total = this.results[bench.getName()].length; + passed += _passed; + failed += _failed; + total += _total; + console.log(`${bold(`${bench.getName()}:`)} ${green(`${_passed} passed,`)} ${red(`${_failed} failed,`)} total ${_total}`); + } + console.log(`${bold("All Tests:")} ${green(`${passed} passed,`)} ${red(`${failed} failed,`)} total ${total}`); } diff --git a/tests/endpoints/suite/tester.ts b/tests/endpoints/suite/tester.ts index 7917d44..2537ab7 100644 --- a/tests/endpoints/suite/tester.ts +++ b/tests/endpoints/suite/tester.ts @@ -32,9 +32,9 @@ export class Tester { } - async invoke():Promise { + async invoke(host:string):Promise { try { - this.handler!(await this.getResponse()); + this.handler!(await this.getResponse(host)); return { name: this.name, success: true }; } catch (error) { let stack = new StackTracey(error.stack).items.map((e) => e.beforeParse).join("\n"); @@ -56,9 +56,9 @@ export class Tester { } - private async getResponse():Promise { + private async getResponse(host:string):Promise { let { body, contentType } = this.getRequestBody(this.body); - return await this.cast(await fetch(this.url, { + return await this.cast(await fetch(new URL(this.url, host).toString(), { method: this.method, body: body, headers: { From 1d7fc214afe09b85e51658b32b6fee6fcab6f99a Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Tue, 14 May 2024 20:53:20 -0400 Subject: [PATCH 05/32] Added Endpoint Tests --- package.json | 5 +- src/native/response/index.ts | 13 +- tests/endpoints/index.test.ts | 298 +++++++++++++++++- .../regular/response/html/basic/index.ts | 42 +++ .../regular/response/json/basic/index.ts | 48 +++ .../regular/response/none/basic/index.ts | 20 ++ .../regular/response/redirect/basic/index.ts | 20 ++ .../response/redirect/success/index.ts | 24 ++ .../regular/response/text/basic/index.ts | 21 ++ tests/endpoints/suite/suite.ts | 9 +- tests/endpoints/suite/tester.ts | 6 +- 11 files changed, 486 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index f1e0874..9b54929 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,9 @@ "prepare": "npm run build", "build": "tsc --build --force ./toolchain/tsconfig.json", "lint": "eslint . --ext .ts -c ./toolchain/.eslintrc.cjs", - "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js -c ./toolchain/jest.config.ts", - "test-server": "node ./dist/tests/endpoints/index.test.js" + "test": "npm run test-unit && npm run test-endpoints", + "test-unit": "node --experimental-vm-modules node_modules/jest/bin/jest.js -c ./toolchain/jest.config.ts", + "test-endpoints": "npm run build && node ./dist/tests/endpoints/index.test.js" }, "devDependencies": { "@types/checksum": "^0.1.35", diff --git a/src/native/response/index.ts b/src/native/response/index.ts index d370451..c335d62 100644 --- a/src/native/response/index.ts +++ b/src/native/response/index.ts @@ -23,12 +23,6 @@ export interface Options { } -const DEFAULT_OPTIONS:Options = { - headers:new Headers(), - status:200, -} - - export class ResponseBuilder { @@ -81,8 +75,8 @@ export class ResponseBuilder { } - static redirect(redirect:string, options?:Partial):IResponse { - let _options = ResponseBuilder.defaultOptions(BodyType.None, options); + static redirect(redirect:string):IResponse { + let _options = ResponseBuilder.defaultOptions(BodyType.None, {}); if (!_options.headers.has("Location")) { _options.headers.set("Location", redirect); } @@ -98,7 +92,8 @@ export class ResponseBuilder { private static defaultOptions(bodyType:BodyType, options?:Partial):Options { let _options:Options = { - ...DEFAULT_OPTIONS, + status: 200, + headers: new Headers(), ...options }; if (!_options.headers.has("Content-Type")) { diff --git a/tests/endpoints/index.test.ts b/tests/endpoints/index.test.ts index 2b7e6a4..692f99a 100644 --- a/tests/endpoints/index.test.ts +++ b/tests/endpoints/index.test.ts @@ -13,6 +13,10 @@ suite.bench("Local", { teardown: [] }); +// suite.bench("Vercel", { +// host: "https://sherpajs-test.vercel.app/" +// }); + suite.test("Basic Get - GET /regular", { method: Method.GET, @@ -146,6 +150,51 @@ suite.test("HTML Response - Additional Method - POST /regular/response/html/basi }); +suite.test("HTML Response - Additional Method - PUT /regular/response/html/basic", { + method: Method.PUT, + path: "/regular/response/html/basic" +}).expect((response) => { + equals(201, response.status); + equals("Created", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + +suite.test("HTML Response - Additional Method - PATCH /regular/response/html/basic", { + method: Method.PATCH, + path: "/regular/response/html/basic" +}).expect((response) => { + equals(201, response.status); + equals("Created", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + +suite.test("HTML Response - Additional Method - DELETE /regular/response/html/basic", { + method: Method.DELETE, + path: "/regular/response/html/basic" +}).expect((response) => { + equals(201, response.status); + equals("Created", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + suite.test("HTML Response - Standalone - GET /regular/response/html/standalone", { method: Method.GET, path: "/regular/response/html/standalone" @@ -159,7 +208,254 @@ suite.test("HTML Response - Standalone - GET /regular/response/html/standalone", }); -// - Response types - with custom headers and status code +suite.test("JSON Response - GET /regular/response/json/basic", { + method: Method.GET, + path: "/regular/response/json/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + +suite.test("JSON Response - POST /regular/response/json/basic", { + method: Method.POST, + path: "/regular/response/json/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + +suite.test("JSON Response - PUT /regular/response/json/basic", { + method: Method.PUT, + path: "/regular/response/json/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + +suite.test("JSON Response - PATCH /regular/response/json/basic", { + method: Method.PATCH, + path: "/regular/response/json/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + +suite.test("JSON Response - DELETE /regular/response/json/basic", { + method: Method.DELETE, + path: "/regular/response/json/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("food", response?.body?.["string"]); + equals(3, response?.body?.["number"]); + equals(true, response?.body?.["boolean"]); + equals(3, response?.body?.["object"]["numbers"][0]); + equals(-4, response?.body?.["object"]["numbers"][1]); +}); + + +suite.test("None Response - GET /regular/response/none/basic", { + method: Method.GET, + path: "/regular/response/none/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("None Response - POST /regular/response/none/basic", { + method: Method.POST, + path: "/regular/response/none/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("None Response - PUT /regular/response/none/basic", { + method: Method.PUT, + path: "/regular/response/none/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("None Response - PATCH /regular/response/none/basic", { + method: Method.PATCH, + path: "/regular/response/none/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("None Response - DELETE /regular/response/none/basic", { + method: Method.DELETE, + path: "/regular/response/none/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("Text Response - GET /regular/response/text/basic", { + method: Method.GET, + path: "/regular/response/text/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.Text, response.bodyType); + equals("Hello World", response?.body); +}); + + +suite.test("Text Response - POST /regular/response/text/basic", { + method: Method.POST, + path: "/regular/response/text/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.Text, response.bodyType); + equals("Hello World", response?.body); +}); + + +suite.test("Text Response - PUT /regular/response/text/basic", { + method: Method.PUT, + path: "/regular/response/text/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.Text, response.bodyType); + equals("Hello World", response?.body); +}); + + +suite.test("Text Response - PATCH /regular/response/text/basic", { + method: Method.PATCH, + path: "/regular/response/text/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.Text, response.bodyType); + equals("Hello World", response?.body); +}); + + +suite.test("Text Response - DELETE /regular/response/text/basic", { + method: Method.DELETE, + path: "/regular/response/text/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.Text, response.bodyType); + equals("Hello World", response?.body); +}); + + +suite.test("Redirect Response - GET /regular/response/redirect/basic", { + method: Method.GET, + path: "/regular/response/redirect/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/regular/response/redirect/success", response?.body?.["request"]["url"]); + equals(Method.GET, response?.body?.["request"]["method"]); +}); + + +suite.test("Redirect Response - POST /regular/response/redirect/basic", { + method: Method.GET, + path: "/regular/response/redirect/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/regular/response/redirect/success", response?.body?.["request"]["url"]); + equals(Method.GET, response?.body?.["request"]["method"]); +}); + + +suite.test("Redirect Response - PUT /regular/response/redirect/basic", { + method: Method.PUT, + path: "/regular/response/redirect/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/regular/response/redirect/success", response?.body?.["request"]["url"]); + equals(Method.PUT, response?.body?.["request"]["method"]); +}); + + +suite.test("Redirect Response - PATCH /regular/response/redirect/basic", { + method: Method.PATCH, + path: "/regular/response/redirect/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/regular/response/redirect/success", response?.body?.["request"]["url"]); + equals(Method.PATCH, response?.body?.["request"]["method"]); +}); + + +suite.test("Redirect Response - DELETE /regular/response/redirect/basic", { + method: Method.DELETE, + path: "/regular/response/redirect/basic" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/regular/response/redirect/success", response?.body?.["request"]["url"]); + equals(Method.DELETE, response?.body?.["request"]["method"]); +}); + + +// - Response types - with custom headers and status code - defining headers different ways +// - status codes - every single one - make endpoint that uses dynamic paths +// - test body // - error page // - ENVIRONMENT VARIABLES // - SHERPA_PLATFORM diff --git a/tests/endpoints/server/routes/regular/response/html/basic/index.ts b/tests/endpoints/server/routes/regular/response/html/basic/index.ts index eecf945..a97712d 100644 --- a/tests/endpoints/server/routes/regular/response/html/basic/index.ts +++ b/tests/endpoints/server/routes/regular/response/html/basic/index.ts @@ -14,3 +14,45 @@ export function POST() { }); } + +export function PUT() { + return Response.JSON({ + "string": "food", + "number": 3, + "boolean": true, + "object": { + "numbers": [3, -4] + } + }, { + status: 201 + }); +} + + +export function PATCH() { + return Response.JSON({ + "string": "food", + "number": 3, + "boolean": true, + "object": { + "numbers": [3, -4] + } + }, { + status: 201 + }); +} + + +export function DELETE() { + return Response.JSON({ + "string": "food", + "number": 3, + "boolean": true, + "object": { + "numbers": [3, -4] + } + }, { + status: 201 + }); +} + diff --git a/tests/endpoints/server/routes/regular/response/json/basic/index.ts b/tests/endpoints/server/routes/regular/response/json/basic/index.ts index 51d5d46..d4885c1 100644 --- a/tests/endpoints/server/routes/regular/response/json/basic/index.ts +++ b/tests/endpoints/server/routes/regular/response/json/basic/index.ts @@ -12,3 +12,51 @@ export function GET() { }); } + +export function POST() { + return Response.JSON({ + "string": "food", + "number": 3, + "boolean": true, + "object": { + "numbers": [3, -4] + } + }); +} + + +export function PUT() { + return Response.JSON({ + "string": "food", + "number": 3, + "boolean": true, + "object": { + "numbers": [3, -4] + } + }); +} + + +export function PATCH() { + return Response.JSON({ + "string": "food", + "number": 3, + "boolean": true, + "object": { + "numbers": [3, -4] + } + }); +} + + +export function DELETE() { + return Response.JSON({ + "string": "food", + "number": 3, + "boolean": true, + "object": { + "numbers": [3, -4] + } + }); +} + diff --git a/tests/endpoints/server/routes/regular/response/none/basic/index.ts b/tests/endpoints/server/routes/regular/response/none/basic/index.ts index 960bbd6..67431a8 100644 --- a/tests/endpoints/server/routes/regular/response/none/basic/index.ts +++ b/tests/endpoints/server/routes/regular/response/none/basic/index.ts @@ -5,3 +5,23 @@ export function GET() { return Response.new(); } + +export function POST() { + return Response.new(); +} + + +export function PUT() { + return Response.new(); +} + + +export function PATCH() { + return Response.new(); +} + + +export function DELETE() { + return Response.new(); +} + diff --git a/tests/endpoints/server/routes/regular/response/redirect/basic/index.ts b/tests/endpoints/server/routes/regular/response/redirect/basic/index.ts index c81218b..fa9490f 100644 --- a/tests/endpoints/server/routes/regular/response/redirect/basic/index.ts +++ b/tests/endpoints/server/routes/regular/response/redirect/basic/index.ts @@ -5,3 +5,23 @@ export function GET() { return Response.redirect("../success"); } + +export function POST() { + return Response.redirect("../success"); +} + + +export function PUT() { + return Response.redirect("../success"); +} + + +export function PATCH() { + return Response.redirect("../success"); +} + + +export function DELETE() { + return Response.redirect("../success"); +} + diff --git a/tests/endpoints/server/routes/regular/response/redirect/success/index.ts b/tests/endpoints/server/routes/regular/response/redirect/success/index.ts index e4f808d..ed8d016 100644 --- a/tests/endpoints/server/routes/regular/response/redirect/success/index.ts +++ b/tests/endpoints/server/routes/regular/response/redirect/success/index.ts @@ -8,3 +8,27 @@ export function GET(request:Request, context:unknown) { }); } + +export function PUT(request:Request, context:unknown) { + return Response.JSON({ + request, + context + }); +} + + +export function PATCH(request:Request, context:unknown) { + return Response.JSON({ + request, + context + }); +} + + +export function DELETE(request:Request, context:unknown) { + return Response.JSON({ + request, + context + }); +} + diff --git a/tests/endpoints/server/routes/regular/response/text/basic/index.ts b/tests/endpoints/server/routes/regular/response/text/basic/index.ts index a7d2f34..1ec0a47 100644 --- a/tests/endpoints/server/routes/regular/response/text/basic/index.ts +++ b/tests/endpoints/server/routes/regular/response/text/basic/index.ts @@ -5,3 +5,24 @@ export function GET() { return Response.text("Hello World"); } + +export function POST() { + return Response.text("Hello World"); +} + + + +export function PUT() { + return Response.text("Hello World"); +} + + +export function PATCH() { + return Response.text("Hello World"); +} + + +export function DELETE() { + return Response.text("Hello World"); +} + diff --git a/tests/endpoints/suite/suite.ts b/tests/endpoints/suite/suite.ts index 53f10a2..4c8edab 100644 --- a/tests/endpoints/suite/suite.ts +++ b/tests/endpoints/suite/suite.ts @@ -40,8 +40,7 @@ export class Suite { async run() { - - await Promise.all(this.benches.map(async (bench) => { + for await (const bench of this.benches) { if (this.results[bench.getName()]) { throw new Error(`Test bench name duplicate: "${bench.getName()}"`); } @@ -49,11 +48,11 @@ export class Suite { await bench.setup(); await bench.start(); - await Promise.all(this.tests.map(async (test) => { + for await (const test of this.tests) { this.results[bench.getName()].push(await test.invoke(bench.getHost())); - })); + } await bench.teardown(); - })); + } this.display(); } diff --git a/tests/endpoints/suite/tester.ts b/tests/endpoints/suite/tester.ts index 2537ab7..0fbf368 100644 --- a/tests/endpoints/suite/tester.ts +++ b/tests/endpoints/suite/tester.ts @@ -107,17 +107,17 @@ export class Tester { body: undefined, bodyType: BodyType.None }; - } else if (contentType == "application/json") { + } else if (contentType.startsWith("application/json")) { return { body: JSON.parse(body as string), bodyType: BodyType.JSON }; - } else if (contentType == "text/html") { + } else if (contentType.startsWith("text/html")) { return { body: body, bodyType: BodyType.HTML }; - } else if (contentType == "text/plain") { + } else if (contentType.startsWith("text/plain")) { return { body: body, bodyType: BodyType.Text From 2a5a48a5bbf9f5f559e2a03b7225fe4d6ad896c5 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Tue, 14 May 2024 20:56:31 -0400 Subject: [PATCH 06/32] Updated Linting Issues --- src/compiler/index.ts | 3 ++- src/server-development/index.ts | 2 +- tests/endpoints/suite/bench.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/index.ts b/src/compiler/index.ts index 8eb2fed..4bc1e03 100644 --- a/src/compiler/index.ts +++ b/src/compiler/index.ts @@ -10,11 +10,12 @@ * */ + import fs from "fs"; import { green, red } from "colorette"; import { getStructure } from "./structure/index.js"; import { Logger } from "./utilities/logger/index.js"; -import { NewBundler, clean } from "./bundler/index.js"; +import { NewBundler } from "./bundler/index.js"; import { BuildOptions, BundlerType } from "./models.js"; import { Level, Message } from "./utilities/logger/model.js"; import { Path } from "./utilities/path/index.js"; diff --git a/src/server-development/index.ts b/src/server-development/index.ts index 9421d52..2de1c8c 100644 --- a/src/server-development/index.ts +++ b/src/server-development/index.ts @@ -42,7 +42,7 @@ export class ServerDevelopment { this.refresh(); chokidar.watch(this.options.input, { persistent: true, - ignored: /(^|[\/\\])\../, // note: . files are ignored + ignored: /(^|[/\\])\../, // note: . files are ignored }).on("change", (path, stats) => { if (path && stats) { this.refresh(); diff --git a/tests/endpoints/suite/bench.ts b/tests/endpoints/suite/bench.ts index 5551fa0..57c173c 100644 --- a/tests/endpoints/suite/bench.ts +++ b/tests/endpoints/suite/bench.ts @@ -86,7 +86,7 @@ export class Bench { private getArguments(command:string):string[] { - return command.replace(/^\%sherpa-cli\%/, "node ../../../dist/src/cli/index.js").split(" "); + return command.replace(/^%sherpa-cli%/, "node ../../../dist/src/cli/index.js").split(" "); } From ed080de0e83de59740a2e12f0b7fbfe34fa52c97 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Tue, 14 May 2024 20:59:31 -0400 Subject: [PATCH 07/32] Updated Workflow --- .github/workflows/testing.yml | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 6671f9a..cfdc576 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -27,8 +27,26 @@ jobs: - name: Install dependencies run: npm install - - name: Run Tests - run: npm test + - name: Run Unit Tests + run: npm run test-unit + + endpoint-test: + name: Endpoint Tests + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + run: npm install + + - name: Run Endpoint Tests + run: npm run test-endpoints linting: name: Linting From 01689c3c24d2d210c15f92e1ce2b5a4bec6f5b4f Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Tue, 14 May 2024 21:00:44 -0400 Subject: [PATCH 08/32] Update index.test.ts --- tests/endpoints/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/endpoints/index.test.ts b/tests/endpoints/index.test.ts index 692f99a..c2bb320 100644 --- a/tests/endpoints/index.test.ts +++ b/tests/endpoints/index.test.ts @@ -23,7 +23,7 @@ suite.test("Basic Get - GET /regular", { path: "/regular" }).expect((response) => { equals(BodyType.JSON, response.bodyType); - equals("/regular", response?.body?.["request"]["url"]); + equals("/regular/foo", response?.body?.["request"]["url"]); //! FIXME equals(Method.GET, response?.body?.["request"]["method"]); }); From 8d64865806ac853066475cac34defde5b7105998 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Tue, 14 May 2024 21:02:47 -0400 Subject: [PATCH 09/32] Update suite.ts --- tests/endpoints/suite/suite.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/endpoints/suite/suite.ts b/tests/endpoints/suite/suite.ts index 4c8edab..8ce9e68 100644 --- a/tests/endpoints/suite/suite.ts +++ b/tests/endpoints/suite/suite.ts @@ -101,6 +101,9 @@ export class Suite { console.log(`${bold(`${bench.getName()}:`)} ${green(`${_passed} passed,`)} ${red(`${_failed} failed,`)} total ${_total}`); } console.log(`${bold("All Tests:")} ${green(`${passed} passed,`)} ${red(`${failed} failed,`)} total ${total}`); + if (failed > 0) { + process.exit(1); + } } From 3361fc8a10b62247714f059a45ed9a61ac58b05e Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Tue, 14 May 2024 21:04:19 -0400 Subject: [PATCH 10/32] Update index.test.ts --- tests/endpoints/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/endpoints/index.test.ts b/tests/endpoints/index.test.ts index c2bb320..692f99a 100644 --- a/tests/endpoints/index.test.ts +++ b/tests/endpoints/index.test.ts @@ -23,7 +23,7 @@ suite.test("Basic Get - GET /regular", { path: "/regular" }).expect((response) => { equals(BodyType.JSON, response.bodyType); - equals("/regular/foo", response?.body?.["request"]["url"]); //! FIXME + equals("/regular", response?.body?.["request"]["url"]); equals(Method.GET, response?.body?.["request"]["method"]); }); From b142d5682d151aa2524fe18b56b55595d2cbcbd9 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Wed, 15 May 2024 09:09:00 -0400 Subject: [PATCH 11/32] Added Additional Tests --- src/native/response/index.ts | 13 +- tests/endpoints/index.test.ts | 188 +++++++++++++++++- .../regular/response/json/custom/index.ts | 58 ++++++ .../regular/response/none/custom/index.ts | 48 +++++ .../regular/response/text/custom/index.ts | 48 +++++ 5 files changed, 345 insertions(+), 10 deletions(-) create mode 100644 tests/endpoints/server/routes/regular/response/json/custom/index.ts create mode 100644 tests/endpoints/server/routes/regular/response/none/custom/index.ts create mode 100644 tests/endpoints/server/routes/regular/response/text/custom/index.ts diff --git a/src/native/response/index.ts b/src/native/response/index.ts index c335d62..29f556d 100644 --- a/src/native/response/index.ts +++ b/src/native/response/index.ts @@ -11,14 +11,14 @@ */ -import { Headers } from "../headers/index.js"; +import { Headers, HeadersInit } from "../headers/index.js"; import { BodyType, CONTENT_TYPE } from "../model.js"; import { IResponse } from "./interface.js"; import { STATUS_TEXT } from "./status-text.js"; export interface Options { - headers:Headers; + headers:HeadersInit; status:number; } @@ -90,11 +90,10 @@ export class ResponseBuilder { } - private static defaultOptions(bodyType:BodyType, options?:Partial):Options { - let _options:Options = { - status: 200, - headers: new Headers(), - ...options + private static defaultOptions(bodyType:BodyType, options?:Partial):{ status:number, headers:Headers } { + let _options = { + status: options?.status || 200, + headers: new Headers(options?.headers || {}) }; if (!_options.headers.has("Content-Type")) { _options.headers.set("Content-Type", CONTENT_TYPE[bodyType] as string); diff --git a/tests/endpoints/index.test.ts b/tests/endpoints/index.test.ts index 692f99a..a14cb87 100644 --- a/tests/endpoints/index.test.ts +++ b/tests/endpoints/index.test.ts @@ -283,6 +283,66 @@ suite.test("JSON Response - DELETE /regular/response/json/basic", { }); +suite.test("JSON Response - Custom Status + Headers - GET /regular/response/json/custom", { + method: Method.GET, + path: "/regular/response/json/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.JSON, response.bodyType); + equals("bar", response?.body?.["foo"]); +}); + + +suite.test("JSON Response - Custom Status + Headers - POST /regular/response/json/custom", { + method: Method.POST, + path: "/regular/response/json/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.JSON, response.bodyType); + equals("bar", response?.body?.["foo"]); +}); + + +suite.test("JSON Response - Custom Status + Headers - PUT /regular/response/json/custom", { + method: Method.PUT, + path: "/regular/response/json/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.JSON, response.bodyType); + equals("bar", response?.body?.["foo"]); +}); + + +suite.test("JSON Response - Custom Status + Headers - PATCH /regular/response/json/custom", { + method: Method.PATCH, + path: "/regular/response/json/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.JSON, response.bodyType); + equals("bar", response?.body?.["foo"]); +}); + + +suite.test("JSON Response - Custom Status + Headers - DELETE /regular/response/json/custom", { + method: Method.DELETE, + path: "/regular/response/json/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.JSON, response.bodyType); + equals("bar", response?.body?.["foo"]); +}); + + suite.test("None Response - GET /regular/response/none/basic", { method: Method.GET, path: "/regular/response/none/basic" @@ -338,6 +398,66 @@ suite.test("None Response - DELETE /regular/response/none/basic", { }); +suite.test("None Response - Custom Status + Headers - GET /regular/response/none/custom", { + method: Method.GET, + path: "/regular/response/none/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("None Response - Custom Status + Headers - POST /regular/response/none/custom", { + method: Method.POST, + path: "/regular/response/none/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("None Response - Custom Status + Headers - PUT /regular/response/none/custom", { + method: Method.PUT, + path: "/regular/response/none/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("None Response - Custom Status + Headers - PATCH /regular/response/none/custom", { + method: Method.PATCH, + path: "/regular/response/none/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + +suite.test("None Response - Custom Status + Headers - DELETE /regular/response/none/custom", { + method: Method.DELETE, + path: "/regular/response/none/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.None, response.bodyType); + equals(undefined, response?.body); +}); + + suite.test("Text Response - GET /regular/response/text/basic", { method: Method.GET, path: "/regular/response/text/basic" @@ -393,6 +513,66 @@ suite.test("Text Response - DELETE /regular/response/text/basic", { }); +suite.test("Text Response - Custom Status + Headers - GET /regular/response/text/custom", { + method: Method.GET, + path: "/regular/response/text/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.Text, response.bodyType); + equals("foo-bar", response?.body); +}); + + +suite.test("Text Response - Custom Status + Headers - POST /regular/response/text/custom", { + method: Method.POST, + path: "/regular/response/text/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.Text, response.bodyType); + equals("foo-bar", response?.body); +}); + + +suite.test("Text Response - Custom Status + Headers - PUT /regular/response/text/custom", { + method: Method.PUT, + path: "/regular/response/text/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.Text, response.bodyType); + equals("foo-bar", response?.body); +}); + + +suite.test("Text Response - Custom Status + Headers - PATCH /regular/response/text/custom", { + method: Method.PATCH, + path: "/regular/response/text/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.Text, response.bodyType); + equals("foo-bar", response?.body); +}); + + +suite.test("Text Response - Custom Status + Headers - DELETE /regular/response/text/custom", { + method: Method.DELETE, + path: "/regular/response/text/custom" +}).expect((response) => { + equals(401, response.status); + equals("Unauthorized", response.statusText); + equals("bar", response.headers.get("X-Foo")); + equals(BodyType.Text, response.bodyType); + equals("foo-bar", response?.body); +}); + + suite.test("Redirect Response - GET /regular/response/redirect/basic", { method: Method.GET, path: "/regular/response/redirect/basic" @@ -453,15 +633,17 @@ suite.test("Redirect Response - DELETE /regular/response/redirect/basic", { }); -// - Response types - with custom headers and status code - defining headers different ways + // - status codes - every single one - make endpoint that uses dynamic paths -// - test body +// - status code that doesn't exists +// - query parameters +// - dynamic path +// - static files // - error page // - ENVIRONMENT VARIABLES // - SHERPA_PLATFORM // - CONTEXT // - context modules -// - query parameters (async () => { diff --git a/tests/endpoints/server/routes/regular/response/json/custom/index.ts b/tests/endpoints/server/routes/regular/response/json/custom/index.ts new file mode 100644 index 0000000..12bb721 --- /dev/null +++ b/tests/endpoints/server/routes/regular/response/json/custom/index.ts @@ -0,0 +1,58 @@ +import { Response, Headers as SherpaHeaders } from "../../../../../../../../index.js"; + + +export function GET() { + return Response.JSON({ + "foo": "bar" + }, { + status: 401, + headers: { + "X-Foo": "bar" + } + }); +} + + +export function POST() { + return Response.JSON({ + "foo": "bar" + }, { + status: 401, + headers: new Headers({ + "X-Foo": "bar" + }) + }); +} + + +export function PUT() { + return Response.JSON({ + "foo": "bar" + }, { + status: 401, + headers: new SherpaHeaders({ + "X-Foo": "bar" + }) + }); +} + + +export function PATCH() { + return Response.JSON({ + "foo": "bar" + }, { + status: 401, + headers: [["X-Foo", "bar"]] + }); +} + + +export function DELETE() { + return Response.JSON({ + "foo": "bar" + }, { + status: 401, + headers: new SherpaHeaders([["X-Foo", "bar"]]) + }); +} + diff --git a/tests/endpoints/server/routes/regular/response/none/custom/index.ts b/tests/endpoints/server/routes/regular/response/none/custom/index.ts new file mode 100644 index 0000000..f13afcf --- /dev/null +++ b/tests/endpoints/server/routes/regular/response/none/custom/index.ts @@ -0,0 +1,48 @@ +import { Response, Headers as SherpaHeaders } from "../../../../../../../../index.js"; + + +export function GET() { + return Response.new({ + status: 401, + headers: { + "X-Foo": "bar" + } + }); +} + + +export function POST() { + return Response.new({ + status: 401, + headers: new Headers({ + "X-Foo": "bar" + }) + }); +} + + +export function PUT() { + return Response.new({ + status: 401, + headers: new SherpaHeaders({ + "X-Foo": "bar" + }) + }); +} + + +export function PATCH() { + return Response.new({ + status: 401, + headers: [["X-Foo", "bar"]] + }); +} + + +export function DELETE() { + return Response.new({ + status: 401, + headers: new SherpaHeaders([["X-Foo", "bar"]]) + }); +} + diff --git a/tests/endpoints/server/routes/regular/response/text/custom/index.ts b/tests/endpoints/server/routes/regular/response/text/custom/index.ts new file mode 100644 index 0000000..75d18a8 --- /dev/null +++ b/tests/endpoints/server/routes/regular/response/text/custom/index.ts @@ -0,0 +1,48 @@ +import { Response, Headers as SherpaHeaders } from "../../../../../../../../index.js"; + + +export function GET() { + return Response.text("foo-bar", { + status: 401, + headers: { + "X-Foo": "bar" + } + }); +} + + +export function POST() { + return Response.text("foo-bar", { + status: 401, + headers: new Headers({ + "X-Foo": "bar" + }) + }); +} + + +export function PUT() { + return Response.text("foo-bar", { + status: 401, + headers: new SherpaHeaders({ + "X-Foo": "bar" + }) + }); +} + + +export function PATCH() { + return Response.text("foo-bar", { + status: 401, + headers: [["X-Foo", "bar"]] + }); +} + + +export function DELETE() { + return Response.text("foo-bar", { + status: 401, + headers: new SherpaHeaders([["X-Foo", "bar"]]) + }); +} + From 6ff32112fcabcae3632a11c0a0aa7bb8c0d8e1d5 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 11:14:06 -0400 Subject: [PATCH 12/32] Updated Tests --- tests/endpoints/index.test.ts | 85 ++++++++++++++++++- .../modules/pass-primary-1/routes/index.ts | 31 +++++++ .../pass-primary-1/routes/test/index.ts | 7 ++ tests/endpoints/suite/bench.ts | 17 +++- tests/endpoints/suite/helpers.ts | 17 +++- tests/endpoints/suite/index.ts | 16 +++- tests/endpoints/suite/model.ts | 16 +++- tests/endpoints/suite/suite.ts | 18 +++- tests/endpoints/suite/tester.ts | 17 +++- 9 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 tests/endpoints/modules/pass-primary-1/routes/test/index.ts diff --git a/tests/endpoints/index.test.ts b/tests/endpoints/index.test.ts index a14cb87..f58d696 100644 --- a/tests/endpoints/index.test.ts +++ b/tests/endpoints/index.test.ts @@ -633,11 +633,94 @@ suite.test("Redirect Response - DELETE /regular/response/redirect/basic", { }); +suite.test("Module Response Get - GET /module/m1", { + method: Method.GET, + path: "/module/m1" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/module/m1", response?.body?.["request"]["url"]); + equals(Method.GET, response?.body?.["request"]["method"]); +}); + + +suite.test("Module Response Post - POST /module/m1", { + method: Method.POST, + path: "/module/m1" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/module/m1", response?.body?.["request"]["url"]); + equals(Method.POST, response?.body?.["request"]["method"]); +}); + + +suite.test("Module Response Put - PUT /module/m1", { + method: Method.PUT, + path: "/module/m1" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/module/m1", response?.body?.["request"]["url"]); + equals(Method.PUT, response?.body?.["request"]["method"]); +}); + + +suite.test("Module Response Patch - PATCH /module/m1", { + method: Method.PATCH, + path: "/module/m1" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/module/m1", response?.body?.["request"]["url"]); + equals(Method.PATCH, response?.body?.["request"]["method"]); +}); + + +suite.test("Module Response Delete - DELETE /module/m1", { + method: Method.DELETE, + path: "/module/m1" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.JSON, response.bodyType); + equals("/module/m1", response?.body?.["request"]["url"]); + equals(Method.DELETE, response?.body?.["request"]["method"]); +}); + + +suite.test("Module HTML Response - Regular - GET /module/m1/test", { + method: Method.GET, + path: "/module/m1/test" +}).expect((response) => { + equals(200, response.status); + equals("OK", response.statusText); + equals(BodyType.HTML, response.bodyType); + includes(response?.body as string, "

Hello, world!

"); +}); + + +suite.test("Module HTML Response - Additional Methods - POST /module/m1/test", { + method: Method.POST, + path: "/module/m1/test" +}).expect((response) => { + equals(201, response.status); + equals("Created", response.statusText); + equals(BodyType.Text, response.bodyType); + includes(response?.body as string, "Hello World"); +}); + +// TODO: Tests to add +// - modules +// - dynamic path (modules + regular) // - status codes - every single one - make endpoint that uses dynamic paths // - status code that doesn't exists // - query parameters -// - dynamic path // - static files // - error page // - ENVIRONMENT VARIABLES diff --git a/tests/endpoints/modules/pass-primary-1/routes/index.ts b/tests/endpoints/modules/pass-primary-1/routes/index.ts index 0d860e2..23e704c 100644 --- a/tests/endpoints/modules/pass-primary-1/routes/index.ts +++ b/tests/endpoints/modules/pass-primary-1/routes/index.ts @@ -8,3 +8,34 @@ export function GET(request:Request, context:unknown) { }); } +export function POST(request:Request, context:unknown) { + return Response.JSON({ + request, + context + }); +} + + +export function PUT(request:Request, context:unknown) { + return Response.JSON({ + request, + context + }); +} + + +export function PATCH(request:Request, context:unknown) { + return Response.JSON({ + request, + context + }); +} + + +export function DELETE(request:Request, context:unknown) { + return Response.JSON({ + request, + context + }); +} + diff --git a/tests/endpoints/modules/pass-primary-1/routes/test/index.ts b/tests/endpoints/modules/pass-primary-1/routes/test/index.ts new file mode 100644 index 0000000..5c9094c --- /dev/null +++ b/tests/endpoints/modules/pass-primary-1/routes/test/index.ts @@ -0,0 +1,7 @@ +import { Response } from "../../../../../../index.js"; + + +export function POST() { + return Response.text("Hello World", { status: 201 }); +} + diff --git a/tests/endpoints/suite/bench.ts b/tests/endpoints/suite/bench.ts index 57c173c..33b9b88 100644 --- a/tests/endpoints/suite/bench.ts +++ b/tests/endpoints/suite/bench.ts @@ -1,4 +1,15 @@ -// FIXME - Add Headers + Footers +/* + * Copyright (C) 2024 Sellers Industries, Inc. + * distributed under the MIT License + * + * author: Evan Sellers + * date: Thu May 16 2024 + * file: bench.ts + * project: SherpaJS - Module Microservice Platform + * purpose: Endpoint Test Suite - Test Benches + * + */ + import { Path } from "../../../src/compiler/utilities/path/index.js"; import { ChildProcess, spawn } from "child_process"; @@ -101,3 +112,7 @@ export class Bench { } + +// If I give all I possess to the poor and give over my body to hardship that +// I may boast, but do not have love, I gain nothing. +// - 1 Corinthians 13:3 diff --git a/tests/endpoints/suite/helpers.ts b/tests/endpoints/suite/helpers.ts index 65c4daf..1ce11c4 100644 --- a/tests/endpoints/suite/helpers.ts +++ b/tests/endpoints/suite/helpers.ts @@ -1,4 +1,15 @@ -// FIXME - Add Headers + Footers +/* + * Copyright (C) 2024 Sellers Industries, Inc. + * distributed under the MIT License + * + * author: Evan Sellers + * date: Thu May 16 2024 + * file: helpers.ts + * project: SherpaJS - Module Microservice Platform + * purpose: Endpoint Test Suite - Verification Helpers + * + */ + export class Fail extends Error { constructor(message:string) { @@ -20,3 +31,7 @@ export function includes(buffer:string, searchString:string) { } } + +// Therefore we do not lose heart. Though outwardly we are wasting away, yet +// inwardly we are being renewed day by day. +// - 2 Corinthians 4:16 diff --git a/tests/endpoints/suite/index.ts b/tests/endpoints/suite/index.ts index 1f90e24..f0c6ab9 100644 --- a/tests/endpoints/suite/index.ts +++ b/tests/endpoints/suite/index.ts @@ -1,4 +1,14 @@ -// FIXME - Add Headers + Footers +/* + * Copyright (C) 2024 Sellers Industries, Inc. + * distributed under the MIT License + * + * author: Evan Sellers + * date: Thu May 16 2024 + * file: index.ts + * project: SherpaJS - Module Microservice Platform + * purpose: Endpoint Test Suite + * + */ import { Suite } from "./suite.js"; @@ -9,3 +19,7 @@ import { equals, includes } from "./helpers.js"; export type { Body }; export { Suite, equals, includes, Method, BodyType }; + +// And he took bread, gave thanks and broke it, and gave it to them, saying, +// "This is my body given for you; do this in remembrance of me." +// - Luke 22:19 diff --git a/tests/endpoints/suite/model.ts b/tests/endpoints/suite/model.ts index 39c4136..f6fbc33 100644 --- a/tests/endpoints/suite/model.ts +++ b/tests/endpoints/suite/model.ts @@ -1,4 +1,15 @@ -// FIXME - Add Headers + Footers +/* + * Copyright (C) 2024 Sellers Industries, Inc. + * distributed under the MIT License + * + * author: Evan Sellers + * date: Thu May 16 2024 + * file: model.ts + * project: SherpaJS - Module Microservice Platform + * purpose: Endpoint Test Suite - Models + * + */ + import { Method, Body } from "../../../index.js"; @@ -25,3 +36,6 @@ export type TestResults = { stack?:string }; + +// Whoever eats my flesh and drinks my blood remains in me, and I in them. +// - John 6:56 diff --git a/tests/endpoints/suite/suite.ts b/tests/endpoints/suite/suite.ts index 8ce9e68..99d093c 100644 --- a/tests/endpoints/suite/suite.ts +++ b/tests/endpoints/suite/suite.ts @@ -1,4 +1,15 @@ -// FIXME - Add Headers + Footers +/* + * Copyright (C) 2024 Sellers Industries, Inc. + * distributed under the MIT License + * + * author: Evan Sellers + * date: Thu May 16 2024 + * file: suite.ts + * project: SherpaJS - Module Microservice Platform + * purpose: Endpoint Test Suite - Suite + * + */ + import { Tester } from "./tester.js"; import { BenchOptions, TestOptions, TestResults } from "./model.js"; @@ -109,3 +120,8 @@ export class Suite { } + +// Wives, submit yourselves to your own husbands as you do to the Lord. For the +// husband is the head of the wife as Christ is the head of the church, his +// body, of which he is the Savior. +// - Ephesians 5:22-23 diff --git a/tests/endpoints/suite/tester.ts b/tests/endpoints/suite/tester.ts index 0fbf368..4a98016 100644 --- a/tests/endpoints/suite/tester.ts +++ b/tests/endpoints/suite/tester.ts @@ -1,4 +1,15 @@ -// FIXME - Add Headers + Footers +/* + * Copyright (C) 2024 Sellers Industries, Inc. + * distributed under the MIT License + * + * author: Evan Sellers + * date: Thu May 16 2024 + * file: tester.ts + * project: SherpaJS - Module Microservice Platform + * purpose: Endpoint Test Suite - Test + * + */ + import StackTracey from "stacktracey"; import { @@ -130,3 +141,7 @@ export class Tester { } + +// You, God, are my God, earnestly I seek you; I thirst for you, my whole being +// longs for you, in a dry and parched land where there is no water. +// - Psalm 63:1 From bf86df08b6a3ed558cd20f97e09e6104413d355b Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 11:25:23 -0400 Subject: [PATCH 13/32] Update index.test.ts --- tests/endpoints/index.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/endpoints/index.test.ts b/tests/endpoints/index.test.ts index f58d696..c3da47b 100644 --- a/tests/endpoints/index.test.ts +++ b/tests/endpoints/index.test.ts @@ -649,6 +649,7 @@ suite.test("Module Response Post - POST /module/m1", { method: Method.POST, path: "/module/m1" }).expect((response) => { + console.log(response); equals(200, response.status); equals("OK", response.statusText); equals(BodyType.JSON, response.bodyType); From 5735dae1ecd770f943e12b834adabd1d007e8e90 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 11:30:12 -0400 Subject: [PATCH 14/32] ?? --- tests/endpoints/modules/pass-primary-1/routes/index.ts | 5 +---- tests/endpoints/server/sherpa.module.ts | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/endpoints/modules/pass-primary-1/routes/index.ts b/tests/endpoints/modules/pass-primary-1/routes/index.ts index 23e704c..37cf58d 100644 --- a/tests/endpoints/modules/pass-primary-1/routes/index.ts +++ b/tests/endpoints/modules/pass-primary-1/routes/index.ts @@ -9,10 +9,7 @@ export function GET(request:Request, context:unknown) { } export function POST(request:Request, context:unknown) { - return Response.JSON({ - request, - context - }); + return Response.text("hi"); } diff --git a/tests/endpoints/server/sherpa.module.ts b/tests/endpoints/server/sherpa.module.ts index 9fc53cc..2523398 100644 --- a/tests/endpoints/server/sherpa.module.ts +++ b/tests/endpoints/server/sherpa.module.ts @@ -7,3 +7,4 @@ export default SherpaJS.New.module({ name: "pass-primary-2", interface: CreateModuleInterface<{ test: boolean }> }); + From 06adc6894c0d753e305740b4b64bdb5c30bd7592 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 13:06:13 -0400 Subject: [PATCH 15/32] Added Route Sorting --- src/compiler/models.ts | 2 ++ src/compiler/structure/assets/index.ts | 11 +++++++++-- src/compiler/structure/endpoint/index.ts | 8 +++++++- .../structure/endpoint/load-functions.ts | 4 +++- src/native/request/utilities.ts | 17 +++++++++++++++++ .../modules/pass-primary-1/routes/index.ts | 6 +++++- tests/endpoints/server/sherpa.module.ts | 1 - tests/endpoints/suite/tester.ts | 1 + 8 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/compiler/models.ts b/src/compiler/models.ts index 743bca1..a8b798a 100644 --- a/src/compiler/models.ts +++ b/src/compiler/models.ts @@ -117,6 +117,7 @@ export type Endpoint = { methods:Method[]; module:ModuleConfigFile; segments:Segment[]; + path:string; } @@ -135,6 +136,7 @@ export type Asset = { filepath:string; filename:string; segments:Segment[]; + path:string; } diff --git a/src/compiler/structure/assets/index.ts b/src/compiler/structure/assets/index.ts index f10efbb..7e4752a 100644 --- a/src/compiler/structure/assets/index.ts +++ b/src/compiler/structure/assets/index.ts @@ -16,6 +16,7 @@ import { Segment, AssetTree, Asset } from "../../models.js"; import { DirectoryStructureTree } from "../../utilities/path/directory-structure/model.js"; import { Message } from "../../utilities/logger/model.js"; import { getAssetFiles } from "./files.js"; +import { RequestUtilities } from "../../../native/request/utilities.js"; export function getAssets(entry:string):{ assets:AssetTree, logs:Message[] } { @@ -38,7 +39,12 @@ export function flattenAssets(assetTree?:AssetTree):Asset[] { let segments = Object.keys(assetTree).filter(segment => segment != "."); assetList.push(...segments.map(segment => flattenAssets(assetTree[segment] as AssetTree)).flat()); - return assetList.flat(); + return assetList.flat().sort(sortAssets); +} + + +function sortAssets(assetA:Asset, assetB:Asset):number { + return RequestUtilities.compareURL(assetA.segments, assetB.segments); } @@ -49,7 +55,8 @@ function getAssetTree(assetTree:DirectoryStructureTree, segments:Segment[]=[]):A return { filepath: file.filepath.absolute, filename: Path.getFilename(file.filepath.absolute), - segments: segments + segments: segments, + path: RequestUtilities.getDynamicURL(segments) + "/" + Path.getFilename(file.filepath.absolute) } }); } diff --git a/src/compiler/structure/endpoint/index.ts b/src/compiler/structure/endpoint/index.ts index df443e0..f7345c3 100644 --- a/src/compiler/structure/endpoint/index.ts +++ b/src/compiler/structure/endpoint/index.ts @@ -11,6 +11,7 @@ */ +import { RequestUtilities } from "../../../native/request/utilities.js"; import { Endpoint, EndpointTree, FILENAME, FILE_EXTENSIONS, ModuleConfigFile, Segment } from "../../models.js"; import { Level, Message } from "../../utilities/logger/model.js"; import { DirectoryStructureTree } from "../../utilities/path/directory-structure/model.js"; @@ -45,7 +46,12 @@ export function flattenEndpoints(endpointTree?:EndpointTree):Endpoint[] { let segments = Object.keys(endpointTree).filter(segment => segment != "."); endpointList.push(...segments.map(segment => flattenEndpoints(endpointTree[segment] as EndpointTree)).flat()); - return endpointList; + return endpointList.sort(sortEndpoints); +} + + +function sortEndpoints(endpointA:Endpoint, endpointB:Endpoint):number { + return RequestUtilities.compareURL(endpointA.segments, endpointB.segments); } diff --git a/src/compiler/structure/endpoint/load-functions.ts b/src/compiler/structure/endpoint/load-functions.ts index 0002072..5c47370 100644 --- a/src/compiler/structure/endpoint/load-functions.ts +++ b/src/compiler/structure/endpoint/load-functions.ts @@ -18,6 +18,7 @@ import { EXPORT_VARIABLES, EXPORT_VARIABLES_METHODS, Method, FILENAME } from "../../models.js"; +import { RequestUtilities } from "../../../native/request/utilities.js"; export async function getEndpointFunctions(module:ModuleConfigFile, functionsFilepath:string|undefined, viewFilepath:string|undefined, segments:Segment[]):Promise<{ logs:Message[], endpoints?:EndpointTree }> { @@ -45,7 +46,8 @@ export async function getEndpointFunctions(module:ModuleConfigFile, functionsFil viewFilepath: viewFilepath, methods: getExportedMethods(variables), module: module, - segments: segments + segments: segments, + path: RequestUtilities.getDynamicURL(segments) } } } diff --git a/src/native/request/utilities.ts b/src/native/request/utilities.ts index 765f61a..fd14717 100644 --- a/src/native/request/utilities.ts +++ b/src/native/request/utilities.ts @@ -31,6 +31,23 @@ export class RequestUtilities { } + static compareURL(segmentsA:Segment[], segmentsB:Segment[]):number { + if (segmentsA.length == 0 || segmentsB.length == 0) { + return segmentsA.length - segmentsB.length; + } + if (segmentsA[0].isDynamic && !segmentsB[0].isDynamic) { + return 1; + } + if (!segmentsA[0].isDynamic && segmentsB[0].isDynamic) { + return -1; + } + if (segmentsA[0]["name"] != segmentsB[0]["name"]) { + return segmentsA[0]["name"].localeCompare(segmentsB[0]["name"]); + } + return this.compareURL(segmentsA.slice(1), segmentsB.slice(1)); + } + + } diff --git a/tests/endpoints/modules/pass-primary-1/routes/index.ts b/tests/endpoints/modules/pass-primary-1/routes/index.ts index 37cf58d..495fb5a 100644 --- a/tests/endpoints/modules/pass-primary-1/routes/index.ts +++ b/tests/endpoints/modules/pass-primary-1/routes/index.ts @@ -8,8 +8,12 @@ export function GET(request:Request, context:unknown) { }); } + export function POST(request:Request, context:unknown) { - return Response.text("hi"); + return Response.JSON({ + request, + context + }); } diff --git a/tests/endpoints/server/sherpa.module.ts b/tests/endpoints/server/sherpa.module.ts index 2523398..9fc53cc 100644 --- a/tests/endpoints/server/sherpa.module.ts +++ b/tests/endpoints/server/sherpa.module.ts @@ -7,4 +7,3 @@ export default SherpaJS.New.module({ name: "pass-primary-2", interface: CreateModuleInterface<{ test: boolean }> }); - diff --git a/tests/endpoints/suite/tester.ts b/tests/endpoints/suite/tester.ts index 4a98016..d7944f0 100644 --- a/tests/endpoints/suite/tester.ts +++ b/tests/endpoints/suite/tester.ts @@ -48,6 +48,7 @@ export class Tester { this.handler!(await this.getResponse(host)); return { name: this.name, success: true }; } catch (error) { + console.log(error); let stack = new StackTracey(error.stack).items.map((e) => e.beforeParse).join("\n"); if (error instanceof Fail) { return { From e33a1315d989b64d15784e99124d32bd851afdfb Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 13:07:53 -0400 Subject: [PATCH 16/32] Updated Workflow --- .github/workflows/testing.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index cfdc576..e0ea0ff 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -6,6 +6,7 @@ on: jobs: + unit-test: strategy: matrix: @@ -30,9 +31,14 @@ jobs: - name: Run Unit Tests run: npm run test-unit + endpoint-test: - name: Endpoint Tests - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + name: Endpoint Tests (${{ matrix.os }}) + runs-on: ${{ matrix.os }} steps: - name: Checkout code @@ -48,6 +54,7 @@ jobs: - name: Run Endpoint Tests run: npm run test-endpoints + linting: name: Linting runs-on: ubuntu-latest From a161163a4346922c7bf5bd7513f64da11963570d Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 13:17:13 -0400 Subject: [PATCH 17/32] Prevent Multiple Dynamic Routes --- src/compiler/structure/endpoint/files.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/compiler/structure/endpoint/files.ts b/src/compiler/structure/endpoint/files.ts index df9ae08..4e236df 100644 --- a/src/compiler/structure/endpoint/files.ts +++ b/src/compiler/structure/endpoint/files.ts @@ -108,6 +108,7 @@ function validateFile(file:DirectoryStructureFile):Message[] { function validateSegments(structure:DirectoryStructureTree, filepath:string):Message[] { let errors:Message[] = []; + errors.push(...validateMultipleDynamicSegments(Object.keys(structure.directories), filepath)); for (let segmentName of Object.keys(structure.directories)) { let _filepath = Path.join(filepath, segmentName); errors.push(...validateSegmentName(segmentName, _filepath)); @@ -129,6 +130,21 @@ function validateSegmentName(segment:string, filepath?:string):Message[] { } +function validateMultipleDynamicSegments(segments:string[], filepath:string):Message[] { + let hasMultipleDynamicPaths = segments.map((segment) => { + return segment.startsWith("[") && segment.endsWith("]"); + }).filter((segment) => segment).length > 1; + if (hasMultipleDynamicPaths) { + return [{ + level: Level.ERROR, + text: "Only one dynamic endpoint per route is allowed.", + file: { filepath: filepath } + }]; + } + return []; +} + + // Who is it that overcomes the world? Only the one who believes that Jesus // is the Son of God. // - 1 John 5:5 From 8f0ef0b484da018c9397abcb2797b99ecfd74aac Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 13:37:04 -0400 Subject: [PATCH 18/32] Improved Response Class --- src/internal/request/index.ts | 2 +- src/internal/response/index.ts | 4 +- src/native/index.ts | 15 +++--- src/native/request/{interface.ts => index.ts} | 4 +- src/native/response/index.ts | 48 +++++++++++-------- src/native/response/interface.ts | 32 ------------- .../regular/response/none/basic/index.ts | 2 +- .../regular/response/none/custom/index.ts | 2 +- 8 files changed, 42 insertions(+), 67 deletions(-) rename src/native/request/{interface.ts => index.ts} (93%) delete mode 100644 src/native/response/interface.ts diff --git a/src/internal/request/index.ts b/src/internal/request/index.ts index d1e5f99..7460ba9 100644 --- a/src/internal/request/index.ts +++ b/src/internal/request/index.ts @@ -11,7 +11,7 @@ */ -import { IRequest } from "../../native/request/interface.js"; +import { IRequest } from "../../native/request/index.js"; import { Body, BodyType } from "../../native/model.js"; import { Headers } from "../../native/headers/index.js"; import { Parameters } from "../../native/parameters/index.js"; diff --git a/src/internal/response/index.ts b/src/internal/response/index.ts index b9157a4..6ff917a 100644 --- a/src/internal/response/index.ts +++ b/src/internal/response/index.ts @@ -13,8 +13,8 @@ import { OriginURL } from "../../native/url/index.js"; import { BodyType } from "../../native/model.js"; -import { IRequest } from "../../native/request/interface.js"; -import { IResponse } from "../../native/response/interface.js"; +import { IRequest } from "../../native/request/index.js"; +import { IResponse } from "../../native/response/index.js"; import { ServerResponse as LocalResponse } from "http"; const VercelResponse = Response; type VercelResponseType = Response; diff --git a/src/native/index.ts b/src/native/index.ts index 11ce40e..5dec1c2 100644 --- a/src/native/index.ts +++ b/src/native/index.ts @@ -14,28 +14,27 @@ import { Parameters } from "./parameters/index.js"; import { Headers } from "./headers/index.js"; import { Body, BodyType } from "./model.js"; -import { IResponse } from "./response/interface.js"; -import { ResponseBuilder, Options as ResponseOptions } from "./response/index.js"; -import { IRequest } from "./request/interface.js"; +import { IResponse, Options as ResponseOptions } from "./response/index.js"; +import { IRequest } from "./request/index.js"; import { CreateModuleInterface, Method, ModuleInterface } from "../compiler/models.js"; export { - ResponseBuilder as Response, Headers, Parameters, Method, BodyType, CreateModuleInterface, - ModuleInterface + ModuleInterface, + IRequest as Request, + IRequest, + IResponse as Response, + IResponse } export type { Body, - IRequest as Request, - IRequest, - IResponse, ResponseOptions } diff --git a/src/native/request/interface.ts b/src/native/request/index.ts similarity index 93% rename from src/native/request/interface.ts rename to src/native/request/index.ts index 027eed9..e9562a7 100644 --- a/src/native/request/interface.ts +++ b/src/native/request/index.ts @@ -4,7 +4,7 @@ * * author: Evan Sellers * date: Tue Mar 19 2024 - * file: interface.ts + * file: index.ts * project: SherpaJS - Module Microservice Platform * purpose: Request Interface * @@ -17,7 +17,7 @@ import { Parameters } from "../parameters/index.js"; import { Method } from "../../compiler/models.js"; -export interface IRequest { +export class IRequest { readonly url:string; readonly params:{ path:Parameters, query:Parameters }; diff --git a/src/native/response/index.ts b/src/native/response/index.ts index 29f556d..f326eb8 100644 --- a/src/native/response/index.ts +++ b/src/native/response/index.ts @@ -12,8 +12,7 @@ import { Headers, HeadersInit } from "../headers/index.js"; -import { BodyType, CONTENT_TYPE } from "../model.js"; -import { IResponse } from "./interface.js"; +import { Body, BodyType, CONTENT_TYPE } from "../model.js"; import { STATUS_TEXT } from "./status-text.js"; @@ -23,26 +22,36 @@ export interface Options { } -export class ResponseBuilder { +export class IResponse { + + readonly status:number; + readonly statusText:string; + readonly headers:Headers; + + readonly body:Body; + readonly bodyType:keyof typeof BodyType; + + + constructor(options?:Partial) { + let _options = IResponse.defaultOptions(BodyType.None, options); + this.status = _options.status; + this.statusText = IResponse.getStatusText(_options.status); + this.headers = _options.headers; + this.body = undefined; + this.bodyType = BodyType.None; + } static new(options?:Partial):IResponse { - let _options = ResponseBuilder.defaultOptions(BodyType.None, options); - return { - status: _options.status, - statusText: ResponseBuilder.getStatusText(_options.status), - headers: _options.headers, - body: undefined, - bodyType: BodyType.None - } + return new IResponse(options); } static text(text:T, options?:Partial):IResponse { - let _options = ResponseBuilder.defaultOptions(BodyType.Text, options); + let _options = IResponse.defaultOptions(BodyType.Text, options); return { status: _options.status, - statusText: ResponseBuilder.getStatusText(_options.status), + statusText: IResponse.getStatusText(_options.status), headers: _options.headers, body: text.toString(), bodyType: BodyType.Text @@ -51,11 +60,11 @@ export class ResponseBuilder { static JSON }>(JSON:T|Record, options?:Partial):IResponse { - let _options = ResponseBuilder.defaultOptions(BodyType.JSON, options); + let _options = IResponse.defaultOptions(BodyType.JSON, options); let _isCallable = JSON.toJSON && typeof (JSON as Record).toJSON === "function"; return { status: _options.status, - statusText: ResponseBuilder.getStatusText(_options.status), + statusText: IResponse.getStatusText(_options.status), headers: _options.headers, body: _isCallable ? (JSON as { toJSON():Record }).toJSON() : JSON, bodyType: BodyType.JSON @@ -64,10 +73,10 @@ export class ResponseBuilder { static HTML(html:string, options?:Partial):IResponse { - let _options = ResponseBuilder.defaultOptions(BodyType.HTML, options); + let _options = IResponse.defaultOptions(BodyType.HTML, options); return { status: _options.status, - statusText: ResponseBuilder.getStatusText(_options.status), + statusText: IResponse.getStatusText(_options.status), headers: _options.headers, body: html, bodyType: BodyType.HTML @@ -76,13 +85,13 @@ export class ResponseBuilder { static redirect(redirect:string):IResponse { - let _options = ResponseBuilder.defaultOptions(BodyType.None, {}); + let _options = IResponse.defaultOptions(BodyType.None, {}); if (!_options.headers.has("Location")) { _options.headers.set("Location", redirect); } return { status: 302, - statusText: ResponseBuilder.getStatusText(302), + statusText: IResponse.getStatusText(302), headers: _options.headers, body: undefined, bodyType: BodyType.None @@ -110,7 +119,6 @@ export class ResponseBuilder { return text; } - } diff --git a/src/native/response/interface.ts b/src/native/response/interface.ts deleted file mode 100644 index 1aebc00..0000000 --- a/src/native/response/interface.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2024 Sellers Industries, Inc. - * distributed under the MIT License - * - * author: Evan Sellers - * date: Tue Mar 19 2024 - * file: interface.ts - * project: SherpaJS - Module Microservice Platform - * purpose: Response Interface - * - */ - - -import { Body, BodyType } from "../model.js"; -import { Headers } from "../headers/index.js"; - - -export interface IResponse { - - readonly status:number; - readonly statusText:string; - readonly headers:Headers; - - readonly body:Body; - readonly bodyType:keyof typeof BodyType; - -} - - -// Whoever believes in me, as Scripture has said, rivers of living water will -// flow from within them. -// - John 7:38 diff --git a/tests/endpoints/server/routes/regular/response/none/basic/index.ts b/tests/endpoints/server/routes/regular/response/none/basic/index.ts index 67431a8..34524f0 100644 --- a/tests/endpoints/server/routes/regular/response/none/basic/index.ts +++ b/tests/endpoints/server/routes/regular/response/none/basic/index.ts @@ -2,7 +2,7 @@ import { Response } from "../../../../../../../../index.js"; export function GET() { - return Response.new(); + return new Response(); } diff --git a/tests/endpoints/server/routes/regular/response/none/custom/index.ts b/tests/endpoints/server/routes/regular/response/none/custom/index.ts index f13afcf..272d6a5 100644 --- a/tests/endpoints/server/routes/regular/response/none/custom/index.ts +++ b/tests/endpoints/server/routes/regular/response/none/custom/index.ts @@ -2,7 +2,7 @@ import { Response, Headers as SherpaHeaders } from "../../../../../../../../inde export function GET() { - return Response.new({ + return new Response({ status: 401, headers: { "X-Foo": "bar" From ef7c2c2930444dda8dd7653413fce94f2abe1562 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 13:37:32 -0400 Subject: [PATCH 19/32] Update index.ts --- src/native/response/index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/native/response/index.ts b/src/native/response/index.ts index f326eb8..1872a36 100644 --- a/src/native/response/index.ts +++ b/src/native/response/index.ts @@ -24,12 +24,12 @@ export interface Options { export class IResponse { - readonly status:number; - readonly statusText:string; - readonly headers:Headers; + status:number; + statusText:string; + headers:Headers; - readonly body:Body; - readonly bodyType:keyof typeof BodyType; + body:Body; + bodyType:keyof typeof BodyType; constructor(options?:Partial) { From 2a2495e4046bdfd59033eac4b6619af2885f66eb Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 13:41:37 -0400 Subject: [PATCH 20/32] Updated Workflow --- .github/workflows/testing.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index e0ea0ff..569efa1 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -34,8 +34,8 @@ jobs: endpoint-test: strategy: - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] name: Endpoint Tests (${{ matrix.os }}) runs-on: ${{ matrix.os }} From 725a19b33109a6edd2a217a90faf1e252163ef71 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 14:05:37 -0400 Subject: [PATCH 21/32] Updated Docs --- docs.json | 2 +- docs/api/components/request.mdx | 14 +- docs/api/components/response.mdx | 232 +++++++++++++++++++++++++++++++ src/native/response/index.ts | 10 +- 4 files changed, 245 insertions(+), 13 deletions(-) create mode 100644 docs/api/components/response.mdx diff --git a/docs.json b/docs.json index a8a81a9..97f0b82 100644 --- a/docs.json +++ b/docs.json @@ -21,7 +21,7 @@ ], [ "API Reference", [ - ["Response - WIP", [["Response - WIP", "/api/response"]]], + ["Response", "/api/components/response"], ["Request", "/api/components/request"], ["Headers", "/api/components/headers"], ["Parameters", "/api/components/parameters"], diff --git a/docs/api/components/request.mdx b/docs/api/components/request.mdx index d3a824a..a434580 100644 --- a/docs/api/components/request.mdx +++ b/docs/api/components/request.mdx @@ -1,5 +1,5 @@ # Request -The `Request` interface represents an HTTP request with various properties such +The `Request` class represents an HTTP request with various properties such as URL, parameters, method, headers, body, and body type. This object is passed to an endpoint when a request is made. @@ -10,7 +10,7 @@ to an endpoint when a request is made. ## Properties ### url - * Type - `string` + * Type - `string` *(readonly)* * Description - The URL of the HTTP request. @@ -18,7 +18,7 @@ to an endpoint when a request is made. ### params - * Type - `{ path: Parameters, query: Parameters }` + * Type - `{ path: Parameters, query: Parameters }` *(readonly)* * Description - An object containing `path` and `query` parameters represented by instances of the [Parameters class](/api/components/parameters). @@ -27,7 +27,7 @@ to an endpoint when a request is made. ### method - * Type - `keyof typeof Method` + * Type - `keyof typeof Method` *(readonly)* * Description - The HTTP method of the request, represented as one of the keys of the [Method](/api/components/request#method-1) enum. @@ -36,7 +36,7 @@ to an endpoint when a request is made. ### headers - * Type - `Headers` + * Type - `Headers` *(readonly)* * Description - The headers of the request, represented by an instance of the [Headers class](/api/components/headers). @@ -45,7 +45,7 @@ to an endpoint when a request is made. ### body - * Type - `Body` + * Type - `Body` *(readonly)* * Description - The body of the request, which can be `undefined`, a string, or a JSON object. The body will be automatically parsed from the request. @@ -54,7 +54,7 @@ to an endpoint when a request is made. ### bodyType - * Type - `keyof typeof BodyType` + * Type - `keyof typeof BodyType` *(readonly)* * Description: The type of the request body, represented as one of the keys of the [BodyType](/api/components/request#bodytypes-1) enum. diff --git a/docs/api/components/response.mdx b/docs/api/components/response.mdx new file mode 100644 index 0000000..e308ab5 --- /dev/null +++ b/docs/api/components/response.mdx @@ -0,0 +1,232 @@ +# Response +The `Response` class represents an HTTP response with various properties such +as status, status text, headers, body, and body type. The object is returned +from an endpoint when a request is made. The class also has static methods for +creating creating HTTP response objects with various content types. + + +
+ + +## Properties + +### status + * Type - `number` *(readonly)* + * Description - The status code for the response. See + [HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) + for more information. + + +
+ + +### statusText + * Type - `string` *(readonly)* + * Description - The status message for the corresponding status code. See + [HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) + for more information. + + +
+ + +### headers + * Type - `Headers` *(readonly)* + * Description - The headers of the response, represented by an instance + of the [Headers class](/api/components/headers). + + +
+ + +### body + * Type - `Body` *(readonly)* + * Description - The body of the response, which can be `undefined`, a string, + or a JSON object. + + +
+ + +### bodyType + * Type - `keyof typeof BodyType` *(readonly)* + * Description - The type of the response body, represented as one of the keys of + the [BodyType](/api/components/response#bodytypes-1) enum. + + +
+ + +## Static Methods + + +### new +`static new(options?: Partial): Response` \ +Creates a new response with no body. + * `options` (optional): Partial configuration options for the response. + * [`headers`](/api/components/headers): The headers to include in the response. + * `status`: The HTTP status code of the response. + + +
+ + +### text +`static text(text: T, options?: Partial): Response` \ +Creates a new response with a text body. + * `text`: The text content for the response body. Can be an object with a `toString` method or a plain string. + * `options` (optional): Partial configuration options for the response. + * [`headers`](/api/components/headers): The headers to include in the response. + * `status`: The HTTP status code of the response. + + +
+ + +### JSON +`static JSON }>(JSON: T | Record, options?: Partial): Response` \ +Creates a new response with a JSON body. + * `JSON`: The JSON content for the response body. Can be an object with a `toJSON` method or a plain object. + * `options` (optional): Partial configuration options for the response. + * [`headers`](/api/components/headers): The headers to include in the response. + * `status`: The HTTP status code of the response. + + +
+ + +### HTML +`static HTML(html: string, options?: Partial): Response` \ +Creates a new response with an HTML body. + * `html`: The HTML content for the response body. + * `options` (optional): Partial configuration options for the response. + * [`headers`](/api/components/headers): The headers to include in the response. + * `status`: The HTTP status code of the response. + + +
+ + +### redirect +`static redirect(redirect: string): Response` \ +Creates a new redirect response with a `Location` header. + * `redirect`: The URL to redirect to. + + +
+ + +## Enums + +### BodyType +An enum representing the possible types of the request body: + * `JSON` - The body is in JSON format. + * `Text` - The body is in plain text format. + * `HTML` - The body is in HTML format. + * `None` - There is no body associated with the request. + + +
+ + +## Examples + +### No Body +```typescript +import { Response, Headers } from "sherpa-core"; + +export function GET() { + return new Response(); +} + +export function POST() { + return new Response({ + status: 201, + headers: { + "X-Foo": "bar" + } + }); +} + +export function PUT() { + return Response.new({ + status: 401, + headers: new Headers({ + "X-Foo": "bar" + }) + }); +} +``` + + +
+ + +### Text Body +```typescript +import { Response, Headers } from "sherpa-core"; + +export function GET() { + return Response.text("Hello World!"); +} + +export function POST() { + return Response.text("Hello World!", { + status: 201 + }); +} +``` + + +
+ + +### JSON Body +```typescript +import { Response, Headers } from "sherpa-core"; + +export function GET() { + return Response.JSON({ "foo": "bar" }); +} + +export function POST() { + return Response.JSON({ "foo": "bar" }, { + status: 201 + }); +} +``` + + +
+ + +### HTML Body +```typescript +import { Response, Headers } from "sherpa-core"; + +export function GET() { + return Response.HTML("

Hello World

"); +} + +export function POST() { + return Response.HTML("

Hello World

", { + status: 201 + }); +} +``` + + +
+ + +### Redirect +Assuming this endpoint is at route `/example/foo` the user will be redirected +to `/example/success`. + +```typescript +import { Response, Headers } from "sherpa-core"; + +export function GET() { + return Response.redirect("../success"); +} +``` diff --git a/src/native/response/index.ts b/src/native/response/index.ts index 1872a36..f326eb8 100644 --- a/src/native/response/index.ts +++ b/src/native/response/index.ts @@ -24,12 +24,12 @@ export interface Options { export class IResponse { - status:number; - statusText:string; - headers:Headers; + readonly status:number; + readonly statusText:string; + readonly headers:Headers; - body:Body; - bodyType:keyof typeof BodyType; + readonly body:Body; + readonly bodyType:keyof typeof BodyType; constructor(options?:Partial) { From 18267730d08af50acff481764363fcd9e8dbb7bd Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Thu, 16 May 2024 20:43:39 -0400 Subject: [PATCH 22/32] Updated Docs --- docs.json | 4 +- docs/build/module-config.mdx | 188 ++++++++++++++++++++++++++++++++++- docs/build/server-config.mdx | 122 ++++++++++++++++++++++- 3 files changed, 310 insertions(+), 4 deletions(-) diff --git a/docs.json b/docs.json index 97f0b82..7bb6395 100644 --- a/docs.json +++ b/docs.json @@ -15,8 +15,8 @@ ["Routes - WIP", "/build/routes"], ["Endpoints - WIP", "/build/endpoints"], ["Static Assets - WIP", "/build/static-assets"], - ["Server Config - WIP", "/build/server-config"], - ["Module Config - WIP", "/build/module-config"] + ["Server Config", "/build/server-config"], + ["Module Config", "/build/module-config"] ] ], [ "API Reference", diff --git a/docs/build/module-config.mdx b/docs/build/module-config.mdx index a171803..9e3d862 100644 --- a/docs/build/module-config.mdx +++ b/docs/build/module-config.mdx @@ -1 +1,187 @@ -# Module Config \ No newline at end of file +# Module Configuration +Sherpa modules are configured using a `sherpa.module.ts` file, where you define +the structure and behavior of your module. This configuration file is located +at the root of your project and serves as the entry point for your Sherpa module. + + +## Config File +The configuration file must be located at `sherpa.module.ts` and have a +default export of the config using the `SherpaJS.New.module` function as +follows. You can export a class using `CreateModuleInterface` that acts as a +wrapper for validating the context when the module is loaded. + + +
+ + +### Basic Configuration +This basic configuration sets up a module with a simple interface +definition. The context schema is defined inline using the +`CreateModuleInterface` function. + +```typescript title="sherpa.module.ts" +import { SherpaJS, CreateModuleInterface } from "sherpa-core"; + +export default SherpaJS.New.module({ + name: "example-module", + interface: CreateModuleInterface<{ foo: boolean, bar: string }>() +}); +``` + + +
+ + +### Class-Based Configuration +Alternatively, you can export any interface class with a constructor that +takes the context as a parameter and sets `this.context` within your class. +You can attach additional methods to interact with your module. + +These interfaces can be called by other functions and endpoints inside your +codebase, see the +[calling module interfaces example](/build/module-config#module-interface-call-example). + +```typescript title="sherpa.module.ts" +import { SherpaJS, ModuleInterface } from "sherpa-core"; + +export default SherpaJS.New.module({ + name: "example-module", + interface: class Example implements ModuleInterface { + context: { foo: number, bar: string }; + constructor(context: { foo: number, bar: string }) { + this.context = context; + } + } +}); +``` + + + You can also export any additional attributes from this file as needed. The + module config file, `sherpa.module.ts` should be the main script defined + in your `package.json`. + + + +
+ + +## Config Structure + +### name +The name of the module. + + +
+ + +### interface +A class that has a constructor with `context:[TYPE]` parameter and a +property `context: [TYPE]`. You can also use `CreateModuleInterface` to +generate this class. + + +
+ + +## Module Config Type +The module configuration type is structured as: + +```typescript +{ + name:string; + interface:T; +} +``` + +where `T` is a class that implements implements `ModuleInterface`. Thus, it +has a `context` and a `constructor` that takes `context` as a parameter. + +```typescript +{ + context:Schema; + constructor(context:Schema) { this.context = context; } +} +``` + + +
+ + +## Example Config + +### Basic Example +A basic configuration using the `CreateModuleInterface` function. + +```typescript title="example-module/sherpa.module.ts" +import { SherpaJS, CreateModuleInterface } from "sherpa-core"; + +export default SherpaJS.New.module({ + name: "example-module", + interface: CreateModuleInterface<{ foo: boolean, bar: string }>() +}); +``` + +Loading the module from a server endpoints, [learn more](/build/endpoints). +```typescript title="route/module.ts" +import ExampleModule from "../example-module/sherpa.module.ts"; + +export default ExampleModule.load({ + foo: true, + bar: "hello" +}) +``` + + + +
+ + +### Module Interface Call Example + +A basic configuration using the `CreateModuleInterface` function. + +```typescript title="example-module/sherpa.module.ts" +import { SherpaJS, CreateModuleInterface } from "sherpa-core"; + +export type Schema = { foo: number, bar: string }; + +export default SherpaJS.New.module({ + name: "example-module", + interface: class Example implements ModuleInterface { + + context:Schema; + + constructor(context:Schema) { + this.context = context; + } + + getFoo():number { + return this.context.foo; + } + + } +}); +``` + +Loading the a module from a server endpoints, +[learn more](/build/endpoints). +```typescript title="route/example/module.ts" +import ExampleModule from "../../example-module/sherpa.module.ts"; + +export default ExampleModule.load({ + foo: 3, + bar: "hello" +}) +``` + +Calling the loaded module instance from another endpoint... +```typescript title="route/index.ts" +import { Request, Response } from "sherpa-core"; +import example from "./example/module.ts"; + +export function GET() { + return Response.text(example.getFoo()); // returns 3 +} + +``` + diff --git a/docs/build/server-config.mdx b/docs/build/server-config.mdx index dbfed2e..b63da57 100644 --- a/docs/build/server-config.mdx +++ b/docs/build/server-config.mdx @@ -1 +1,121 @@ -# Server Config \ No newline at end of file +# Server Configuration +Sherpa servers are configured using a `sherpa.server.ts` file, where you define +the structure and behavior of your server. This configuration file is located +at the root of your project and serves as the entry point for your Sherpa server. + + +
+ + +## Config File +The configuration file must be located at `sherpa.server.ts` and have a +default export of the config using the `SherpaJS.New.server` function as follows: + +```typescript title="sherpa.server.ts" +import SherpaJS from "sherpa-core"; + +export default SherpaJS.New.server({ + content: { + serverSecret: process.env.SERVER_SECRET, + allowThingy: true + } +}); +``` + + + When you load modules they have there own context, that is provided + by the module loader, and do not have access to your server context. + + + + +
+ + +## Config Structure + +### Context +A property that allows you to define a context object. Contexts are +provided to endpoints and can contain any additional data or settings needed +for request processing. + + +
+ + +## Server Config Type +The server configuration type is structured as: + +```typescript +{ + context: T; +} +``` + +where `T` can be any type, allowing for flexible and customizable +server configurations. + + +
+ + +## Examples + +### Basic Example +A basic configuration where the context contains simple settings: + +```typescript title="sherpa.server.ts" +import { SherpaJS } from "sherpa-core"; + +export default SherpaJS.New.server({ + context: { + serverSecret: "foo", + allowThingy: true + } +}); +``` + +The context object is then available within endpoints. +```typescript title="routes/index.ts" +import { Request, Response } from "sherpa-core"; + + +export function GET(request:Request, context:unknown) { + consoe.log(context.serverSecret); // returns "foo" + consoe.log(context.allowThingy); // returns true + return Response.new(); +} +``` + + +
+ + +### Typed Example +A more detailed configuration using a typed context for additional type +safety and clarity: + +```typescript title="sherpa.server.ts" +import { SherpaJS } from "sherpa-core"; + +type ConfigExample = { serverSecret: string; allowThingy: boolean }; + +export default SherpaJS.New.server({ + context: { + serverSecret: "foo", + allowThingy: true + } +}); +``` + +The context object is then available within endpoints. +```typescript title="routes/index.ts" +import { Request, Response } from "sherpa-core"; + + +export function GET(request:Request, context:ConfigExample) { + consoe.log(context.serverSecret); // returns "foo" + consoe.log(context.allowThingy); // returns true + return Response.new(); +} +``` From 32856453b070b1edd9265bb6b1443b88ae6ebf9f Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Fri, 17 May 2024 09:02:56 -0400 Subject: [PATCH 23/32] Updated Documentation --- docs.json | 2 +- docs/build/routes.mdx | 5 -- docs/build/routing.mdx | 162 +++++++++++++++++++++++++++++++++++++++++ docs/index.mdx | 28 +++++++ 4 files changed, 191 insertions(+), 6 deletions(-) delete mode 100644 docs/build/routes.mdx create mode 100644 docs/build/routing.mdx diff --git a/docs.json b/docs.json index 7bb6395..cc385d6 100644 --- a/docs.json +++ b/docs.json @@ -12,7 +12,7 @@ ], [ "Building Your Application", [ - ["Routes - WIP", "/build/routes"], + ["Routing", "/build/routing"], ["Endpoints - WIP", "/build/endpoints"], ["Static Assets - WIP", "/build/static-assets"], ["Server Config", "/build/server-config"], diff --git a/docs/build/routes.mdx b/docs/build/routes.mdx deleted file mode 100644 index bc51cc3..0000000 --- a/docs/build/routes.mdx +++ /dev/null @@ -1,5 +0,0 @@ -# Routes - -## Regular Route - -## Dynamic Route \ No newline at end of file diff --git a/docs/build/routing.mdx b/docs/build/routing.mdx new file mode 100644 index 0000000..1233e4f --- /dev/null +++ b/docs/build/routing.mdx @@ -0,0 +1,162 @@ +# Routing +SherpaJS provides a flexible and intuitive way to define endpoints and handle +incoming requests within your microservice architecture. Drawing inspiration +by Next.js, SherpaJS routes follow a directory-based structure located in +the `/routes` directory of your module. + + +## Terminology + +### Route Component Tree + * **Routes**: A hierarchical structure for all the segments and endpoints + of the server. + * **Subroutes**: A subsection of the route structure. + * **Root**: The first level of segments and endpoints in a route or subroute. + + +
+ + +### URL Anatomy + * **Segment**: The directory name part of the URL path delimited by slashes. + * **URL Path**: The part of the URL that comes after the domain, composed of segments. + * **Endpoint**: The final destination in the route structure where the request + is handled, typically defined in `index.ts` files. + + +
+ + +## Structure of Routes +In the `/routes` directory, you can create directories to organize your +routes. Each endpoint within a route is represented by a file typically named +`index.ts`, [learn more about other types of endpoints](/build/endpoints). + + +
+ + +### Example Route Structure +```plaintext +/routes +│ +├── /users +│ └── index.ts // Endpoint logic for "/users" +│ +│ +├── /example +│ ├── index.ts // Endpoint logic for "/example" +│ ├── /subroute +│ │ └── index.ts // Endpoint logic for "/example/subroute" +│ +├── /[id] +│ └── index.ts // Endpoint logic for "/[id]" access "[id]" with request.params.path.get("id") +│ +├── /products +│ ├── index.ts // Endpoint logic for "/products" +│ ├── /[productID] +│ │ └── index.ts // Endpoint logic for "/products/[productID]" access "[productID]" with request.params.path.get("productID") +│ └── /category +│ └── index.ts // Endpoint logic for "/products/category" +``` + + +
+ + +## Defining Segment routes +Routes in SherpaJS are created using a file-system based router where folders +define segment routes, and files inside these folders define the endpoint logic. + + +
+ + +### Basic Segment Route +In SherpaJS, the basic segment routes are straightforward. Each folder +represents a route segment, and the `index.ts` file within the folder +contains the endpoint logic, [or other types of endpoints](/build/endpoints). + +```typescript title="routes/index.ts" +import { Request, Response } from "sherpa-core"; + +export function GET(request:Request) { + return Response.text("Hello World!"); +} +``` + + +
+ + +### Nested Segment Route +To create a nested segment route, nest folders inside each other. For example, to +create a `/dashboard/settings` route, you would nest two folders like so: + +```plaintext +/routes +│ +├── /dashboard +│ ├── index.ts // Endpoint logic for "/dashboard" +│ └── /settings +│ └── index.ts // Endpoint logic for "/dashboard/settings" +``` + +```typescript title="routes/dashboard/settings/index.ts" +import { Request, Response } from "sherpa-core"; + +export function GET(request:Request) { + return Response.text("Hello World!"); +} +``` + + +
+ + +### Dynamic Segment Route +To define a dynamic segment route, name a directory using square brackets, such +as `[id]`. Within a dynamic segment route directory, you can access the parameter +value from the request object in your endpoint logic. For example, if you have +a dynamic segement route named `[id]`, you can access the parameter +using `request.params.path.get("id")`. + +```plaintext +/routes +│ +├── /products +│ └── /[id] +│ └── index.ts // Endpoint logic for "/products/[id]" +``` + +```typescript title="routes/products/[id]/index.ts" +import { Request, Response } from "sherpa-core"; + +export function GET(request:Request) { + return Response.new(request.params.path.get("id")); +} +``` + + +
+ + +## Restrictions +The SherpaJS routing system has some restrictions when it comes to defining +routes, these restrictions help to keep routing simple, consistent, and ensure +best practices. The SherpaJS compiler will prevent you from compiling if you +violate any of these restrictions. + * Multiple [dynamic segement routes](/build/routing#dynamic-segment-route) + are not allowed in a single segement route. + * Additional segment routes or endpoints are not allowed as the segment where + a [Module Endpoint](/build/endpoints#module-endpoint) is loaded. + + +
+ + +## Next Steps +Now that you understand the fundamentals of routing in SherpaJS, you can start +creating endpoints for your application. \ + +[Learn more about Endpoints](/build/endpoints) diff --git a/docs/index.mdx b/docs/index.mdx index d01d9d4..4273c86 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -67,3 +67,31 @@ The current platforms that SherpaJS supports, with more to come in the future! * Vercel Edge Functions * Local + +
+ + +## Deploy a Server +SherpaJS can compile to various different web platforms, with more to come +later. Want to support a new framework? [Submit a Ticket](https://github.com/sellersindustry/SherpaJS/issues). +See the [build command](/api/cli#build-command) to compile to each platform. + + +
+ + +### Vercel Edge Functions +Building to Vercel will generate a Vercel serverless server in the `.vercel` +directory relative to your output. When your SherpaJS server repository is +deployed Vercel this folder will automatically be deployed. Ensure your build +command is set to build SherpaJS with the Vercel bundler. + + +
+ + +### Local Server +Building to local server will generate a NodeJS server, that utilizes the built +in HTTP service. This server will be located at the `.sherpa/index.js` relative +to your output. You can start the server using +[`sherpa start`](/api/cli#start-command). From 74bc2e54bf3c4f434c57594bd3c6475071494483 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Fri, 17 May 2024 10:59:01 -0400 Subject: [PATCH 24/32] Updated Documentation --- docs.json | 6 +- docs/build/building-a-module.mdx | 1 + docs/build/endpoints.mdx | 222 ++++++++++++++++++++++++++++++- docs/build/miscellaneous.mdx | 1 + docs/build/routing.mdx | 4 +- docs/structure.mdx | 6 +- 6 files changed, 231 insertions(+), 9 deletions(-) create mode 100644 docs/build/building-a-module.mdx create mode 100644 docs/build/miscellaneous.mdx diff --git a/docs.json b/docs.json index cc385d6..710aa4e 100644 --- a/docs.json +++ b/docs.json @@ -13,10 +13,12 @@ "Building Your Application", [ ["Routing", "/build/routing"], - ["Endpoints - WIP", "/build/endpoints"], + ["Endpoints", "/build/endpoints"], ["Static Assets - WIP", "/build/static-assets"], ["Server Config", "/build/server-config"], - ["Module Config", "/build/module-config"] + ["Module Config", "/build/module-config"], + ["Building a Module - WIP", "/build/building-a-module"], + ["Miscellaneous - WIP", "/build/miscellaneous"] ] ], [ "API Reference", diff --git a/docs/build/building-a-module.mdx b/docs/build/building-a-module.mdx new file mode 100644 index 0000000..a2ff562 --- /dev/null +++ b/docs/build/building-a-module.mdx @@ -0,0 +1 @@ +# Building a Module \ No newline at end of file diff --git a/docs/build/endpoints.mdx b/docs/build/endpoints.mdx index 6e5e504..993c515 100644 --- a/docs/build/endpoints.mdx +++ b/docs/build/endpoints.mdx @@ -1,7 +1,223 @@ # Endpoints +Endpoints represent the individual points of access within your microservice +architecture, allowing clients to interact with specific functionalities or +resources. Endpoints are defined within route files (`index.ts`, `module.ts`, +and `view.html`). -## Functions Endpoint -## View Endpoint +
+ + +## Function Endpoints +Function endpoints are defined using a `index.ts` file. Each endpoint is +defined within a route file using the corresponding HTTP +method (`GET`, `POST`, `PATCH`, `PUT`, `DELETE`) function. These functions provide +access to the incoming request and the environment, allowing developers +to customize the endpoint's behavior based on the request data and the +server environment. + + +
+ + +### Defining Function Endpoints +Endpoint functions receive two parameters: +1. [`request`](/api/components/request) - Contains the HTTP request information. +2. `context` - Additional properties provided to configure the endpoint. The + context is either provided by the server configuration + (if it's the root route) or the module loader (if it's a module route). + +A response should be returned by the function, using the +[SherpaJS Response utility](/api/components/response). + + +#### Supported HTTP methods + * [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) + * [POST](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) + * [PATCH](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) + * [PUT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) + * [DELETE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) + + +
+ + +### Example Function Endpoint +```typescript title="/routes/index.ts" +import { Request, Context, Response } from "sherpa-core"; + +// Example GET endpoint +export function GET(request: Request, context: Context) { + return Response.text("Hello World"); +} + +// Example POST endpoint +export function POST(request: Request, context: Context) { + return Response.text("Example POST", { status: 201 }); +} + +// Example DELETE endpoint +export function DELETE(request: Request, context: Context) { + return Response.JSON({ message: "DELETE request received" }, { status: 204 }); +} +``` + + +
+ + +## View Endpoints +Endpoints can also render views, including HTML files. To render a view, +simply place the view file (named `view.html`) in the endpoint directory. + + +
+ + +### Defining Function Endpoints +Simply create a view endpoint by creating a `view.html` in an endpoint +directory. You can use view endpoints along with function endpoints, but there +are a couple of additional rules: + +1. When rendering a view, you cannot also have a GET method in your function endpoint. +2. Function endpoints are not required when a view is provided. +3. View endpoints do not support module endpoints. + + +
+ + +### Example View Endpoint +```html title="/routes/about/view.html" + + + + + + Welcome to SherpaJS + + +

Welcome to SherpaJS

+

This is an example HTML view rendered by SherpaJS.

+

Use this template to create your own custom views and endpoints.

+

© 2024 SherpaJS. All rights reserved.

+ + +``` + + +
+ + +## Module Endpoints +SherpaJS allows endpoint modules to be loaded, which are sets of endpoints built +by the [community](/#community-modules) or [yourself](/build/building-a-module). +By integrating these prebuilt modules, which can range from authentication to +analytics, you can easily extend your server's functionality without +duplicating code. These modules are loaded with a `module.ts` endpoint file. + + +
+ + +### Defining Module Endpoints +Modules are loaded in the same endpoint file (`module.ts`) as a regular +endpoint. Instead of exporting HTTP methods, you export a loaded module. +Simply import the module and use the load method, while providing the context. + + + Additional segment routes or endpoints are not allowed where module + endpoints are defined. + + + +
+ + +### Example Module Loading +The module entry point can either be a relative directory +(in which case you must specify the `sherpa.module.ts` file)... + +```typescript title="/routes/example/module.ts" +import ExampleModule from "../../modules/sherpa.module"; + +export default ExampleModule.load({ + test: "Hello World" +}); +``` + +or an NPM package name... + +```typescript title="/routes/flags/module.ts" +// module.ts +import StaticFlags from "sherpajs-static-flags"; + +export default StaticFlags.load({ + test: "Hello World" +}); +``` + + + Module interfaces or context can be access from other places within your + code, using [interface calling](/build/module-config#module-interface-call-example). + + + +
+ + +## Example Routing + +### Basic Route Structure +```plaintext +/routes +│ +├── /users +│ └── index.ts // Function endpoint for "/users" +│ +├── /posts +│ └── index.ts // Function endpoint for "/posts" +│ +├── /auth +│ └── index.ts // Function endpoint for "/auth" +``` + + +
+ + +### Nested and Dynamic Routes +```plaintext +/routes +│ +├── /example +│ ├── index.ts // Function endpoint for "/example" +│ ├── /subroute +│ │ └── index.ts // Function endpoint for "/example/subroute" +│ +├── /[id] +│ └── index.ts // Function endpoint for "/[id]" access "[id]" with request.params.path.get("id") +│ +├── /products +│ ├── index.ts // Function endpoint for "/products" +│ ├── /[productID] +│ │ └── index.ts // Function endpoint for "/products/[productID]" access "[productID]" with request.params.path.get("productID") +│ └── /category +│ └── index.ts // Function endpoint for "/products/category" +``` + + +
+ + +### View and Module Endpoints +```plaintext +/routes +│ +├── /home +│ └── view.html // View endpoint for "/home" +│ +├── /dashboard +│ └── module.ts // Module endpoint for "/dashboard" +``` -## Module Endpoint \ No newline at end of file diff --git a/docs/build/miscellaneous.mdx b/docs/build/miscellaneous.mdx new file mode 100644 index 0000000..687fb2f --- /dev/null +++ b/docs/build/miscellaneous.mdx @@ -0,0 +1 @@ +# Miscellaneous \ No newline at end of file diff --git a/docs/build/routing.mdx b/docs/build/routing.mdx index 1233e4f..e39327b 100644 --- a/docs/build/routing.mdx +++ b/docs/build/routing.mdx @@ -149,7 +149,9 @@ violate any of these restrictions. * Multiple [dynamic segement routes](/build/routing#dynamic-segment-route) are not allowed in a single segement route. * Additional segment routes or endpoints are not allowed as the segment where - a [Module Endpoint](/build/endpoints#module-endpoint) is loaded. + a [Module Endpoint](/build/endpoints#module-endpoints) is loaded. + * [Function Endpoints](/build/endpoints#function-endpoints) cannot have a + GET method when paired with a [View Endpoint](/build/endpoints#view-endpoints).
diff --git a/docs/structure.mdx b/docs/structure.mdx index 3136103..d09de7b 100644 --- a/docs/structure.mdx +++ b/docs/structure.mdx @@ -41,8 +41,8 @@ endpoints may persist together, but no other files should be present in your | | | | |---|---|---| -| [`index`](/build/endpoints#functions-endpoint) | `.ts` `.js` | Functions endpoint | -| [`module`](/build/endpoints#module-endpoint) | `.ts` `.js` | Module endpoint | -| [`view`](/build/endpoints#endpoint-view) | `.html` | View endpoint | +| [`index`](/build/endpoints#function-endpoints) | `.ts` `.js` | Functions endpoint | +| [`module`](/build/endpoints#module-endpoints) | `.ts` `.js` | Module endpoint | +| [`view`](/build/endpoints#view-endpoints) | `.html` | View endpoint | | [`/folder_name`](/build/routes#regular-route) | | Regular route segment, *any folder_name* | | [`/[param_name]`](/build/routes#dynamic-route) | | Dynamic route segment, *any param_name* | From 3c4b6795aeab62c7a600b0896af26426e9e3477f Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Fri, 17 May 2024 11:13:57 -0400 Subject: [PATCH 25/32] Updated Documentation --- docs.json | 2 +- docs/build/static-assets.mdx | 97 +++++++++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/docs.json b/docs.json index 710aa4e..fa6d2fc 100644 --- a/docs.json +++ b/docs.json @@ -14,7 +14,7 @@ [ ["Routing", "/build/routing"], ["Endpoints", "/build/endpoints"], - ["Static Assets - WIP", "/build/static-assets"], + ["Static Assets", "/build/static-assets"], ["Server Config", "/build/server-config"], ["Module Config", "/build/module-config"], ["Building a Module - WIP", "/build/building-a-module"], diff --git a/docs/build/static-assets.mdx b/docs/build/static-assets.mdx index cb41e9e..ce69756 100644 --- a/docs/build/static-assets.mdx +++ b/docs/build/static-assets.mdx @@ -1 +1,96 @@ -# Static Assets \ No newline at end of file +# Static Assets +SherpaJS servers can serve static assets such as images, CSS, JavaScript +files, and other resources that do not change frequently. These assets are +placed in a dedicated folder within your project and are served directly to +clients when requested. + +This static asset directory is optional. Static assets are not transferred from +modules. + + +
+ + +## Defining Static Assets Directory +The default directory for static assets in a SherpaJS project is the `public` +folder. Any files placed in this folder are accessible via a URL path that +mirrors the directory structure within `public`. + + +
+ + +## Serving Static Assets +To serve static assets, simply place the files within the `public` +directory of your project. For example: + +```plaintext +/your-project +│ +├── /public +│ ├── /images +│ │ └── logo.png +│ ├── /css +│ │ └── styles.css +│ └── /js +│ └── script.js +│ +├── /routes +│ └── view.html +└── sherpa.server.ts +``` + +In this structure: + * `logo.png` will be accessible at `/images/logo.png` + * `styles.css` will be accessible at `/css/styles.css` + * `script.js` will be accessible at `/js/script.js` + * `view.html` will be accessible at `/` + + +
+ + +## Examples + + +### View Endpoints Example +If you want to reference these static assets in your view endpoint or other +files, use the appropriate URL path. For example, in an HTML file: + +```html title="/routes/view.html" + + + + + + My SherpaJS App + + + +
+ Logo +
+
+

Welcome to My SherpaJS App

+

This is a simple example of serving static assets.

+ +
+ + +``` + + +
+ + +## Security Considerations + * **Access Control** - Ensure that sensitive files are not placed in the + `public` directory as they will be publicly accessible. + + +
+ + +By organizing your static assets efficiently and using SherpaJS's built-in +capabilities, you can serve these resources effectively to enhance the +performance and usability of your web applications. \ No newline at end of file From 31f4556d8966a0d959baa57994459936547d9004 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Fri, 17 May 2024 11:18:07 -0400 Subject: [PATCH 26/32] Updated Docs --- docs/build/routing.mdx | 3 +++ docs/installation.mdx | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/build/routing.mdx b/docs/build/routing.mdx index e39327b..b15a6de 100644 --- a/docs/build/routing.mdx +++ b/docs/build/routing.mdx @@ -5,6 +5,9 @@ by Next.js, SherpaJS routes follow a directory-based structure located in the `/routes` directory of your module. +
+ + ## Terminology ### Route Component Tree diff --git a/docs/installation.mdx b/docs/installation.mdx index eeb41f6..86bc430 100644 --- a/docs/installation.mdx +++ b/docs/installation.mdx @@ -99,7 +99,8 @@ Learn more about [routing](/build/rounting) and [endpoints](/build/endpoints).
-### Creating Public Assets (Optional) +### Creating Static Assets (Optional) Create a `/public` directory in the root directory of your project to store static assets such as images, stylings and more. +Learn more about [static assets](/build/static-assets). From 52a5b68590a2d5c445b7de8adb3da6c7bf978ef8 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Fri, 17 May 2024 13:32:59 -0400 Subject: [PATCH 27/32] Updated Docs --- docs.json | 2 +- docs/api/components/parameters.mdx | 5 +++ docs/build/miscellaneous.mdx | 61 +++++++++++++++++++++++++++++- docs/structure.mdx | 1 + 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/docs.json b/docs.json index fa6d2fc..02d4bf5 100644 --- a/docs.json +++ b/docs.json @@ -18,7 +18,7 @@ ["Server Config", "/build/server-config"], ["Module Config", "/build/module-config"], ["Building a Module - WIP", "/build/building-a-module"], - ["Miscellaneous - WIP", "/build/miscellaneous"] + ["Miscellaneous", "/build/miscellaneous"] ] ], [ "API Reference", diff --git a/docs/api/components/parameters.mdx b/docs/api/components/parameters.mdx index 28489ff..41ee115 100644 --- a/docs/api/components/parameters.mdx +++ b/docs/api/components/parameters.mdx @@ -6,6 +6,11 @@ includes numbers and booleans. This class is very similar to the standard [URLSearchParams class](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) used in web APIs. +When parameters come from the [`Request`](/api/components/request) class, from a +URL they are automatically parsed (booleans and numbers) and seperated by commas. +See [request examples](/api/components/request#basic-get-request), for more +information. +
diff --git a/docs/build/miscellaneous.mdx b/docs/build/miscellaneous.mdx index 687fb2f..b5a8f77 100644 --- a/docs/build/miscellaneous.mdx +++ b/docs/build/miscellaneous.mdx @@ -1 +1,60 @@ -# Miscellaneous \ No newline at end of file +# Miscellaneous + + +## Environment Variables +Environment variables are a key part of configuring your SherpaJS application. +They allow you to set various configuration options and secrets without +hardcoding them into your application's codebase. + + +
+ + +### Loading Environment Variables +SherpaJS uses the `.env` file to load environment variables. This file should +be placed at the root of your project. When the system is compiled, the +variables defined in this file are automatically loaded into your server's +environment. + +Any environment variables provided by hosting services (such as Vercel or AWS) +are automatically included in your build. + +Environment varibles can also be added during build with the +[build command](/api/cli#build-command). + + +
+ + +### Automatic Parsing +SherpaJS automatically parses environment variables to their appropriate types: +- Strings remain as strings +- Booleans are converted to `true` or `false` +- Numbers are converted to numeric values + + +
+ + +### Example .env File +Here is an example of a `.env` file: + +```shell title=".env" +PORT=3000 # number +DATABASE_URL=mongodb://localhost:27017/mydatabase # string +JWT_SECRET=myverysecretkey # string +ENABLE_FEATURE_X=true # boolean +MAX_CONNECTIONS=100 # number +``` + +
+ + +### Best Practices +- **Security**: Never commit your `.env` file to version control. Add it + to your `.gitignore` file. +- **Defaults**: Provide sensible default values for environment variables + in your code. +- **Validation**: Validate the presence and format of critical environment + variables at the start of your application to avoid runtime errors. + diff --git a/docs/structure.mdx b/docs/structure.mdx index d09de7b..c655a11 100644 --- a/docs/structure.mdx +++ b/docs/structure.mdx @@ -27,6 +27,7 @@ Top-level files are used to configure SherpaJS and manage the environment. |---|---| | [`sherpa.server.ts`](/build/server-config) | SherpaJS server config | | [`sherpa.module.ts`](/build/module-config) | SherpaJS module config, *optional only if creating a module* | +| [`.env`](/build/miscellaneous#environment-variables) | Environment Varibles File | From 1d332db58e1071a3162b49bb766252c6339ce0e3 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Mon, 20 May 2024 16:37:20 -0400 Subject: [PATCH 28/32] Updated Docs --- README.md | 2 +- docs.json | 5 +- docs/assets/logos/logo-dark.png | Bin 64410 -> 31814 bytes docs/assets/logos/logo-large-dark.png | Bin 0 -> 64410 bytes docs/assets/logos/logo-large-light.png | Bin 0 -> 60920 bytes docs/assets/logos/logo-light.png | Bin 60920 -> 30290 bytes docs/build/building-a-module.mdx | 147 ++++++++++++++++++++++++- docs/index.mdx | 2 +- docs/installation.mdx | 3 +- 9 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 docs/assets/logos/logo-large-dark.png create mode 100644 docs/assets/logos/logo-large-light.png diff --git a/README.md b/README.md index dfafb0d..a46cdbc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![](./docs/assets/logos/logo-dark.png) +![](./docs/assets/logos/logo-large-dark.png) # SherpaJS - Serverless Web Framework ![NPM Version](https://img.shields.io/npm/v/sherpa-core) diff --git a/docs.json b/docs.json index 02d4bf5..95bbb4e 100644 --- a/docs.json +++ b/docs.json @@ -2,6 +2,9 @@ "name": "SherpaJS", "description": "Module and Reusable Microservice Platform. Build and modularize custom API endpoints, inspired by NextJS APIs. Export to Vercel and ExpressJS.", "headerDepth": 5, + "logo": "./assets/logo-light.png", + "logoDark": "./assets/logo-dark.png", + "theme": "#0D95DC", "sidebar": [[ "Getting Started", [ @@ -17,7 +20,7 @@ ["Static Assets", "/build/static-assets"], ["Server Config", "/build/server-config"], ["Module Config", "/build/module-config"], - ["Building a Module - WIP", "/build/building-a-module"], + ["Building a Module", "/build/building-a-module"], ["Miscellaneous", "/build/miscellaneous"] ] ], [ diff --git a/docs/assets/logos/logo-dark.png b/docs/assets/logos/logo-dark.png index 4f201cc0d3d053ce54a8849a22771be0d795cd6d..cc6f1ad6ce30e0f0d2b7b5501a1f334963072f98 100644 GIT binary patch literal 31814 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 literal 64410 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 diff --git a/docs/assets/logos/logo-large-dark.png b/docs/assets/logos/logo-large-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..4f201cc0d3d053ce54a8849a22771be0d795cd6d GIT binary patch literal 64410 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 literal 0 HcmV?d00001 diff --git a/docs/assets/logos/logo-large-light.png b/docs/assets/logos/logo-large-light.png new file mode 100644 index 0000000000000000000000000000000000000000..a6bbf5ce81bccced878c9b2c1be7cc8fb3fd382d GIT binary patch literal 60920 zcmeFYbyQSQ*FQcpbR*p!U)pcFoLwSgdhx^0s=$V z@8bKs-}U_c`}@6Xv1Z*n%suDqv(Jvt{_JQSEfoS>8e9+vM4+ass0RXJVt_#4I&4hf z35mp`F5m;lOV!jH1i~Y|{{w?Ev#EfGU~fGYc~Hd&-8OK8?kJ}z2Le^c<6YYVKi`W} zQ{A(Ik^&*}_50gKMO+8R3 z^P%d>RGhLO($O$yz}g|_$Hzz74pZ%oT->EQ$KV=nZscf72J+zICPspom_g{cd8*+bvJqFz2 zkid1vy6MDaAC;I>73!e zhxgq?bHV-1{$KxBwg21J?fri}K+Fk}{MYR)Hb1ag|L+n(*ZA-E5rFmo-&erm6%b_q zbvsM^e?R>v4%q*R=|5`me=6}GLHwUe{I8+-Kb83Zr4nK8fE|X#Eysy2_P0=42Uh>_ zvuN?*yb2oPY3v^sMOqMc?lsI0YR?e;dp$q*{z7*!8oF(gBQn}LubS@OwJ5j5|JJ8TVFatw_2lUF+sI$OIx?~`nq{7 zOPF8LokgQP%_Io1Q9!h?zii&hT)?N~f*<%dl<|kgJ6|aO%*{lqPRv?{W6m$CkM}Ol zCWmTLd$PrQbHqK2xV+$wR9iApSltYc!%uL=P{0nx1j~{FBZVAdwMGXXO_+2vIj+Y= zr>F(QbnpnH@3*{uD07?Y?mx7xOQ9+I9T+&D==U5Kv|m}4@=~XQXYs`Q)Bm_fD&BO+ zBNe0q>ZZFrri_N>>EC6d;5X&8Twpr#`=uO4&k(H(dTOn~>txhChd(K>fuQ(&qLoXX4&L(D|KoQf@ZgBUmvKo9 z{%eWfl+o!@h@e{vM@ykZ&j}H|3KS$TwvS}FxmpAv$R?pw2^FJ`d6Q;d!<$OYR@%vZ z9%nzUz1ugBkC0Gz5)P!Y7{$u7wZVG7( zXcTb4)|Y?4G>L!QK-ZTjh_d?&EMWh|FVH;M6qiu>(nRt#O{V+9U= zi~f&@*8Yv+t@s%Y^)ySq^`(WGu{#2zs=@{rgwoIp3|gsIxERduKXZ2m+a@kN6vY&B zA1h2B3CMlVDSgswh_-x^m>7K3YjS(Di&gjlV!~{&HXZp_g~4AjFKaV5So$r~jP}1F z#H1^1NyfpG<9;IU2qn~$GHyUlQY#afpOByW`3j%knosh1l50}FsKpMsd05G+^NjYP ze;sV{O2rvjY%;y>vy}BYF>qzKwI*vs6_D2Q=W;Eln;@a=X!)RjBfwUdCosnOx1F3& zH8h-{T}(JgHol2=Ker>01FN_HEcQJOxFL#!IF6)v0y8`U_KbNgwWuD8w`k~MT5)Zl za?hcgrvfl@y1M3!-GL(mgPiDo*uJgFv;*_+XY4?TBg0yb#JV(tF9|(cBnuO?Nir_S;pKczLe1YUJRm znqM(CnL!#=v-OU~_Z{HdB#}3#mTQ!%`E}Lj>Fb zI+`O`^^wY7a8D+U_m3d5e-irv4`2_3?1>`~*W)Wrb7ucM2q@DA`!OaIE58?1h6YR> zkDXIG_-w-DcIH#`@8qu+2O<~4ekO`IFW@kPL`Z!mM6Z%mM;Ui^2h&J!SxFB8F{{}`NEEkYf*EjJ6tRY3z`=fx5d$Hx$ zwZ=sDkH~jA1#g1Ni@^zB@CRe?Hj$ReFh%Jbz6?&ABW*`Ir$EGd-8^mFn%$-!Iw&

V*q{H?* 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

V*q{H?* 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 + + +## Quick Installation +We recommend starting with the +[SherpaJS Module Template](https://github.com/sellersindustry/SherpaJS-template-module), +which provides a pre-configured structure and example endpoints. After +downloading the template, install all dependencies by running: + +```sh +npm install +``` + +You can start the development server with `npm run dev`. + +Now your project is all setup, explore around the project files and get +acquainted with the [SherpaJS Project Structure](/structure) and +[SherpaJS CLI](/api/cli). + + +
+ + +## Manual Installation +Creating a new module is extremely easy and can be done within a couple of +minutes. To manually create a new module start by create a new NodeJS project +with `npm init`. Then install the SherpaJS Core package: + +```sh +npm install sherpa-core +``` + + +
+ + + +### Updating `package.json` +Open the `package.json` file in the root directory of your project, and +update the following properties. + +```json title="package.json" +{ + "type": "module", + "exports": "./sherpa.module.ts", + "scripts": { + "build": "sherpa build -b Vercel", + "build-local": "sherpa build -b local", + "start": "sherpa start", + "dev": "npm run build-local && npm run start" + } +} +``` + + +
+ +### Creating Module Config +Create a [module config](/build/module-config) file named `sherpa.module.ts` in +the root directory of your module. This file will default export a module +configuration. + +```typescript title="sherpa.module.ts" +import { SherpaJS, CreateModuleInterface } from "sherpa-core"; + +export type Schema = { foo: boolean, bar: string }; + +export default SherpaJS.New.module({ + name: "example-module", + interface: CreateModuleInterface() +}); +``` + +[Learn more about module configs](/build/module-config). + + +
+ + +### Creating Server Config +Create a new Typescript file for your [server configuration](/build/server-config) +in the root directory of your project named `sherpa.server.ts`. *Technically a +server config is not required to create a module, but it is to test the module*. + +```typescript title="sherpa.server.ts" +import { SherpaJS } from "sherpa-core"; +import { Schema } from "../sherpa.module.ts"; + +export default SherpaJS.New.server({ + context: { + example: "foo" + } +}); +``` + +The context you provide the server should match the context schema for your module. + + +### Creating Endpoints +SherpaJS uses a directory-based structure for routing, similar to NextJS. Start +by creating a `/routes` directory and place a new enpoint `index.ts` file in the +directory. This will be processed at the root `/` of your application. + +```typescript title="routes/index.ts" +import { Request, Response } from "sherpa-core"; +import { Schema } from "../sherpa.module.ts" + +export function GET(request:Request, context:Schema) { + return Response.text("Hello World!"); +} +``` + +Learn more about [routing](/build/rounting) and [endpoints](/build/endpoints). + + +
+ + +### Details +While the routes of your module are available on a server when the module is +loaded, other assets like the `public` directory are not available. Keep this +in mind when designing your module. + + +
+ + +### Share Your Module +Share your module with the world by deploying it as an NPM package and +submitting a +[new issue](https://github.com/sellersindustry/SherpaJS/issues/new/choose) +to get it listed as a SherpaJS Community module. + +**Important Notes** + * Ensure your module is deployed as an NPM package. + * Include documentation on how to set it up, including required properties. + * Link to the SherpaJS documentation for users to understand how to set it up. + +Thank you for supporting SherpaJS! 🎉🥳 + diff --git a/docs/index.mdx b/docs/index.mdx index 4273c86..feea73b 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -3,7 +3,7 @@ title: Overview description: Instant Open Source docs with zero configuration. --- -![SherpaJS Logo](/assets/logos/logo-dark.png) +![SherpaJS Logo](/assets/logos/logo-large-dark.png) ## What is SherpaJS? SherpaJS is a **modular and agnostic serverless JavaScript web framework,** that diff --git a/docs/installation.mdx b/docs/installation.mdx index 86bc430..52d2b11 100644 --- a/docs/installation.mdx +++ b/docs/installation.mdx @@ -49,6 +49,7 @@ the following properties. ```json title="package.json" { + "type": "module", "scripts": { "build": "sherpa build -b Vercel", "build-local": "sherpa build -b local", @@ -85,7 +86,7 @@ SherpaJS uses a directory-based structure for routing, similar to NextJS. Start by creating a `/routes` directory and place a new enpoint `index.ts` file in the directory. This will be processed at the root `/` of your application. -```typescript title="index.ts" +```typescript title="/routes/index.ts" import { Request, Response, Context } from "sherpa-core"; export function GET(request:Request, context:Context) { From 02cdb843e5345cef3118d558947fbd1914f2a462 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Mon, 20 May 2024 16:38:39 -0400 Subject: [PATCH 29/32] Update docs.json --- docs.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs.json b/docs.json index 95bbb4e..7d67849 100644 --- a/docs.json +++ b/docs.json @@ -2,8 +2,8 @@ "name": "SherpaJS", "description": "Module and Reusable Microservice Platform. Build and modularize custom API endpoints, inspired by NextJS APIs. Export to Vercel and ExpressJS.", "headerDepth": 5, - "logo": "./assets/logo-light.png", - "logoDark": "./assets/logo-dark.png", + "logo": "./assets/logos/logo-light.png", + "logoDark": "./assets/logos/logo-dark.png", "theme": "#0D95DC", "sidebar": [[ "Getting Started", From 0fcd26386411cf3a0f009e12e2d1bb46d06ae28a Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Mon, 20 May 2024 16:39:33 -0400 Subject: [PATCH 30/32] Added "Favicon" --- docs.json | 4 ++-- docs/assets/logos/favicon.png | Bin 0 -> 16323 bytes 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 docs/assets/logos/favicon.png diff --git a/docs.json b/docs.json index 7d67849..663b63f 100644 --- a/docs.json +++ b/docs.json @@ -2,8 +2,8 @@ "name": "SherpaJS", "description": "Module and Reusable Microservice Platform. Build and modularize custom API endpoints, inspired by NextJS APIs. Export to Vercel and ExpressJS.", "headerDepth": 5, - "logo": "./assets/logos/logo-light.png", - "logoDark": "./assets/logos/logo-dark.png", + "logo": "./assets/logos/favicon.png", + "logoDark": "./assets/logos/favicon.png", "theme": "#0D95DC", "sidebar": [[ "Getting Started", diff --git a/docs/assets/logos/favicon.png b/docs/assets/logos/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..71efe8c7b399f1085298400a4dfa73584e4b7c1d GIT binary patch literal 16323 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 Date: Mon, 20 May 2024 16:53:02 -0400 Subject: [PATCH 31/32] Update README.md --- README.md | 820 +----------------------------------------------------- 1 file changed, 15 insertions(+), 805 deletions(-) diff --git a/README.md b/README.md index a46cdbc..575fe25 100644 --- a/README.md +++ b/README.md @@ -1,827 +1,37 @@ -![](./docs/assets/logos/logo-large-dark.png) -# SherpaJS - Serverless Web Framework -![NPM Version](https://img.shields.io/npm/v/sherpa-core) -[![Testing](https://github.com/sellersindustry/SherpaJS/actions/workflows/testing.yml/badge.svg)](https://github.com/sellersindustry/SherpaJS/actions/workflows/testing.yml) -> [!TIP] -> **The documenation is a bit of a mess right now, to get an overview really quick just checkout the [server example](https://github.com/sellersindustry/SherpaJS-template-server).** -> [!IMPORTANT] -> This project is in early development, so it is possible for you to run into issues. If you run into any issues please just create a new issue and link your code. Feel free to debug or update the code! -> -> - If you have an issue, [let us know](https://github.com/sellersindustry/SherpaJS/issues), even if you fix it. It could help us build a better linter. -> - If the documentation is confusing some place, [ask](https://github.com/sellersindustry/SherpaJS/issues). Also feel free to make a pull request with the updates. -> - Have a suggested change or feature? [Submit a Ticket](https://github.com/sellersindustry/SherpaJS/issues) -> - Need a module that isn't built? Please help us build the SherpaJS Community and built it following our [build guide](#create-a-module), then [submit your module to the community](https://github.com/sellersindustry/SherpaJS/issues). -> -> [Development Notes](#development) +

+ + +

SherpaJS

+ +

-SherpaJS empowers developers to effortlessly construct **modular and agnostic serverless applications**. Developers can easily build serverless web server using a directory-based structure, inspired by NextJS and even import pre-built modules at endpoints. SherpaJS servers can then be compiled to a variety of different web platforms including Vercel Serverless and local Server (with more to come later). +

+ + +

-
- - -## Table of Contents - - [Supported Platforms](#deploy-a-server) - - [Community Modules](#community-modules) - - [Installation](#installation) - - [Commands](#commands) - - [Servers](#servers) - - [Create a Server](#creating-a-server) - - [Configuration](#server-configuration) - - [Deploy a Server](#deploy-a-server) - - Routing - - [Routes](#routes) - - [Endpoints](#endpoints) - - [Static Assets](#static-assets) - - [Modules](#modules) - - [Create a Module](#creating-a-module) - - [Configuration](#module-configuration) - - [Development & Contributing](#development) - - -
-
- - -## Community Modules -| Module | Description | -|---|---| -| [Static Flags](https://github.com/sellersindustry/SherpaJS-static-flags) | Create static flags of booleans, strings, or numbers | -| [Events](https://github.com/sellersindustry/SherpaJS-events) | Create event sending endpoints for analytics platforms like PostHog using [Metadapter Events](https://github.com/sellersindustry/metadapter-event) | - -
-
- - -## Installation -To install SherpaJS, simply run the following command in your terminal: -```bash -npm install sherpa-core -g -``` -This command will globally install the SherpaJS core package, enabling you to utilize its features across your system. Once installed, you can easily run the SherpaJS command-line interface (CLI) using the following command: -```bash -sherpa -npx sherpa -``` -This command initializes the SherpaJS CLI, allowing you to efficiently manage and configure your modular microservice endpoints. [Learn about CLI Commands](#commands). - - -
-
- - -## Commands -CLI for SherpaJS - Modular Microservices Framework - -```bash -sherpa [options] [command] -``` - -#### Options: - - `-V`, `--version` output the version number - - `-h`, `--help` display help for command - -#### Commands: - - `build [options]` Build SherpaJS Server - - `clean [options]` Remove SherpaJS Build Directories - - `help [command]` display help for command - - -
- - -### Build Command -Build SherpaJS Server. -```bash -sherpa build [options] -``` - -#### Options: - - `-i`, `--input ` path to SherpaJS server, defaults to current directory - - `-o`, `--output ` path to server output, defaults to input directory - - `-b`, `--bundler ` platform bundler ("**Vercel**", "*local**", *default: "local"*) - - `-v`, `--variable [key values...]` Specify optional environment variables as key=value pairs Ex. `foo=bar test="1234 HI"` - - `--dev` enable development mode, does not minify output - - `-h`, `--help` display help for command - - -
- - -### Start Command -Start SherpaJS Server Locally. Ensure you have created a [local build](#build-command). -```bash -sherpa start [options] -``` - -#### Options: - - `-i`, `--input ` path to SherpaJS server, defaults to current directory - - `-p`, `--port ` port number (default: "3000") - - `-h`, `--help` display help for command - - -
- - -### Clean Command -Remove SherpaJS Build Directories. -```bash -sherpa clean [options] -``` - -#### Options: - - `-i`, `--input ` path to SherpaJS build directories, defaults to current directory - - `-h`, `--help` display help for command - - -
-
- - -## Servers -A SherpaJS server is a backend web server framework, akin to Flask, primarily -designed for creating serverless applications, offering developers a -lightweight and modular approach to building scalable backend services in JavaScript. - -### Creating a Server -Creating a new server is extremely easy and can be done within a couple of -minutes. Check out the [SherpaJS Server Template](https://github.com/sellersindustry/SherpaJS-template-server) -for an example of how to build your server. - -#### Step 1 -Setup a new NodeJS project with `npm init`. - -#### Step 2 -Install SherpaJS with `npm install sherpa-core`. - -#### Step 3 -Create a new server configuration file in the root directory of your server name `sherpa.server.ts`. This file will default export a [server configuration](#server-configuration). - -```typescript -// sherpa.server.ts -import { SherpaJS } from "sherpa-core"; - -export default SherpaJS.New.server({ - context: { // contexts are provided to endpoints, and are optional - example: "foo" - } -}); -``` - -#### Step 4 -Create an your endpoints in the `/routes` directory. See an example below or [learn about endpoints](#endpoints). - -```typescript -// ./routes/index.ts -import { Request, Response, Context } from "sherpa-core"; - -export function GET(request:Request, context:Context) { - return Response.text("Hello World!"); -} -``` - -> [!NOTE] -> It's here where you can load pre-build SherpaJS modules and provide them with context. -> [Loading Modules](#module-endpoint) - - -#### Step 6 -Build the local server with `sherpa build` [command](#build-command). This -will create a NodeJS file at `./.sherpa/index.js` which you can start at using -`node ./.sherpa/index.js` see [local server platform](#local-server) for additional information. - -That's it! You're now ready to start building powerful serverless web -applications with SherpaJS. Happy coding! ⚓ - - -
- - -### Server Configuration -Sherpa servers are configured using a `sherpa.server.ts` file, where you define -the structure and behavior of your server. This configuration file serves as -the entry point for your Sherpa server. - - -#### Config File -The file must located at `sherpa.server.ts` and have a default export of the -config and use the `SherpaJS.New.server` function as follows: -```typescript -import SherpaJS from "sherpa-core"; - -export default SherpaJS.New.server(); -``` - -#### Config Structure - - **Context:** An optional property that allows you to define a context - object. Contexts are provided to endpoints and can contain any - additional data or settings needed for request processing. - -The configuration provided to the server must match the TypeScript object as follows: -```typescript -export type Context = unknown; - -export type ServerConfig = { - context: Schema; -}; -``` - -#### Example Config -```typescript -// sherpa.server.ts -import { SherpaJS } from "sherpa-core"; - -export default SherpaJS.New.server({ - context: { - serverSecret: "foo", - allowThingy: true - } -}); -``` - -```typescript -// sherpa.server.ts -import { SherpaJS } from "sherpa-core"; - -type ConfigExample = { serverSecret:string, allowThingy:boolean }; -export default SherpaJS.New.server({ - context: { - serverSecret: "foo", - allowThingy: true - } -}); -``` - -
- - -### Environment Variables -The `.env` environment file is loaded into your server when the system is -compiled. Any environment variables provided by hosting services (like Vercel) -will also automatically be included in your build. - - -
- - - -### Deploy a Server -SherpaJS can compile to various different web platforms, with more to come -later. [Want to support a new framework? Submit a Ticket](https://github.com/sellersindustry/SherpaJS/issues). -See the [build command](#build-command) to compile to each platform. - - -#### Vercel Serverless -Building to Vercel will generate a Vercel serverless server in the `.vercel` -directory relative to your output. When your SherpaJS server repository is -deployed Vercel this folder will automatically be deployed. Ensure your build -command is set to build SherpaJS with the Vercel bundler. - - -#### Local Server -Building to local server will generate a NodeJS server, that utilizes the built -in HTTP service. This server will be located at the `.sherpa/index.js` relative -to your output. By default the port number is `3000` but you can provide an -different port number with an argument `node ./.sherpa/index.js 5000`. - - -
-
- - -## Routes -Routes in SherpaJS provide a flexible and intuitive way to define -[endpoints](#endpoints) and handle incoming requests within your microservice -architecture. Drawing inspiration from Next.js, SherpaJS routes follow a -directory-based structure located in the `/routes` directory of your module. - - -### Structure of Routes -In the `/routes` directory, you can create additional directories to organize -your routes. For instance, you might have a directory like `/example`, which -contains specific endpoints related to a particular feature or functionality. -Each endpoint within a route is represented by a file named `index.ts`. - -Subroutes are located relative to the modules. For example if an endpoint is -defined in a module at `/example` and the module is loaded at `/app-1/foo` then -the example endpoint will be accessed at `/app-1/foo/example`. - -### Dynamic Routes -To define a dynamic route, simply name a directory using square brackets, such -as `[id]`. Within a dynamic route directory, you can access the parameter value -from the request object in your endpoint logic. For example, if you have a -dynamic route named `[id]`, you can access the parameter using -`request.params.path.get("id")`, to learn more see [endpoint requests](#requests). - -### Examples of Route Structures -```less -/routes -│ -├── /users -│ └── index.ts // Endpoint logic for "/users" -│ -├── /posts -│ └── index.ts // Endpoint logic for "/posts" -│ -├── /auth -│ └── index.ts // Endpoint logic for "/auth" - -``` - -```less -/routes -│ -├── /example -│ ├── index.ts // Endpoint logic for "/example" -│ ├── /subroute -│ └── index.ts // Endpoint logic for "/example/subroute" -│ -├── /[id] -│ └── index.ts // Endpoint logic for "/[id]" access "[id]" with request.params.path.get("id") -``` - -```less -/routes -│ -├── /products -│ ├── index.ts // Endpoint logic for "/products" -│ ├── /[productID] -│ │ └── index.ts // Endpoint logic for "/products/[productID]" access "[productID]" with request.params.path.get("productID") -│ │ -│ └── /category -│ └── index.ts // Endpoint logic for "/products/category" - -``` +--- -
- - -## Endpoints -Endpoints represent the individual points of access within your microservice -architecture, allowing clients to interact with specific functionalities or -resources. Endpoints are defined within route files `index.ts` and are -associated with specific HTTP methods (GET, POST, PATCH, PUT, DELETE) to -perform corresponding actions. - -### Function Endpoint -Each endpoint is defined within a route file using the corresponding -HTTP method function. These functions provide access to the incoming request -and the environment, allowing developers to customize the endpoint's behavior -based on the request data and the server environment. - -Endpoint can be defined by exporting a function with the desired method name. -The following HTTP methods are supported: `GET`, `POST`, `PATCH`, `PUT`, and -`DELETE`. - -Endpoint functions receive two parameters: the [request](#requests) which -contains the HTTP request information and the [context](#context) which is -additional properties provided to configure the endpoint. The context is either -provided by the [server configuration](#server-config), if it's the root route -or the [module loader](#module-endpoint), if it's a module route. - -A response should be returned by the function, using the -[SherpaJS Response utility](#response). - -```typescript -import { Request, Context, Response } from "sherpa-core"; - -// Example GET endpoint -export function GET(request:Request, context:Context) { - return Response.text("Hello World"); -} - -// Example POST endpoint -export function POST(request:Request, env:Environment) { - return Response.text("Example POST", { status: 201 }); -} - -// Example DELETE endpoint -export function DELETE(request:Request, env:Environment) { - return Response.JSON({ message: "DELETE request received" }, { status: 204 }); -} -``` - - -### View Endpoint -Endpoints can also render views, this include HTML _(more to come soon)_ files. -To render a view simply place the view file (named `index.html`) in the -endpoint directory. - -When rendering a view you are not allowed to also have a `GET` method in your -function endpoint. Additionally, function endpoints are not required when a view -is provided. View endpoints do not support module endpoints. - - -### Module Endpoint -SherpaJS allows endpoint modules to be loaded, which is a set of endpoints -built by the [community](#community-modules) or [your self](#creating-a-module). -By integrating these prebuilt modules which can range from authentication to -analytics into your server, you can easily extend your server's -functionality without duplicating code. This promotes code organization, -modularity, and reusability, simplifying development and accelerating -time-to-market for your web applications. - -Modules are loaded in the same endpoint file (`index.ts`) as a regular endpoint, -but instead of export HTTP methods you export a loaded module. Simply import the -module and use the `load` method, while providing the context. - -This entry point can either be a relative directory (in which case you must -specify the `sherpa.module` file) or a NPM package name. - -```typescript -// index.ts -import StaticFlags from "sherpajs-static-flags"; - -export default StaticFlags.load({ - test: "Hello World" -}); -``` - -```typescript -// index.ts -import ExampleModule from "../../modules/sherpa.module"; - -export default ExampleModule.load({ - test: "Hello World" -}); -``` - - -### Requests -The request as a typescript type. Parameters are parsed are parsed as the types -they are provided as and if multiple are provided as an array. - -```typescript -enum BodyType { - JSON = "JSON", - Text = "Text", - None = "None" -} - -type Body = Record|string|undefined; - -interface Request { - readonly url:string; - readonly params:{ path:Parameters, query:Parameters }; - readonly method:keyof typeof Method; - readonly headers:Headers; - readonly body:Body; - readonly bodyType:keyof typeof BodyType; -} -``` - -#### Request Example - - `doc/abc/def/page/2?thing1=foo,bar&thing2=true&thing2=false&thing3=4` - - `doc/[testID]/[testID]/page/[pageID]` - - `request.params.path.get("testID")` ➜ `"abc"` - - `request.params.path.getAll("testID")` ➜ `[ "abc", "def" ]` - - `request.params.path.has("testID")` ➜ `true` - - `request.params.path.keys()` ➜ `[ "testID", "pageID" ]` -```json -{ - "url": "/regular/dynamic-paths/abc/def/page/2", - "params": { - "path": { - "testID": [ "abc", "def" ], - "pageID": [ 2 ] - }, - "query": { - "thing1": [ "foo", "bar" ], - "thing2": [ true, false ], - "thing3": [ 4 ] - } - }, - "method": "POST", - "headers": { - "content-type": "application/json", - }, - "bodyType": "JSON", - "body": { - "test": "hello world" - } -} -``` - - -### Context -The [context](#context) is additional properties provided to configure the -endpoint. The context is either provided by the -[server configuration](#server-config), if it's the root route or the -[module loader](#module-endpoint), if it's a module route. If the module provides -a context schema type, the context provided will be verified during build. - - -### Response -The Response class is used to generate HTTP responses. It provides static -methods to create different types of responses, such as text, JSON, and -redirects. - -#### Blank Response -Creates a new response object with default options. Optional provide object that -specifies custom response options such as headers and status code. - -```typescript -import { Request, Headers } from "sherpa-core"; -Response.new(); -Response.new({ status: 201 }); -Response.new({ status: 201, headers: new Headers() }); -``` - -#### Text Response -Generates a text response with the specified text content. Optional provide -object that specifies custom response options such as headers and status code. - -```typescript -import { Request, Headers } from "sherpa-core"; -Response.text("hello world"); -Response.text("hello world", { status: 201 }); -Response.text("hello world", { status: 201, headers: new Headers() }); -``` - - -#### JSON Response -Generates a JSON response with the specified JSON data. Optional provide -object that specifies custom response options such as headers and status code. - -```typescript -import { Request, Headers } from "sherpa-core"; -Response.text({ test: "hello world" }); -Response.text({ foo: "bar" }, { status: 201 }); -Response.text({ num: 3 }, { status: 201, headers: new Headers() }); -``` - - -#### Redirect Response -Generates a redirect response with the specified URL. This URL can either be either... - - Absolute with Origin `https://example.com/foo` - - Absolute `/foo` - - Relative `./foo` or `../foo` -Optional provide object that specifies custom response options such as headers -and status code. - -```typescript -import { Request, Headers } from "sherpa-core"; -Response.redirect("https://example.com/foo"); -Response.redirect("/foo", { status: 201 }); -Response.redirect("../foo", { status: 201, headers: new Headers() }); -``` - - -## Static Assets -SherpaJS servers can serve static assets under the `public` folder. - -
-
- - -## Modules -Modules are self-contained units of functional endpoints. They can do various -tasks such as analytics, status updates, authentication, and more. There are -plenty of [community modules](#community-modules), but if what you need doesn't -exist, developing your own modules is very simple. - -
- -### Creating a Module -A new module can be created relatively easily in just a couple of minutes. Check -out the [SherpaJS Module Template](https://github.com/sellersindustry/SherpaJS-template-module) -for an example of how to build your module. - -#### Step 1 -Setup a new NodeJS project with `npm init`. - -> [!TIP] -> You don't have to create a repository to make a module. If you choice you can -> simply create a new directory in your server and skip to [step 3](#step-3-1). - -Ensure your main is set to `sherpa.module.ts` so your ContextSchema and other -resources are accessible by servers implementing your module. -```json -{ - "name": "sherpa-module", - "version": "0.0.2", - "main": "sherpa.module.ts", - "scripts": { - "build": "sherpa build -b Vercel", - "dev": "sherpa build -b local && node ./.sherpa/index.js" - } -} -``` - -#### Step 2 -Install SherpaJS with `npm install sherpa-core`. - -#### Step 3 -Then create a module configuration file in the root directory of your modules -named `sherpa.module.ts`. This file will default export -a [module configuration](#module-configuration). - - -```typescript -// sherpa.module.ts -import { SherpaJS, CreateModuleInterface } from "sherpa-core"; - -export default SherpaJS.New.module({ - name: "example-module", - interface: CreateModuleInterface<{ foo: boolean, bar: string }> -}); -``` - -Alteratively, you can export any `interface` class with a constructor that -takes the context as a parameter sets `this.context` within your class. You -can attach additional methods onto this, that can be used to interact with your -module. - -```typescript -// sherpa.module.ts -import { SherpaJS, ModuleInterface } from "sherpa-core"; - -export default SherpaJS.New.module({ - name: "pass-primary-1", - interface: class example implements ModuleInterface { - context:{ foo: number, bar: string }; - constructor(context:{ foo: number, bar: string }) { - this.context = context; - } - } -}); -``` - - -#### Step 4 -To create endpoints for a new module in SherpaJS, you'll create a new -`/routes` directory the module. Each path inside the route directory will -correspond to it's relative endpoint. Endpoint logic is implemented in -javascript file named `index.ts` within these route directories. - -A simple implementation of an endpoint can be seen below. For detailed -instructions on creating routes and endpoints, see the [endpoints](#endpoints) -section. - -```typescript -// ./route/example/index.ts -import { Response, Request, Environment } from "sherpa-core"; - -export function GET(request:Request, env:Environment) { - return Response({ "hello": "world" }); -} -``` - -#### Step 6 -Create a [Sherpa Server](#servers) to test your module. For more details about -creating server configs see the [creating a server](#creating-a-server) section. - -```typescript -// sherpa.server.ts -import { SherpaJS } from "sherpa-core"; - -export default SherpaJS.New.server({ - context: { - test: true - } -}); -``` - - -#### Step 7 -Share your module with the world and get it listed as a [SherpaJS Community module](#community-modules) by [submitting a new issue](https://github.com/sellersindustry/SherpaJS/issues/new/choose). - -> [!IMPORTANT] -> Ensure your module... -> - Is deployed as an NPM package -> - Contains the documentation on how to set it up, like what properties are required. -> - Link to the SherpaJS documentation, so people understand how to set it up. -> - Share your creation with the world!! Help support SherpaJS!!! - -**Thanks so much for helping support SherpaJS!!! 🥳🎉** - -
- -### Module Configuration -Sherpa modules are configured using a `sherpa.module.ts` file, where you define -the structure and behavior of your module. This configuration file serves as -the entry point for your Sherpa module. - - -#### Config File -The file must located at `sherpa.module.ts` and have a default export of the -config and use the `SherpaJS.New.module` function as follows. You can export -a class using `ContextSchema`, that acts as a wrapper for validating the -context when the module is [loaded](#module-endpoint). - -```typescript -// sherpa.module.ts -import { SherpaJS, CreateModuleInterface } from "sherpa-core"; - -export default SherpaJS.New.module({ - name: "pass-primary-1", - interface: CreateModuleInterface<{ foo: boolean, bar: }> -}); -``` - -Alteratively, you can export any `interface` class with a constructor that -takes the context as a parameter sets `this.context` within your class. You -can attach additional methods onto this, that can be used to interact with your -module. - -```typescript -// sherpa.module.ts -import { SherpaJS, ModuleInterface } from "sherpa-core"; - -export default SherpaJS.New.module({ - name: "pass-primary-1", - interface: class example implements ModuleInterface { - context:{ foo: number, bar: string }; - constructor(context:{ foo: number, bar: string }) { - this.context = context; - } - } -}); -``` - -You can also export any additional attributes that you need, because `sherpa.module.ts` -should be the main script defined in your `package.json`. - - -#### Config Structure - - **Name:** The name of the module. - - **Interface:** Class that has `constructor(context:[TYPE])` and - property `context:[TYPE]`. - -The configuration provided to the module creator must match the TypeScript object as follows: -```typescript -export type ModuleConfig = { - name: string; - interface: Class; -}; -``` - -#### Example Config -```typescript -// sherpa.module.ts -import { SherpaJS, CreateModuleInterface } from "sherpa-core"; - -export default SherpaJS.New.module({ - name: "pass-primary-1", - interface: CreateModuleInterface<{ foo: boolean, bar: }> -}); -``` +## Getting Started +SherpaJS is a modular and agnostic serverless JavaScript web framework, that allows developers to easily build backend serverless web applications.
-
- -## Development -This project is in early development, so it is possible for you to run into issues. We do use this product in production, but that doesn't mean there could be issues. If you run into any issues, they will probably be at build time, just let us know. - -
- - -### Contributing +## Contributing Any help is very much appreciated. Build some useful modules and [submit them to our community](https://github.com/sellersindustry/SherpaJS/issues/new/choose) module list. Even help with documentation or refactoring code is helpful.
-### Proposed Features - - Build Test Harness to test standard endpoint features, bug detection, (and later Vercel Deployment). - - Support more than Text and JSON body payloads - - Auto reloading development server. - - Clean Command. - - Add SherpaJS 500 Error Page. - - Add SherpaJS 404 Error Page. - - Ability to add custom 500 and 404 error pages, with HTML in `/errors`. - - Catch all dynamic routes. - - Ability to add admin portal - - Ability to interact with modules. This can allow other endpoints or code - in the system or admin portals to call special functions that are part of the - module, with the given context. - - Import the endpoint which loads the module. The default export - using SherpaJS.Load.module(path, context, interactionClass); will have - a added optional variable of a class. The sherpaJS.Load.module will return - an instatiatied version of tha class with the context. - - Public Assets - - Migrate to RUST (Start by Migrating Tooling as it probs takes the longest) - - Make a document website with [Mintlify](https://mintlify.com/preview). - - Console Development Server, Live Logs - - -
- -### Proposed Modules - - Dynamic redirect service. - - Authical Authentication Service. - - GitHub Issue Creator Form for Support - -
- ### Credits + - [Evan Sellers](https://github.com/SellersEvan) - Illustration by Icons 8 from Ouch! From bd9676c21d73b6c687f20338eedffd8d573f09e9 Mon Sep 17 00:00:00 2001 From: Evan Sellers Date: Mon, 20 May 2024 16:54:38 -0400 Subject: [PATCH 32/32] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 575fe25..fc3f211 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ ## Getting Started SherpaJS is a modular and agnostic serverless JavaScript web framework, that allows developers to easily build backend serverless web applications. + * Check out the [documentation](https://docs.page/sellersindustry/SherpaJS) + * Check out the [server template example](https://github.com/sellersindustry/SherpaJS-template-server) + * Check out the [module template example](https://github.com/sellersindustry/SherpaJS-template-module) +