mirror of
https://github.com/eliasrenman/gardentron.git
synced 2026-03-16 20:46:07 +01:00
chore: setup featherjs project
This commit is contained in:
121
server/.gitignore
vendored
Normal file
121
server/.gitignore
vendored
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
.sqlite
|
||||||
|
|
||||||
|
lib/
|
||||||
121
server/.npmignore
Normal file
121
server/.npmignore
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
.sqlite
|
||||||
|
|
||||||
|
lib/
|
||||||
9
server/.prettierrc
Normal file
9
server/.prettierrc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"printWidth": 110,
|
||||||
|
"semi": false,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"singleQuote": true,
|
||||||
|
"parser": "typescript"
|
||||||
|
}
|
||||||
10
server/config/custom-environment-variables.json
Normal file
10
server/config/custom-environment-variables.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"port": {
|
||||||
|
"__name": "PORT",
|
||||||
|
"__format": "number"
|
||||||
|
},
|
||||||
|
"host": "HOSTNAME",
|
||||||
|
"authentication": {
|
||||||
|
"secret": "FEATHERS_SECRET"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
server/config/default.json
Normal file
17
server/config/default.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 3030,
|
||||||
|
"public": "./public/",
|
||||||
|
"origins": [
|
||||||
|
"http://localhost:3030"
|
||||||
|
],
|
||||||
|
"paginate": {
|
||||||
|
"default": 10,
|
||||||
|
"max": 50
|
||||||
|
},
|
||||||
|
"sqlite": {
|
||||||
|
"client": "sqlite3",
|
||||||
|
"connection": "server.sqlite",
|
||||||
|
"useNullAsDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
3
server/config/test.json
Normal file
3
server/config/test.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"port": 8998
|
||||||
|
}
|
||||||
7
server/knexfile.ts
Normal file
7
server/knexfile.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/databases.html
|
||||||
|
import { app } from './src/app'
|
||||||
|
|
||||||
|
// Load our database connection info from the app configuration
|
||||||
|
const config = app.get('sqlite')
|
||||||
|
|
||||||
|
module.exports = config
|
||||||
10
server/node_modules/.yarn-integrity
generated
vendored
Normal file
10
server/node_modules/.yarn-integrity
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"systemParams": "linux-x64-108",
|
||||||
|
"modulesFolders": [],
|
||||||
|
"flags": [],
|
||||||
|
"linkedModules": [],
|
||||||
|
"topLevelPatterns": [],
|
||||||
|
"lockfileEntries": {},
|
||||||
|
"files": [],
|
||||||
|
"artifacts": {}
|
||||||
|
}
|
||||||
48
server/package.json
Normal file
48
server/package.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "server",
|
||||||
|
"description": "The server for handling two way communication with a iot Device",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"homepage": "",
|
||||||
|
"private": true,
|
||||||
|
"keywords": [
|
||||||
|
"feathers"
|
||||||
|
],
|
||||||
|
"author": {},
|
||||||
|
"contributors": [],
|
||||||
|
"bugs": {},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18.16.0"
|
||||||
|
},
|
||||||
|
"feathers": {
|
||||||
|
"language": "ts",
|
||||||
|
"packager": "yarn",
|
||||||
|
"database": "sqlite",
|
||||||
|
"framework": "koa",
|
||||||
|
"transports": [
|
||||||
|
"rest",
|
||||||
|
"websockets"
|
||||||
|
],
|
||||||
|
"schema": "typebox"
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"lib": "src",
|
||||||
|
"test": "test"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib/client.js",
|
||||||
|
"lib/**/*.d.ts",
|
||||||
|
"lib/**/*.shared.js"
|
||||||
|
],
|
||||||
|
"main": "lib/client",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nodemon -x ts-node src/index.ts",
|
||||||
|
"compile": "shx rm -rf lib/ && tsc",
|
||||||
|
"start": "node lib/",
|
||||||
|
"prettier": "npx prettier \"**/*.ts\" --write",
|
||||||
|
"mocha": "cross-env NODE_ENV=test mocha test/ --require ts-node/register --recursive --extension .ts --exit",
|
||||||
|
"test": "cross-env NODE_ENV=test npm run migrate && npm run mocha",
|
||||||
|
"bundle:client": "npm run compile && npm pack --pack-destination ./public",
|
||||||
|
"migrate": "knex migrate:latest",
|
||||||
|
"migrate:make": "knex migrate:make"
|
||||||
|
}
|
||||||
|
}
|
||||||
37
server/public/index.html
Normal file
37
server/public/index.html
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>server</title>
|
||||||
|
<meta name="description" content="The server for handling two way communication with a iot Device">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
min-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.logo {
|
||||||
|
display: block;
|
||||||
|
margin: auto auto;
|
||||||
|
width: 30%;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img class="logo" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjUwMCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTEyOCA5LjEwMmM2NS42NjUgMCAxMTguODk4IDUzLjIzMyAxMTguODk4IDExOC44OTggMCA2NS42NjUtNTMuMjMzIDExOC44OTgtMTE4Ljg5OCAxMTguODk4QzYyLjMzNSAyNDYuODk4IDkuMTAyIDE5My42NjUgOS4xMDIgMTI4IDkuMTAyIDYyLjMzNSA2Mi4zMzUgOS4xMDIgMTI4IDkuMTAyTTEyOCAwQzU3LjQyMSAwIDAgNTcuNDIxIDAgMTI4YzAgNzAuNTc5IDU3LjQyMSAxMjggMTI4IDEyOCA3MC41NzkgMCAxMjgtNTcuNDIxIDEyOC0xMjhDMjU2IDU3LjQyMSAxOTguNTc5IDAgMTI4IDBtMjAuODMgMjUuNTI0Yy0xMC40My0xLjg5Ni0zNS42NTEgMzYuNDA5LTQzLjk5NCA1OS43MzQtLjYzNCAxLjc2OS0yLjA4NiA4LjI0OS0yLjA4NiA5Ljk1NSAwIDAgNi41MzEgMTQuMDU1IDguMzQzIDE3LjM1MS0zLjAzNC0xLjU4LTkuMzIzLTEzLjc1Ni05LjMyMy0xMy43NTYtMy4wMzQgNS43ODQtNS45NDIgMzIuMzQtNC45OTQgMzcuMjcxIDAgMCA2Ljc2MiAxMC4wNjIgOS4zODcgMTIuNTc4LTMuNjAzLTEuMjAxLTkuNjcxLTkuMzU1LTkuNjcxLTkuMzU1LTEuMTM4IDMuNTA4LS45MTYgMTAuODA3LS4zNzkgMTMuMjc0IDQuNTUxIDYuNjM3IDEwLjYxOSA3LjM5NiAxMC42MTkgNy4zOTZzLTYuNjM3IDY2LjE4MSAzLjQxMyA3MS4xMTFjNi4yNTgtMS4zMjcgNy43NzUtNzMuOTU2IDcuNzc1LTczLjk1NnM3LjU4NS41NjkgOS4yOTItMS4zMjdjMy44NTYtMi42NTUgMTIuODI2LTMwLjIyNCAxMi45NTgtMzQuMjAyIDAgMC0xMC40MSAxLjk1Mi0xNS40ODcgMy45MjQgMy44MjYtMy44IDE2LjA0OS02LjM1MiAxNi4wNDktNi4zNTIgMy4zMTUtMy45NzkgMTAuMjkxLTMxLjA0NyAxMC45OTQtMzkuMzkxLjE3Ni0yLjA5My41ODMtNC42NTcuMjY4LTguMzk4IDAgMC05Ljk0MSAyLjE3Ny0xMi4wMTQgMS40MjQgMi4xMDQtLjIzNyAxMi4yNjMtNC4xNCAxMi4yNjMtNC4xNCAxLjgwMS0xNi4yMTMgMi4zNTgtNDIuMDkxLTMuNDEzLTQzLjE0MXptLTM2LjM4IDE3MS42OTFjLS43OTUgMTkuNDk2LTEuMjk0IDI1LjAwNC0yLjExNSAyOS42MDEtLjM3OS44NTctLjc1OC45OTctMS4xMzgtLjA5NS0zLjQ3Ny0xNS45OTItMy4yMjQtMTM2LjQzOCAzNi40MDktMTkxLjI0MS0yMy4wNSA0Mi4wOTItMzMuNTM1IDEyMi44NjEtMzMuMTU2IDE2MS43MzV6IiBmaWxsPSIjMzMzIi8+PC9zdmc+" />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
42
server/readme.md
Normal file
42
server/readme.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# server
|
||||||
|
|
||||||
|
> The server for handling two way communication with a iot Device
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
This project uses [Feathers](http://feathersjs.com). An open source framework for building APIs and real-time applications.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. Make sure you have [NodeJS](https://nodejs.org/) and [npm](https://www.npmjs.com/) installed.
|
||||||
|
2. Install your dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
cd path/to/server
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Start your app
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run compile # Compile TypeScript source
|
||||||
|
npm run migrate # Run migrations to set up the database
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Run `npm test` and all your tests in the `test/` directory will be run.
|
||||||
|
|
||||||
|
## Scaffolding
|
||||||
|
|
||||||
|
This app comes with a powerful command line interface for Feathers. Here are a few things it can do:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npx feathers help # Show all commands
|
||||||
|
$ npx feathers generate service # Generate a new Service
|
||||||
|
```
|
||||||
|
|
||||||
|
## Help
|
||||||
|
|
||||||
|
For more information on all the things you can do with Feathers visit [docs.feathersjs.com](http://docs.feathersjs.com).
|
||||||
54
server/src/app.ts
Normal file
54
server/src/app.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/application.html
|
||||||
|
import { feathers } from '@feathersjs/feathers'
|
||||||
|
import configuration from '@feathersjs/configuration'
|
||||||
|
import { koa, rest, bodyParser, errorHandler, parseAuthentication, cors, serveStatic } from '@feathersjs/koa'
|
||||||
|
import socketio from '@feathersjs/socketio'
|
||||||
|
|
||||||
|
import { configurationValidator } from './configuration'
|
||||||
|
import type { Application } from './declarations'
|
||||||
|
import { logError } from './hooks/log-error'
|
||||||
|
import { sqlite } from './sqlite'
|
||||||
|
import { services } from './services/index'
|
||||||
|
import { channels } from './channels'
|
||||||
|
|
||||||
|
const app: Application = koa(feathers())
|
||||||
|
|
||||||
|
// Load our app configuration (see config/ folder)
|
||||||
|
app.configure(configuration(configurationValidator))
|
||||||
|
|
||||||
|
// Set up Koa middleware
|
||||||
|
app.use(cors())
|
||||||
|
app.use(serveStatic(app.get('public')))
|
||||||
|
app.use(errorHandler())
|
||||||
|
app.use(parseAuthentication())
|
||||||
|
app.use(bodyParser())
|
||||||
|
|
||||||
|
// Configure services and transports
|
||||||
|
app.configure(rest())
|
||||||
|
app.configure(
|
||||||
|
socketio({
|
||||||
|
cors: {
|
||||||
|
origin: app.get('origins')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
app.configure(channels)
|
||||||
|
app.configure(sqlite)
|
||||||
|
app.configure(services)
|
||||||
|
|
||||||
|
// Register hooks that run on all service methods
|
||||||
|
app.hooks({
|
||||||
|
around: {
|
||||||
|
all: [logError]
|
||||||
|
},
|
||||||
|
before: {},
|
||||||
|
after: {},
|
||||||
|
error: {}
|
||||||
|
})
|
||||||
|
// Register application setup and teardown hooks here
|
||||||
|
app.hooks({
|
||||||
|
setup: [],
|
||||||
|
teardown: []
|
||||||
|
})
|
||||||
|
|
||||||
|
export { app }
|
||||||
38
server/src/channels.ts
Normal file
38
server/src/channels.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/channels.html
|
||||||
|
import type { RealTimeConnection, Params } from '@feathersjs/feathers'
|
||||||
|
import type { AuthenticationResult } from '@feathersjs/authentication'
|
||||||
|
import '@feathersjs/transport-commons'
|
||||||
|
import type { Application, HookContext } from './declarations'
|
||||||
|
import { logger } from './logger'
|
||||||
|
|
||||||
|
export const channels = (app: Application) => {
|
||||||
|
logger.warn(
|
||||||
|
'Publishing all events to all authenticated users. See `channels.ts` and https://dove.feathersjs.com/api/channels.html for more information.'
|
||||||
|
)
|
||||||
|
|
||||||
|
app.on('connection', (connection: RealTimeConnection) => {
|
||||||
|
// On a new real-time connection, add it to the anonymous channel
|
||||||
|
app.channel('anonymous').join(connection)
|
||||||
|
})
|
||||||
|
|
||||||
|
app.on('login', (authResult: AuthenticationResult, { connection }: Params) => {
|
||||||
|
// connection can be undefined if there is no
|
||||||
|
// real-time connection, e.g. when logging in via REST
|
||||||
|
if (connection) {
|
||||||
|
// The connection is no longer anonymous, remove it
|
||||||
|
app.channel('anonymous').leave(connection)
|
||||||
|
|
||||||
|
// Add it to the authenticated user channel
|
||||||
|
app.channel('authenticated').join(connection)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
app.publish((data: any, context: HookContext) => {
|
||||||
|
// Here you can add event publishers to channels set up in `channels.js`
|
||||||
|
// To publish only for a specific event use `app.publish(eventname, () => {})`
|
||||||
|
|
||||||
|
// e.g. to publish all service events to all authenticated users use
|
||||||
|
return app.channel('authenticated')
|
||||||
|
})
|
||||||
|
}
|
||||||
34
server/src/client.ts
Normal file
34
server/src/client.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/client.html
|
||||||
|
import { feathers } from '@feathersjs/feathers'
|
||||||
|
import type { TransportConnection, Application } from '@feathersjs/feathers'
|
||||||
|
import authenticationClient from '@feathersjs/authentication-client'
|
||||||
|
import type { AuthenticationClientOptions } from '@feathersjs/authentication-client'
|
||||||
|
|
||||||
|
export interface Configuration {
|
||||||
|
connection: TransportConnection<ServiceTypes>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServiceTypes {}
|
||||||
|
|
||||||
|
export type ClientApplication = Application<ServiceTypes, Configuration>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a typed client for the server app.
|
||||||
|
*
|
||||||
|
* @param connection The REST or Socket.io Feathers client connection
|
||||||
|
* @param authenticationOptions Additional settings for the authentication client
|
||||||
|
* @see https://dove.feathersjs.com/api/client.html
|
||||||
|
* @returns The Feathers client application
|
||||||
|
*/
|
||||||
|
export const createClient = <Configuration = any>(
|
||||||
|
connection: TransportConnection<ServiceTypes>,
|
||||||
|
authenticationOptions: Partial<AuthenticationClientOptions> = {}
|
||||||
|
) => {
|
||||||
|
const client: ClientApplication = feathers()
|
||||||
|
|
||||||
|
client.configure(connection)
|
||||||
|
client.configure(authenticationClient(authenticationOptions))
|
||||||
|
client.set('connection', connection)
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
17
server/src/configuration.ts
Normal file
17
server/src/configuration.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Type, getValidator, defaultAppConfiguration } from '@feathersjs/typebox'
|
||||||
|
import type { Static } from '@feathersjs/typebox'
|
||||||
|
|
||||||
|
import { dataValidator } from './validators'
|
||||||
|
|
||||||
|
export const configurationSchema = Type.Intersect([
|
||||||
|
defaultAppConfiguration,
|
||||||
|
Type.Object({
|
||||||
|
host: Type.String(),
|
||||||
|
port: Type.Number(),
|
||||||
|
public: Type.String()
|
||||||
|
})
|
||||||
|
])
|
||||||
|
|
||||||
|
export type ApplicationConfiguration = Static<typeof configurationSchema>
|
||||||
|
|
||||||
|
export const configurationValidator = getValidator(configurationSchema, dataValidator)
|
||||||
20
server/src/declarations.ts
Normal file
20
server/src/declarations.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/typescript.html
|
||||||
|
import { HookContext as FeathersHookContext, NextFunction } from '@feathersjs/feathers'
|
||||||
|
import { Application as FeathersApplication } from '@feathersjs/koa'
|
||||||
|
import { ApplicationConfiguration } from './configuration'
|
||||||
|
|
||||||
|
export { NextFunction }
|
||||||
|
|
||||||
|
// The types for app.get(name) and app.set(name)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface Configuration extends ApplicationConfiguration {}
|
||||||
|
|
||||||
|
// A mapping of service names to types. Will be extended in service files.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface ServiceTypes {}
|
||||||
|
|
||||||
|
// The application instance type that will be used everywhere else
|
||||||
|
export type Application = FeathersApplication<ServiceTypes, Configuration>
|
||||||
|
|
||||||
|
// The context for hook functions - can be typed with a service class
|
||||||
|
export type HookContext<S = any> = FeathersHookContext<Application, S>
|
||||||
18
server/src/hooks/log-error.ts
Normal file
18
server/src/hooks/log-error.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/log-error.html
|
||||||
|
import type { HookContext, NextFunction } from '../declarations'
|
||||||
|
import { logger } from '../logger'
|
||||||
|
|
||||||
|
export const logError = async (context: HookContext, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
await next()
|
||||||
|
} catch (error: any) {
|
||||||
|
logger.error(error.stack)
|
||||||
|
|
||||||
|
// Log validation errors
|
||||||
|
if (error.data) {
|
||||||
|
logger.error('Data: %O', error.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
11
server/src/index.ts
Normal file
11
server/src/index.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { app } from './app'
|
||||||
|
import { logger } from './logger'
|
||||||
|
|
||||||
|
const port = app.get('port')
|
||||||
|
const host = app.get('host')
|
||||||
|
|
||||||
|
process.on('unhandledRejection', (reason) => logger.error('Unhandled Rejection %O', reason))
|
||||||
|
|
||||||
|
app.listen(port).then(() => {
|
||||||
|
logger.info(`Feathers app listening on http://${host}:${port}`)
|
||||||
|
})
|
||||||
10
server/src/logger.ts
Normal file
10
server/src/logger.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/logging.html
|
||||||
|
import { createLogger, format, transports } from 'winston'
|
||||||
|
|
||||||
|
// Configure the Winston logger. For the complete documentation see https://github.com/winstonjs/winston
|
||||||
|
export const logger = createLogger({
|
||||||
|
// To see more detailed errors, change this to 'debug'
|
||||||
|
level: 'info',
|
||||||
|
format: format.combine(format.splat(), format.simple()),
|
||||||
|
transports: [new transports.Console()]
|
||||||
|
})
|
||||||
6
server/src/services/index.ts
Normal file
6
server/src/services/index.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/application.html#configure-functions
|
||||||
|
import type { Application } from '../declarations'
|
||||||
|
|
||||||
|
export const services = (app: Application) => {
|
||||||
|
// All services will be registered here
|
||||||
|
}
|
||||||
17
server/src/sqlite.ts
Normal file
17
server/src/sqlite.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/databases.html
|
||||||
|
import knex from 'knex'
|
||||||
|
import type { Knex } from 'knex'
|
||||||
|
import type { Application } from './declarations'
|
||||||
|
|
||||||
|
declare module './declarations' {
|
||||||
|
interface Configuration {
|
||||||
|
sqliteClient: Knex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sqlite = (app: Application) => {
|
||||||
|
const config = app.get('sqlite')
|
||||||
|
const db = knex(config!)
|
||||||
|
|
||||||
|
app.set('sqliteClient', db)
|
||||||
|
}
|
||||||
29
server/src/validators.ts
Normal file
29
server/src/validators.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/validators.html
|
||||||
|
import { Ajv, addFormats } from '@feathersjs/schema'
|
||||||
|
import type { FormatsPluginOptions } from '@feathersjs/schema'
|
||||||
|
|
||||||
|
const formats: FormatsPluginOptions = [
|
||||||
|
'date-time',
|
||||||
|
'time',
|
||||||
|
'date',
|
||||||
|
'email',
|
||||||
|
'hostname',
|
||||||
|
'ipv4',
|
||||||
|
'ipv6',
|
||||||
|
'uri',
|
||||||
|
'uri-reference',
|
||||||
|
'uuid',
|
||||||
|
'uri-template',
|
||||||
|
'json-pointer',
|
||||||
|
'relative-json-pointer',
|
||||||
|
'regex'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const dataValidator: Ajv = addFormats(new Ajv({}), formats)
|
||||||
|
|
||||||
|
export const queryValidator: Ajv = addFormats(
|
||||||
|
new Ajv({
|
||||||
|
coerceTypes: true
|
||||||
|
}),
|
||||||
|
formats
|
||||||
|
)
|
||||||
40
server/test/app.test.ts
Normal file
40
server/test/app.test.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// For more information about this file see https://dove.feathersjs.com/guides/cli/app.test.html
|
||||||
|
import assert from 'assert'
|
||||||
|
import axios from 'axios'
|
||||||
|
import type { Server } from 'http'
|
||||||
|
import { app } from '../src/app'
|
||||||
|
|
||||||
|
const port = app.get('port')
|
||||||
|
const appUrl = `http://${app.get('host')}:${port}`
|
||||||
|
|
||||||
|
describe('Feathers application tests', () => {
|
||||||
|
let server: Server
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
server = await app.listen(port)
|
||||||
|
})
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await app.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('starts and shows the index page', async () => {
|
||||||
|
const { data } = await axios.get<string>(appUrl)
|
||||||
|
|
||||||
|
assert.ok(data.indexOf('<html lang="en">') !== -1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows a 404 JSON error', async () => {
|
||||||
|
try {
|
||||||
|
await axios.get(`${appUrl}/path/to/nowhere`, {
|
||||||
|
responseType: 'json'
|
||||||
|
})
|
||||||
|
assert.fail('should never get here')
|
||||||
|
} catch (error: any) {
|
||||||
|
const { response } = error
|
||||||
|
assert.strictEqual(response?.status, 404)
|
||||||
|
assert.strictEqual(response?.data?.code, 404)
|
||||||
|
assert.strictEqual(response?.data?.name, 'NotFound')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
18
server/test/client.test.ts
Normal file
18
server/test/client.test.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import assert from 'assert'
|
||||||
|
import axios from 'axios'
|
||||||
|
import type { Server } from 'http'
|
||||||
|
import { app } from '../src/app'
|
||||||
|
import { createClient } from '../src/client'
|
||||||
|
|
||||||
|
import rest from '@feathersjs/rest-client'
|
||||||
|
|
||||||
|
const port = app.get('port')
|
||||||
|
const appUrl = `http://${app.get('host')}:${port}`
|
||||||
|
|
||||||
|
describe('client tests', () => {
|
||||||
|
const client = createClient(rest(appUrl).axios(axios))
|
||||||
|
|
||||||
|
it('initialized the client', () => {
|
||||||
|
assert.ok(client)
|
||||||
|
})
|
||||||
|
})
|
||||||
21
server/tsconfig.json
Normal file
21
server/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"ts-node": {
|
||||||
|
"files": true
|
||||||
|
},
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2020",
|
||||||
|
"module": "commonjs",
|
||||||
|
"outDir": "./lib",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"declaration": true,
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"sourceMap": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
}
|
||||||
4
server/yarn.lock
Normal file
4
server/yarn.lock
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user