feat: Add Dao

This commit is contained in:
Florian Bouillon 2023-06-19 00:50:46 +02:00
parent 59db3976fe
commit 5c1ed32cb6
30 changed files with 7344 additions and 6753 deletions

218
package-lock.json generated
View File

@ -14,6 +14,7 @@
"@dzeio/url-manager": "^1.0.9",
"astro": "^2.6.4",
"mathjs": "^11.8.1",
"mongoose": "^7.3.0",
"tailwindcss": "^3.3.2"
},
"devDependencies": {
@ -1075,8 +1076,7 @@
"node_modules/@types/node": {
"version": "20.3.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz",
"integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==",
"devOptional": true
"integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg=="
},
"node_modules/@types/parse5": {
"version": "6.0.3",
@ -1093,6 +1093,20 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
"integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ=="
},
"node_modules/@types/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog=="
},
"node_modules/@types/whatwg-url": {
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz",
"integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==",
"dependencies": {
"@types/node": "*",
"@types/webidl-conversions": "*"
}
},
"node_modules/@types/yargs-parser": {
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
@ -1556,6 +1570,14 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/bson": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-5.3.0.tgz",
"integrity": "sha512-ukmCZMneMlaC5ebPHXIkP8YJzNl5DC41N5MAIvKDqLggdao342t4McltoJBQfQya/nHBWAcSsYRqlXPoQkTJag==",
"engines": {
"node": ">=14.20.1"
}
},
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
@ -2655,6 +2677,11 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/ip": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@ -2903,6 +2930,14 @@
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz",
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg=="
},
"node_modules/kareem": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
"integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==",
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@ -3287,6 +3322,12 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -3880,6 +3921,92 @@
"node": "*"
}
},
"node_modules/mongodb": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.6.0.tgz",
"integrity": "sha512-z8qVs9NfobHJm6uzK56XBZF8XwM9H294iRnB7wNjF0SnY93si5HPziIJn+qqvUR5QOff/4L0gCD6SShdR/GtVQ==",
"dependencies": {
"bson": "^5.3.0",
"mongodb-connection-string-url": "^2.6.0",
"socks": "^2.7.1"
},
"engines": {
"node": ">=14.20.1"
},
"optionalDependencies": {
"saslprep": "^1.0.3"
},
"peerDependencies": {
"@aws-sdk/credential-providers": "^3.201.0",
"mongodb-client-encryption": ">=2.3.0 <3",
"snappy": "^7.2.2"
},
"peerDependenciesMeta": {
"@aws-sdk/credential-providers": {
"optional": true
},
"mongodb-client-encryption": {
"optional": true
},
"snappy": {
"optional": true
}
}
},
"node_modules/mongodb-connection-string-url": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz",
"integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
"dependencies": {
"@types/whatwg-url": "^8.2.1",
"whatwg-url": "^11.0.0"
}
},
"node_modules/mongoose": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.3.0.tgz",
"integrity": "sha512-gvkV5qxmBkGohlk7VTeePMPM2OkQPeqVYZHvjoM4goOIK6G1eSfJMZwXV21asivXxlaz6OuP29TfGAKrKooDAg==",
"dependencies": {
"bson": "^5.3.0",
"kareem": "2.5.1",
"mongodb": "5.6.0",
"mpath": "0.9.0",
"mquery": "5.0.0",
"ms": "2.1.3",
"sift": "16.0.1"
},
"engines": {
"node": ">=14.20.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mongoose"
}
},
"node_modules/mongoose/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/mpath": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
"integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/mquery": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz",
"integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==",
"dependencies": {
"debug": "4.x"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
@ -4486,6 +4613,14 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/punycode": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"engines": {
"node": ">=6"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -4962,6 +5097,18 @@
}
]
},
"node_modules/saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"dependencies": {
"sparse-bitfield": "^3.0.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/sass-formatter": {
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/sass-formatter/-/sass-formatter-0.7.6.tgz",
@ -5114,6 +5261,11 @@
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w=="
},
"node_modules/sift": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz",
"integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ=="
},
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
@ -5135,6 +5287,28 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
"integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
"dependencies": {
"ip": "^2.0.0",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.13.0",
"npm": ">= 3.0.0"
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
@ -5152,6 +5326,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"optional": true,
"dependencies": {
"memory-pager": "^1.0.2"
}
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -5449,6 +5632,17 @@
"node": ">=0.6"
}
},
"node_modules/tr46": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
"dependencies": {
"punycode": "^2.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/trim-lines": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
@ -5922,6 +6116,26 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
"engines": {
"node": ">=12"
}
},
"node_modules/whatwg-url": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
"dependencies": {
"tr46": "^3.0.0",
"webidl-conversions": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -1,6 +1,5 @@
{
"name": "paas",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
@ -16,6 +15,7 @@
"@dzeio/url-manager": "^1.0.9",
"astro": "^2.6.4",
"mathjs": "^11.8.1",
"mongoose": "^7.3.0",
"tailwindcss": "^3.3.2"
},
"devDependencies": {

1
src/env.d.ts vendored
View File

@ -3,6 +3,7 @@
interface ImportMetaEnv {
CONFIGS_PATH?: string
PRUSASLICER_PATH?: string
MONGODB?: string
}
interface ImportMeta {

View File

@ -5,7 +5,7 @@
*
* following https://www.rfc-editor.org/rfc/rfc7807.html
*/
export default interface JSONError {
export default interface RFC7807 {
/**
* A URI reference [RFC3986] that identifies the
* problem type.
@ -52,7 +52,7 @@ export default interface JSONError {
instance?: string
}
export function buildRFC7807Error(error: JSONError & Record<string, any>): Response {
export function buildRFC7807(error: RFC7807 & Record<string, any>): Response {
return new Response(JSON.stringify(error), {
headers: {
'Content-Type': 'application/problem+json'

View File

@ -0,0 +1,21 @@
import type APIKey from '.'
import Dao from '../Dao'
export default class APIKeyDao extends Dao<APIKey> {
private idx = 0
public async create(obj: Omit<APIKey, 'id'>): Promise<APIKey | null> {
console.log('pouet', this.idx++)
return null
// throw new Error('Method not implemented.')
}
public async findAll(query?: Partial<APIKey> | undefined): Promise<APIKey[]> {
throw new Error('Method not implemented.')
}
public async update(obj: APIKey): Promise<APIKey | null> {
throw new Error('Method not implemented.')
}
public async delete(obj: APIKey): Promise<boolean> {
throw new Error('Method not implemented.')
}
}

View File

@ -0,0 +1,4 @@
export default interface APIKey {
id: string
user: string
}

18
src/models/Client.ts Normal file
View File

@ -0,0 +1,18 @@
import { MongoClient } from 'mongodb'
import mongoose from 'mongoose'
export default class Client {
private static connectionString = import.meta.env.MONGODB
private static client = false
public static async get() {
if (!this.connectionString) {
throw new Error('Can\'t connect to the database, missing the connection string')
}
if (!this.client) {
mongoose.connect(this.connectionString)
this.client = true
}
return this.client
}
}

View File

@ -0,0 +1,21 @@
import type Config from '.'
import Dao from '../Dao'
export default class ConfigDao extends Dao<Config> {
private idx = 0
public async create(obj: Omit<Config, 'id'>): Promise<Config | null> {
console.log('pouet', this.idx++)
return null
// throw new Error('Method not implemented.')
}
public async findAll(query?: Partial<Config> | undefined): Promise<Config[]> {
throw new Error('Method not implemented.')
}
public async update(obj: Config): Promise<Config | null> {
throw new Error('Method not implemented.')
}
public async delete(obj: Config): Promise<boolean> {
throw new Error('Method not implemented.')
}
}

View File

@ -0,0 +1,6 @@
import type User from '../User'
export default interface Config {
id: string
user: string
}

105
src/models/Dao.ts Normal file
View File

@ -0,0 +1,105 @@
import Client from './Client'
/**
* the Dao is the object that connect the Database or source to the application layer
*
* you MUST call it through the `DaoFactory` file
*/
export default abstract class Dao<Object extends { id: any } = { id: any }> {
/**
* insert a new object into the source
*
* @param obj the object to create
* @returns the object with it's id filled if create or null otherwise
*/
abstract create(obj: Omit<Object, 'id'>): Promise<Object | null>
/**
* insert a new object into the source
*
* @param obj the object to create
* @returns the object with it's id filled if create or null otherwise
*/
public insert: Dao<Object>['create'] = (obj: Parameters<Dao<Object>['create']>[0]) => this.create(obj)
/**
* find the list of objects having elements from the query
*
* @param query a partial object which filter depending on the elements, if not set it will fetch everything
* @returns an array containing the list of elements that match with the query
*/
abstract findAll(query?: Partial<Object>): Promise<Array<Object>>
/**
* find the list of objects having elements from the query
*
* @param query a partial object which filter depending on the elements, if not set it will fetch everything
* @returns an array containing the list of elements that match with the query
*/
public find: Dao<Object>['findAll'] = (query: Parameters<Dao<Object>['findAll']>[0]) => this.findAll(query)
/**
* find an object by it's id
*
* (shortcut to findOne({id: id}))
*
* @param id the id of the object
* @returns
*/
public findById(id: Object['id']): Promise<Object | null> {
return this.findOne({id: id} as Partial<Object>)
}
/**
* find an object by it's id
*
* (shortcut to findOne({id: id}))
*
* @param id the id of the object
* @returns
*/
public get(id: Object['id']) {
return this.findById(id)
}
/**
* find the first element that match `query`
*
* @param query a partial object which filter depending on the elements, if not set it will fetch everything
* @returns the first element matching with the query or null otherwise
*/
public async findOne(query?: Partial<Object>): Promise<Object | null> {
return (await this.findAll(query))[0] ?? null
}
/**
* update the remote reference of the object
*
* note: it will not try to insert an item (use `upsert` to handle this)
*
* @param obj the object to update
* @returns an object if it was able to update or null otherwise
*/
abstract update(obj: Object): Promise<Object | null>
/**
* update the remote reference of the object or create it if not found
* @param obj the object to update/insert
* @returns the object is updated/inserted or null otherwise
*/
public async upsert(object: Object | Omit<Object, 'id'>): Promise<Object | null> {
if ('id' in object) {
return this.update(object)
}
return this.insert(object)
}
/**
* Delete the object
* @param obj the object to delete
*
* @returns if the object was deleted or not (if object is not in db it will return true)
*/
abstract delete(obj: Object): Promise<boolean>
}

63
src/models/DaoFactory.ts Normal file
View File

@ -0,0 +1,63 @@
import Client from './Client'
import ConfigDao from './Config/ConfigDao'
import Dao from './Dao'
import UserDao from './User/UserDao'
/**
* TODO:
* Add to `DaoItem` your model name
* Add to the function `initDao` the Dao
*/
/**
* the different Daos that can be initialized
*
* Touch this interface to define which key is linked to which Dao
*/
interface DaoItem {
config: ConfigDao
user: UserDao
}
/**
* Class to get any DAO
*/
export default class DaoFactory {
/**
* reference of the different Daos for a correct singleton implementation
*/
private static daos: Partial<DaoItem> = {}
/**
* Get a a dao by its key
*
* it will throw an error if no Dao exists linked to the item key
*
* @param key the dao key to get
* @returns the Dao you want as a singleton
*/
public static get<Key extends keyof DaoItem>(key: Key): DaoItem[Key] {
if (!(key in this.daos)) {
const dao = this.initDao(key)
if (!dao) {
throw new Error(`${key} has no valid Dao`)
}
this.daos[key] = dao as DaoItem[Key]
}
return this.daos[key] as DaoItem[Key]
}
/**
* init a dao by its key, it does not care if it exists or not
*
* @param item the element to init
* @returns a new initialized dao or undefined if no dao is linked
*/
private static initDao(item: keyof DaoItem): Dao<any> | undefined {
switch (item) {
case 'config': return new ConfigDao()
case 'user': return new UserDao()
default: return undefined
}
}
}

26
src/models/README.md Normal file
View File

@ -0,0 +1,26 @@
# Models
this folder contains the Application data layer
## Workflow
1. Add a {model}/index.ts contianing your `interface`
2. Add a {model}/{model}Dao.ts containing your DAO that `extends` from `Dao.ts`
3. Add your Dao to the `DaoFactory.ts` file
## **/index.ts
file containing the definition of the model
## **/\*Dao.ts
File containing the implementation of the Dao
## Dao.ts
the Dao.ts is the file each `*Dao.ts` extends from allowing to have a simple, quick and easy to comprehend connectivity
## DaoFactory.ts
The DaoFactory file is the file in which you will have the only direct reference to each `*Dao` files and will be sent from there to the rest of the applicaiton layer

View File

@ -0,0 +1,68 @@
import { objectOmit } from '@dzeio/object-util'
import mongoose, { ObjectId } from 'mongoose'
import User from '.'
import Client from '../Client'
import Dao from '../Dao'
export default class UserDao extends Dao<User> {
private model = mongoose.model('User', new mongoose.Schema({
email: { type: String, required: true }
}, {
timestamps: true
}))
private collection = 'users'
private idx = 0
public async create(obj: Omit<User, 'id' | 'created' | 'updated'>): Promise<User | null> {
await Client.get()
return this.fromSource(await this.model.create(obj))
}
public async findAll(query?: Partial<User> | undefined): Promise<User[]> {
await Client.get()
if (query?.id) {
const item = await this.model.findById(new mongoose.Types.ObjectId(query.id))
if (!item) {
return []
}
return [this.fromSource(item)]
}
const resp = await this.model.find(query ? this.toSource(query as User) : {})
return resp.map(this.fromSource)
}
public async update(obj: User): Promise<User | null> {
await Client.get()
const query = await this.model.updateOne({
_id: new mongoose.Types.ObjectId(obj.id)
}, this.toSource(obj))
if (query.matchedCount >= 1) {
obj.updated = new Date()
return obj
}
return null
// return this.fromSource()
}
public async delete(obj: User): Promise<boolean> {
await Client.get()
const res = await this.model.deleteOne({
_id: new mongoose.Types.ObjectId(obj.id)
})
return res.deletedCount > 0
}
private toSource(obj: User): Omit<User, 'id'> {
return objectOmit(obj, 'id', 'updated', 'created')
}
private fromSource(doc: mongoose.Document<any, any, User>): User {
return {
id: doc._id.toString(),
email: doc.get('email'),
updated: doc.get('updatedAt'),
created: doc.get('createdAt')
}
}
}

6
src/models/User/index.ts Normal file
View File

@ -0,0 +1,6 @@
export default interface User {
id: string
email: string
created: Date
updated: Date
}

View File

@ -7,9 +7,9 @@ import fs from 'node:fs/promises'
import os from 'node:os'
import path from 'node:path/posix'
import { promisify } from 'node:util'
import FilesUtils from '../../libs/FilesUtils'
import { buildRFC7807Error } from '../../libs/HTTPError'
import { getParams } from '../../libs/gcodeUtils'
import FilesUtils from '../../../libs/FilesUtils'
import { buildRFC7807 } from '../../../libs/RFCs/RFC7807'
import { getParams } from '../../../libs/gcodeUtils'
const exec = promisify(execSync)
@ -36,7 +36,7 @@ export const post: APIRoute = async ({ request }) => {
let config = `${import.meta.env.CONFIGS_PATH}/` + configName + '.ini'
if (!await FilesUtils.exists(config)) {
console.log('request finished in error :(', file)
return buildRFC7807Error({
return buildRFC7807({
type: '/missing-config-file',
status: 404,
title: 'Configuration file is missing',
@ -67,14 +67,14 @@ export const post: APIRoute = async ({ request }) => {
console.error(e)
if (line.includes('Objects could not fit on the bed')) {
await fs.rm(stlPath)
return buildRFC7807Error({
return buildRFC7807({
type: '/object-too-large',
status: 413,
title: 'Object is too large'
})
} else if (line.includes('No such file')) {
await fs.rm(stlPath)
return buildRFC7807Error({
return buildRFC7807({
type: '/missing-config-file',
status: 404,
title: 'Configuration file is missing',
@ -82,7 +82,7 @@ export const post: APIRoute = async ({ request }) => {
})
} else if (line.includes('Unknown option')) {
await fs.rm(stlPath)
return buildRFC7807Error({
return buildRFC7807({
type: '/slicer-option-unknown',
status: 400,
title: ' config override doew not exists',
@ -93,7 +93,7 @@ export const post: APIRoute = async ({ request }) => {
line.includes('.dll was not loaded')
) {
await fs.rm(stlPath)
return buildRFC7807Error({
return buildRFC7807({
type: '/slicer-not-found',
status: 408,
title: 'the slicer used to process this file has not been found',
@ -102,7 +102,7 @@ export const post: APIRoute = async ({ request }) => {
})
} else if (line.includes('ETIMEDOUT')) {
await fs.rm(stlPath)
return buildRFC7807Error({
return buildRFC7807({
type: '/timed-out-slicing',
status: 408,
title: 'Timed out slicing file',
@ -110,7 +110,7 @@ export const post: APIRoute = async ({ request }) => {
processingTimeoutMillis: 60000
})
}
return buildRFC7807Error({
return buildRFC7807({
type: '/general-input-output-error',
status: 500,
title: 'General I/O error',
@ -143,7 +143,7 @@ export const post: APIRoute = async ({ request }) => {
if (typeof tmp === 'number') {
price = tmp.toFixed(2)
} else {
return buildRFC7807Error({
return buildRFC7807({
type: '/algorithm-error',
status: 500,
title: 'Algorithm compilation error',
@ -155,7 +155,7 @@ export const post: APIRoute = async ({ request }) => {
}
} catch (e) {
console.dir(e)
return buildRFC7807Error({
return buildRFC7807({
type: '/algorithm-error',
status: 500,
title: 'Algorithm compilation error',

41
test.ts Normal file
View File

@ -0,0 +1,41 @@
import DaoFactory from './src/models/DaoFactory'
(async () => {
// await DaoFactory.get('config').create({user: {id: 'pouet'}})
// await DaoFactory.get('user').create({user: {id: 'pouet'}})
// await DaoFactory.get('config').create({user: {id: 'pouet'}})
// await DaoFactory.get('user').create({user: {id: 'pouet'}})
// await DaoFactory.get('config').create({user: {id: 'pouet'}})
// await DaoFactory.get('config').create({user: {id: 'pouet'}})
// await DaoFactory.get('config').create({user: {id: 'pouet'}})
// await DaoFactory.get('user').create({user: {id: 'pouet'}})
// await DaoFactory.get('config').create({user: {id: 'pouet'}})
// await DaoFactory.get('config').create({user: {id: 'pouet'}})
// await DaoFactory.get('user').create({user: {id: 'pouet'}})
// await DaoFactory.get('user').create({user: {id: 'pouet'}})
const dao = DaoFactory.get('user')
console.log(await dao.create({email: 'pokemon@go.com'}))
const obj = await dao.get('648f82be60a03b7398d36925')
console.log(obj)
if (!obj) {
console.log('no obj :(')
} else {
console.log('object :)', obj)
obj.email += 'jesuisundieu@pokemon.com'
console.log(await dao.update(obj))
}
const toDelete = await dao.findOne({email: 'pokemon@go.com'})
if (toDelete) {
console.log('todelete :)', toDelete)
await dao.delete(toDelete)
}
console.log()
console.log('done')
process.exit(0)
})()
// await mongoose.get('id')
// await fetch(`/api/users/${'id'}`).then((it) => it.json())

View File

@ -1,3 +0,0 @@
{
"extends": "astro/tsconfigs/strict"
}