{"id":25195969,"url":"https://github.com/simplisticated/manifest-for-node","last_synced_at":"2025-07-30T01:15:41.797Z","repository":{"id":39920060,"uuid":"195376096","full_name":"simplisticated/Manifest-for-Node","owner":"simplisticated","description":"Easy configuration for Node.js app","archived":false,"fork":false,"pushed_at":"2023-07-12T02:41:36.000Z","size":612,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-26T22:26:45.109Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simplisticated.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-07-05T08:58:32.000Z","updated_at":"2022-05-21T12:16:35.000Z","dependencies_parsed_at":"2023-07-17T15:07:23.944Z","dependency_job_id":null,"html_url":"https://github.com/simplisticated/Manifest-for-Node","commit_stats":null,"previous_names":["igormatyushkin014/manifest-for-node","russo-programmisto/manifest-for-node"],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/simplisticated/Manifest-for-Node","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplisticated%2FManifest-for-Node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplisticated%2FManifest-for-Node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplisticated%2FManifest-for-Node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplisticated%2FManifest-for-Node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simplisticated","download_url":"https://codeload.github.com/simplisticated/Manifest-for-Node/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simplisticated%2FManifest-for-Node/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267791117,"owners_count":24144910,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-10T01:39:14.606Z","updated_at":"2025-07-30T01:15:41.759Z","avatar_url":"https://github.com/simplisticated.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"images/logo.png\" alt=\"Manifest\" title=\"Manifest\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"#\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Created for-Node.js-teal.svg?style=flat\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"#\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Written in-TypeScript-purple.svg?style=flat\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/License-Apache 2.0-blue.svg?style=flat\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n## At a Glance\n\n`Manifest` is a framework that takes control over Node.js app using a single configuration file. `Manifest` includes `Express` framework and `Handlebars` server-side rendering under the hood.\n\n## How to Get Started\n\nType in Terminal:\n\n```\nnpm install --save @simplisticated/manifest express hbs express-hbs\nnpm install --save-dev @types/express @types/hbs\n```\n\nor, if you prefer `yarn` over `npm`, type:\n\n```\nyarn add @simplisticated/manifest express hbs express-hbs\nyarn add @types/express @types/hbs --dev\n```\n\n## Requirements\n\n- [express](https://expressjs.com)\n- [hbs](https://www.npmjs.com/package/hbs)\n- [express-hbs](https://www.npmjs.com/package/express-hbs)\n\n## Usage\n\n### Launching App\n\nThe simplest way to start Express server:\n\n```typescript\nimport * as mfst from \"@simplisticated/manifest\";\n\nmfst.App.create().start();\n```\n\nOpen [localhost:3000](http://localhost:3000) in your browser. You will see a message saying `Built with Manifest framework`.\n\nThat's all! The server is launched 🚀\n\nBy the way, you can access `Express` instance directly by calling\n\n```typescript\napp.expressInstance\n```\n\nQuite simple, right? 😉\n\n### Server Configuration\n\nNow let's learn how to configure our server:\n\n```typescript\nimport * as mfst from \"@simplisticated/manifest\";\n\nlet app = mfst.App.create({\n    server: {\n        port: 3000,          // Use any port, usually it's 3000\n        secure: false       // HTTP or HTTPS\n    },\n    api: {\n        routes: [\n            {\n                url: `/`,\n                methods: {\n                    get: {\n                        text: `\u003ch1\u003eThis page is under construction\u003c/h1\u003e`,\n                    }\n                }\n            },\n            {\n                url: \"/users\",\n                    methods: {\n                        get: {\n                            json: {\n                                count: 200,\n                                users: [\n                                    {\n                                        id: 1,\n                                        first_name: \"John\",\n                                        last_name: \"Appleseed\"\n                                    },\n                                    // etc...\n                                ]\n                            }\n                        },\n                        post: {\n                            handler: (req, res) =\u003e {\n                                const { first_name, last_name } = req.body;\n                                \n                                if (first_name \u0026\u0026 last_name) {\n                                    // Create user in database...\n                                    return {\n                                        json: {\n                                            id: 123,\n                                            first_name,\n                                            last_name\n                                        },\n                                        status: 200\n                                    };\n                                } else {\n                                    return {\n                                        json: {\n                                            message: \"Please make sure that you send first_name and last_name parameters.\"\n                                        },\n                                        status: 400\n                                    };\n                                }\n                            }\n                        }\n                    }\n                },\n            {\n                url: `*`,\n                methods: {\n                    get: {\n                        text: `\u003ch1\u003ePage not found\u003c/h1\u003e`,\n                        status: 404,\n                        timeout: 2000\n                    }\n                }\n            }\n        ],\n    }\n});\n\napp.start();\n```\n\nIn the above example you can see a very simple configuration that is enough to launch a primitive server which will be able to respond to HTTP requests.\n\n### Manifest Sections\n\n#### `server.port`\n\nPort number that server will be listen to.\n\n#### `server.secure`\n\nIf `true`, HTTPS will be used under the hood. Otherwise, we'll use unsecure HTTP.\n\n#### `server.corsBlocked`\n\nIf `true`, CORS will be enabled for all endpoints.\n\n#### `api.requestHandlers`\n\nArray of functions. Each function has `request` parameter and handles request before it's processed by `Manifest` framework. You can use handlers for any purpose. For example, sending request information to the console output:\n\n```typescript\nrequestHandlers: [\n    (request) =\u003e {\n        console.log(`Request to ${request.url}`);\n    }\n]\n```\n\n#### `api.routes`\n\nArray of objects. Each object represents a different route. Example:\n\n```typescript\n{\n    routes: [\n        {\n            url: \"/\",\n            methods: {\n                get: {\n                    text: \"Hello!\"\n                },\n                post: {\n                    text: \"Post response.\"\n                },\n                put: {\n                    text: \"Put response.\"\n                },\n                delete: {\n                    text: \"Delete response.\"\n                }\n            }\n        }\n    ]\n}\n```\n\nThe `methods` object can include any of these HTTP methods:\n\n- `get`\n- `post`\n- `put`\n- `delete`\n\nEach HTTP method describes the response to client's request. `Manifest` supports 5 types of response:\n\n- Text (returns simple text)\n- JSON (returns JSON object or array)\n- Page (returns page and data for server-side rendering)\n- Redirect (sends command for redirection to another URL)\n- Custom (arrow function that is implemented by developer and returns text or JSON or page response)\n- Custom asynchronous (arrow function that is implemented by developer and returns text or JSON or page response by using callback)\n\nExample of text response:\n\n```typescript\n{\n    routes: [\n        {\n            url: `/profile`,\n            methods: {\n                get: {\n                    text: \"\u003ch1\u003eJohn Green\u003c/h1\u003e\"\n                }\n            }\n        }\n    ]\n}\n```\n\nJSON response:\n\n```typescript\n{\n    routes: [\n        {\n            url: `/profile`,\n            methods: {\n                get: {\n                    json: {\n                        first_name: \"John\",\n                        last_name: \"Green\"\n                    }\n                }\n            }\n        }\n    ]\n}\n```\n\nPage response:\n\n```typescript\n{\n    routes: [\n        {\n            url: `/profile`,\n            methods: {\n                get: {\n                    path: `${__dirname}/views/profile.hbs`,\n                    data: {\n                        // Optional data that will be used by Handlebars engine.\n                        firstName: \"John\",\n                        lastName: \"Green\"\n                    }\n                }\n            }\n        }\n    ]\n}\n```\n\nRedirect response:\n\n```typescript\n{\n    routes: [\n        {\n            url: `/profile`,\n            methods: {\n                get: {\n                    redirectTo: \"/not_found\"\n                }\n            }\n        }\n    ]\n}\n```\n\nCustom response:\n\n```typescript\n{\n    routes: [\n        {\n            url: `/profile`,\n            methods: {\n                get: {\n                    handler: (request, response) =\u003e {\n                        let firstName = \"John\";\n                        let lastName = \"Green\";\n\n                        // We have to return text or JSON or page response here.\n                        return {\n                            json: {\n                                first_name: firstName,\n                                last_name: lastName\n                            }\n                        };\n                    }\n                }\n            }\n        }\n    ]\n}\n```\n\nCustom asynchronous response:\n\n```typescript\n{\n    routes: [\n        {\n            url: `/profile`,\n            methods: {\n                get: {\n                    asyncHandler: (request, response, callback) =\u003e {\n                        let firstName = \"John\";\n                        let lastName = \"Green\";\n                        \n                        // Return response using callback.\n                        callback({\n                            json: {\n                                first_name: firstName,\n                                last_name: lastName\n                            }\n                        });\n                    }\n                }\n            }\n        }\n    ]\n}\n```\n\nAlso, most of response types support optional parameters:\n\n- `status`: HTTP status, by default 200\n- `delay`: The duration in milliseconds of delay before returning response.\n\nExample of using custom HTTP status:\n\n```typescript\n{\n    routes: [\n        {\n            url: `/profile`,\n            methods: {\n                get: {\n                    text: \"\u003ch1\u003eNot found\u003c/h1\u003e\",\n                    status: 404\n                }\n            }\n        }\n    ]\n}\n```\n\nSometimes you might want to simulate slow server. Use `delay` for this purpose:\n\n```typescript\n{\n    routes: [\n        {\n            url: `/profile`,\n            methods: {\n                get: {\n                    json: {\n                        first_name: \"John\",\n                        last_name: \"Green\"\n                    },\n                    delay: 4000\n                }\n            }\n        }\n    ]\n}\n```\n\n#### `server.viewEngines.current`\n\nThe current view engine. Currently supports `handlebars` only. Possible values:\n\n* `handlebars`\n* `none`\n\n#### `server.viewEngines.partialsDirectory`\n\nPath to partials directory for the view engine.\n\n## License\n\n`Manifest` is available under the Apache 2.0 license. See the [LICENSE](./LICENSE) file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimplisticated%2Fmanifest-for-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimplisticated%2Fmanifest-for-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimplisticated%2Fmanifest-for-node/lists"}