From cb65a6dfebc306b15de2b89a2563e34b4b171077 Mon Sep 17 00:00:00 2001 From: Dariusz Filipiak Date: Sat, 27 Apr 2024 23:17:51 +0200 Subject: [PATCH] $$$ update $$$ --- .npmignore | 4 +- .vscode/launch.json | 10 +-- package.json | 64 ++++++++------- src/app.ts | 79 +++++++++++++++---- src/app/app.ts | 0 src/app/example/app.context.ts | 54 ------------- src/app/example/session.controller.ts | 25 ------ src/app/example/session.provider.ts | 8 -- src/app/example/session.repository.ts | 11 --- src/app/example/session.ts | 3 - src/app/example/typecode.controller.ts | 6 -- src/app/example/user.controller.ts | 47 ----------- src/app/example/user.ts | 33 -------- src/lib/base-classes/base-abstract-entity.ts | 12 ++- src/lib/base-classes/base-class.ts | 8 +- src/lib/base-classes/base-controller.ts | 5 ++ src/lib/base-classes/base-crud-controller.ts | 3 +- src/lib/base-classes/base.ts | 12 +-- src/lib/create-context.ts | 37 ++------- .../classes/controller-decorator.ts | 3 +- .../decorators/classes/entity-decorator.ts | 3 +- .../decorators/classes/provider-decorator.ts | 5 +- .../classes/repository-decorator.ts | 3 +- .../http/http-methods-decorators.ts | 46 +++-------- .../decorators/http/http-params-decorators.ts | 47 +++++++---- src/lib/dependency-injection/di-container.ts | 12 +-- src/lib/endpoint-context.ts | 35 ++++++-- src/lib/helpers/class-helpers.ts | 50 ++++++++---- src/lib/helpers/firedev-helpers.ts | 2 +- src/lib/index.ts | 11 ++- src/lib/models.ts | 8 +- src/lib/{orm/column.ts => orm.ts} | 6 +- src/lib/symbols.ts | 4 +- src/lib/validators.ts | 23 ++++++ 34 files changed, 299 insertions(+), 380 deletions(-) create mode 100644 src/app/app.ts delete mode 100644 src/app/example/app.context.ts delete mode 100644 src/app/example/session.controller.ts delete mode 100644 src/app/example/session.provider.ts delete mode 100644 src/app/example/session.repository.ts delete mode 100644 src/app/example/session.ts delete mode 100644 src/app/example/typecode.controller.ts delete mode 100644 src/app/example/user.controller.ts delete mode 100644 src/app/example/user.ts rename src/lib/{orm/column.ts => orm.ts} (95%) diff --git a/.npmignore b/.npmignore index b06b2a2d..5027c6e3 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,6 @@ .vscode -dist/ -src/ +/dist +/src /docs /preview /tests diff --git a/.vscode/launch.json b/.vscode/launch.json index f4e90ab5..790b5833 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,7 +4,7 @@ { "type": "node", "request": "launch", - "name": "Launch Server standalone", + "name": "Debug/Start Server", "program": "${workspaceFolder}/run.js", "args": [ "port=4504", @@ -18,7 +18,7 @@ ] }, { - "name": "Start electron app debug", + "name": "Debug/Start Electron", "type": "node", "request": "launch", "protocol": "inspector", @@ -46,10 +46,10 @@ ], "compounds": [ { - "name": "Debug Server + Electron App", + "name": "Debug/Start (Server + Electron)", "configurations": [ - "Launch Server standalone", - "Start electron app debug" + "Debug/Start Server", + "Debug/Start Electron" ] } ] diff --git a/package.json b/package.json index 16c282f3..360d2acc 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "ora": "3.4.0", "socket.io": "2.4.1", "tslib": "~2.3.0", - "tnp": "~16.5.30" + "tnp": "~16.5.41" }, "license": "MIT", "private": false, @@ -110,7 +110,6 @@ "@ngx-formly/material": "6.1.8", "@ngx-translate/core": "15.0.0", "@ngx-translate/http-loader": "8.0.0", - "@parcel/watcher": "2.3.0", "@sweetalert2/ngx-sweetalert2": "12.1.0", "@testdeck/jest": "0.3.3", "@testdeck/mocha": "0.3.3", @@ -148,12 +147,12 @@ "angular-material-css-vars": "5.0.2", "angular-resize-event": "3.2.0", "animate.css": "4.1.1 ", - "any-project-cli": "~16.5.27", + "any-project-cli": "~16.5.28", "axios": "1.3.5", - "background-worker-process": "~16.5.22", + "background-worker-process": "~16.5.23", "base32": "0.0.7", "bcryptjs": "2.4.3", - "better-sqlite3": "7.6.2", + "better-sqlite3": "9.5.0", "body-parser": "1.18.2", "bootstrap": "4.6.2", "buffer-shims": "1.0.0", @@ -197,13 +196,13 @@ "file-saver": "2.0.5", "file-type": "18.5.0", "firedev": "^16", - "firedev-crud": "~16.5.66", - "firedev-crud-deamon": "~16.5.20", - "firedev-ports": "~16.5.22", - "firedev-storage": "~16.5.18", - "firedev-type-sql": "~16.5.18", - "firedev-typeorm": "~16.5.20", - "firedev-ui": "~16.5.19", + "firedev-crud": "~16.5.67", + "firedev-crud-deamon": "~16.5.21", + "firedev-ports": "~16.5.23", + "firedev-storage": "~16.5.19", + "firedev-type-sql": "~16.5.19", + "firedev-typeorm": "~16.5.21", + "firedev-ui": "~16.5.20", "fkill": "6.1.0", "font-awesome": "4.7.0", "form-data": "4.0.0", @@ -220,11 +219,11 @@ "image-focus": "1.2.1", "immer": "10.0.2", "immutable": "4.3.0", - "incremental-compiler": "~16.5.36", + "incremental-compiler": "~16.5.38", "inquirer": "7.3.3", "inquirer-autocomplete-prompt": "1.3.0", "is-elevated": "3.0.0", - "isomorphic-region-loader": "~16.5.20", + "isomorphic-region-loader": "~16.5.21", "istanbul-instrumenter-loader": "2.0.0", "jest": "29.5.0", "jest-date-mock": "1.0.8", @@ -235,8 +234,8 @@ "joi": "17.9.2", "jscodeshift": "0.6.3", "json-stringify-safe": "5.0.1", - "json10": "~16.5.18", - "json10-writer": "~16.5.27", + "json10": "~16.5.19", + "json10-writer": "~16.5.28", "json5": "2.2.1", "json5-writer": "0.2.0", "jszip": "3.10.1", @@ -245,9 +244,9 @@ "localforage": "1.10.0", "lockfile": "1.0.4", "lodash": "4.17.20", - "lodash-walk-object": "~16.5.18", + "lodash-walk-object": "~16.5.19", "lowdb": "1.0.0", - "magic-renamer": "~16.5.19", + "magic-renamer": "~16.5.20", "material-design-icons": "3.0.1", "method-override": "2.3.10", "minimist": "1.2.0", @@ -259,9 +258,9 @@ "ng-in-viewport": "15.0.2", "ng-lock": "16.0.1", "ng-packagr": "16.0.1", - "ng-talkback": "~16.5.19", - "ng2-logger": "~16.5.29", - "ng2-rest": "~16.5.18", + "ng-talkback": "~16.5.20", + "ng2-logger": "~16.5.30", + "ng2-rest": "~16.5.19", "ngx-ace-wrapper": "14.0.0", "ngx-editor": "15.3.0", "ngx-highlightjs": "9.0.0", @@ -274,7 +273,7 @@ "ngx-scrolltop": "6.0.0", "ngx-store": "3.1.1", "ngx-typed-js": "2.1.1", - "node-cli-tester": "~16.5.19", + "node-cli-tester": "~16.5.20", "node-localstorage": "2.1.6", "node-notifier": "6.0.0", "node-polyfill-webpack-plugin": "2.0.1", @@ -300,7 +299,7 @@ "q": "1.5.1", "rallax.js": "2.0.4", "randomcolor": "0.5.3", - "record-replay-req-res-scenario": "~16.5.18", + "record-replay-req-res-scenario": "~16.5.19", "reflect-metadata": "0.1.10", "rimraf": "2.6.2", "rxjs": "~7.8.0", @@ -310,7 +309,7 @@ "sloc": "0.2.0", "sort-package-json": "1.11.0", "sql.js": "1.8.0", - "static-columns": "~16.5.22", + "static-columns": "~16.5.23", "string-similarity": "4.0.2", "sudo-block": "3.0.0", "supertest": "6.3.3", @@ -318,26 +317,25 @@ "systeminformation": "3.45.7", "task.js": "0.1.5", "threads": "1.7.0", - "tnp-cli": "~16.5.18", - "tnp-config": "~16.5.38", - "tnp-core": "~16.6.35", - "tnp-db": "~16.5.19", - "tnp-helpers": "~16.5.29", - "tnp-models": "~16.5.27", + "tnp-cli": "~16.5.19", + "tnp-config": "~16.5.39", + "tnp-core": "~16.6.36", + "tnp-db": "~16.5.20", + "tnp-helpers": "~16.5.30", + "tnp-models": "~16.5.28", "ts-debug": "1.3.0", "ts-loader": "2.3.1", "ts-node": "10.9.1", "tslint": "5.9.1", "turndown": "7.1.2", - "typeorm": "~0.3.10", "typescript": "~5.0.2", - "typescript-class-helpers": "~16.5.28", + "typescript-class-helpers": "~16.5.29", "typescript-formatter": "~7.2.2", "underscore": "1.9.1", "uuid": "8.3.2", "validator": "9.2.0", "video.js": "8.3.0", - "vpn-split": "~16.5.21", + "vpn-split": "~16.5.22", "watch": "1.0.2", "webpack": "~5.80", "webpack-dev-middleware": "~6.0.2", diff --git a/src/app.ts b/src/app.ts index 05eeb81a..85509d04 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,23 +1,14 @@ //#region @notForNpm - //#region imports -import { Firedev } from 'firedev/src'; +import { Firedev } from './lib/index'; import { EMPTY, Observable, catchError, map, of, startWith } from 'rxjs'; import { Helpers, _ } from 'tnp-core/src'; - import { HOST_BACKEND_PORT } from './app.hosts'; - //#region @browser import { NgModule } from '@angular/core'; import { Component, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; //#endregion -import { SessionController } from './app/example/session.controller'; -import { Session } from './app/example/session'; -import { UserController } from './app/example/user.controller'; -import { User } from './app/example/user'; -import { SessionContext, UserContext } from './app/example/app.context'; - //#endregion //#region @browser @@ -52,17 +43,73 @@ export class FiredevComponent implements OnInit { export class FiredevModule { } //#endregion -//#region user entity +//#region user +@Firedev.Entity({ + className: 'User', + createTable: false +}) +class User extends Firedev.Base.AbstractEntity { -//#endregion + //#region @websql + @Firedev.Orm.Column.String() + //#endregion + firstName: string; +} +@Firedev.Controller({ + className: 'UserController', + path: 'users', +}) +class UserController extends Firedev.Base.CrudController { + provider = this.inject(UserProvider); + async initExampleDbData(): Promise { + // console.log({ 'this.provider': this.provider }); + // console.log(this.provider.helloFromUserProvier()); + } + + + @Firedev.Http.GET() + hello(@Firedev.Http.Param.Query('user') user: string): Firedev.Response { + return async (req, res) => { + return 'hello from user controller my dear ' + user; + } + } -async function start(portForBackend?: string) { - // console.log({ portForBackend }) - // console.log('Helpers.isElectron', Helpers.isElectron) - // console.log('Your server will start on port ' + HOST_BACKEND_PORT); +} + +@Firedev.Provider({ + className: 'UserProvider', +}) +class UserProvider extends Firedev.Base.Provider { + + helloFromUserProvier() { + return 'hello from user provider'; + } + +} + +const UserContext = Firedev.createContext({ + host: `http://localhost:${HOST_BACKEND_PORT}`, + entities: { + User, + }, + controllers: { + UserController, + }, + providers: { + UserProvider, + } +}); +//#endregion + + +async function start(portForBackend?: string) { + console.log({ portForBackend }) + console.log('Helpers.isElectron', Helpers.isElectron) + console.log('Your server will start on port ' + HOST_BACKEND_PORT); + console.log(UserContext.ref.allInstances); await UserContext.initialize({ diff --git a/src/app/app.ts b/src/app/app.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/example/app.context.ts b/src/app/example/app.context.ts deleted file mode 100644 index 81206519..00000000 --- a/src/app/example/app.context.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Firedev } from "firedev/src"; -import { HOST_BACKEND_PORT } from "../../app.hosts"; -import { SessionController } from "./session.controller"; -import { Session } from "./session"; -import { UserController } from "./user.controller"; -import { User } from "./user"; -import { SessionRepository } from "./session.repository"; -import { SessionProvider } from "./session.provider"; -import { TypecodesController } from "./typecode.controller"; - -// only here init example data works - -export const TypecodesContext = Firedev.createContext({ - mode: Firedev.Modes.backendServerIpc(), - controllers: { TypecodesController }, -}); - - -export const SessionContext = Firedev.createContext({ - mode: Firedev.Modes.backendServerTcpUdp('http://localhost:' + HOST_BACKEND_PORT), - contexts: { TypecodesContext }, - controllers: { SessionController }, - entities: { Session }, - repositories: { SessionRepository }, - providers: { SessionProvider } -}); - -export const AuthContext = Firedev.createContext({ - mode: Firedev.Modes.backendServerTcpUdp('http://localhost:' + HOST_BACKEND_PORT + 2), - contexts: { SessionContext } -}); - - - -export const UserContext = Firedev.createContext({ - mode: Firedev.Modes.backendServerTcpUdp('http://localhost:' + HOST_BACKEND_PORT + 3), - contexts: { SessionContext }, - controllers: { - UserController, - TypecodesController, - }, - entities: { - User - }, -}); - - -export const ElectronContext = Firedev.createContext({ - mode: Firedev.Modes.backendServerIpc(), - contexts: { UserContext }, -}); - -// const sesion = Firedev.inject(UserContext.contexts.SessionContext.controllers.SessionController); -// const sesion2 = Firedev.inject(UserContext.controllers.SessionController); diff --git a/src/app/example/session.controller.ts b/src/app/example/session.controller.ts deleted file mode 100644 index b100a449..00000000 --- a/src/app/example/session.controller.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Firedev } from "firedev/src"; -import { SessionContext, TypecodesContext, UserContext } from "./app.context"; -import { UserController } from "./user.controller"; -import { TypecodesController } from "./typecode.controller"; - - -export class SessionController extends Firedev.BaseController { - - typecode = this.inject(TypecodesController); - - _() { - // this.typecode = this.inject(TypecodesController); // SessionContext.contexts.TypecodesContext.from(this).inject.controller.TypecodesController - // this.typecode2 = this.inject(TypecodesController); // TypecodesContext.from(UserContext).inject.controller.TypecodesController; - } - - helloFromSession() { - if (SessionContext.ref.isActiveOn(this)) { - - } - // if (Firedev.contextFrom(this)?.equals(SessionContext.internalContext)) { - - // } - return 'hello from session' - } -} diff --git a/src/app/example/session.provider.ts b/src/app/example/session.provider.ts deleted file mode 100644 index fb0034e5..00000000 --- a/src/app/example/session.provider.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Firedev } from "firedev/src"; -import { SessionContext, UserContext } from "./app.context"; - - -export class SessionProvider { - - -} diff --git a/src/app/example/session.repository.ts b/src/app/example/session.repository.ts deleted file mode 100644 index 146660da..00000000 --- a/src/app/example/session.repository.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Firedev, TypeormRepository } from "firedev/src"; -import { Session } from "./session"; - - -export class SessionRepository extends TypeormRepository { - - getId(entity: Session) { - - } - -} diff --git a/src/app/example/session.ts b/src/app/example/session.ts deleted file mode 100644 index 3457ea9b..00000000 --- a/src/app/example/session.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class Session { - -} diff --git a/src/app/example/typecode.controller.ts b/src/app/example/typecode.controller.ts deleted file mode 100644 index e8e89910..00000000 --- a/src/app/example/typecode.controller.ts +++ /dev/null @@ -1,6 +0,0 @@ -export class TypecodesController { - - hello() { - - } -} diff --git a/src/app/example/user.controller.ts b/src/app/example/user.controller.ts deleted file mode 100644 index 712aa4e5..00000000 --- a/src/app/example/user.controller.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Firedev } from "firedev/src"; -import { Helpers } from "tnp-core/src"; -import { SessionContext, UserContext } from "./app.context"; -import { SessionController } from "./session.controller"; -import { User } from "./user"; -import { TypecodesController } from "./typecode.controller"; - -@Firedev.Controller({ className: 'UserController', entity: User }) -export class UserController extends Firedev.Base.Controller { - session: SessionController; - typecodesController: TypecodesController = this.inject(TypecodesController); - - _(): void { - //Called after the constructor, initializing input properties, and the first call to ngOnChanges. - //Add 'implements OnInit' to the class. - this.session = this.inject(SessionController); - - // this.session = SessionContext.from(this).inject.controller.SessionController; - // this.typecodesController = UserContext.types.controllers.TypecodesController; - // this.typecodesController = UserContext.from(this).inject.controller.TypecodesController; - } - - simpleHelo() { - return 'simple helo' - } - - @Firedev.Http.PUT() - helloWorld(@Firedev.Http.Param.Query('id') id: string, @Firedev.Http.Param.Query('test') test: number): Firedev.Response { - //#region @websqlFunc - return async () => { - console.log({ id, test }) - return 'hello world from ' + (Helpers.isElectron && Helpers.isNode) ? 'ipc' : 'http'; - } - //#endregion - } - - - - //#region @websql - async initExampleDbData(): Promise { - // await this.repository.save(User.from({ name: 'Sam' })) - // await this.repository.save(User.from({ name: 'Samuela' })) - console.log('hello from sesion:', this.session.helloFromSession()); - new UserContext.types.entities.User() - } - //#endregion -} diff --git a/src/app/example/user.ts b/src/app/example/user.ts deleted file mode 100644 index 6a0ee862..00000000 --- a/src/app/example/user.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Firedev } from "firedev/src"; -import { _ } from "tnp-core/src"; -import { UserController } from "./user.controller"; -import { UserContext } from "./app.context"; - -// @Firedev.Entity({ className: 'User' }) -export class User { - - static ctrl: UserController - - static _() { - this.ctrl = UserContext.from(this).inject.controller.UserController; - console.log('INTIED', this.ctrl) - } - - static from(user: Partial) { - // return _.merge(new UserContext.types.entities.User(), user); - } - - constructor() { - console.log(UserContext.types.entities.User.ctrl.simpleHelo()) - } - - //#region @websql - @Firedev.Orm.Column.Generated() - //#endregion - id?: string | number; - - //#region @websql - @Firedev.Orm.Column.Custom({ type: 'varchar', length: 100 }) - //#endregion - name?: string; -} diff --git a/src/lib/base-classes/base-abstract-entity.ts b/src/lib/base-classes/base-abstract-entity.ts index 238dd65a..0c3ea9f6 100644 --- a/src/lib/base-classes/base-abstract-entity.ts +++ b/src/lib/base-classes/base-abstract-entity.ts @@ -1,11 +1,15 @@ -import { EndpointContext } from "../endpoint-context"; -import { Symbols } from "../symbols"; +import { Orm } from "../orm"; import { BaseEntity } from "./base-entity"; +export abstract class BaseAbstractEntity extends BaseEntity { -export class BaseAbstractEntity extends BaseEntity { - + //#region @websql + @Orm.Column.Generated() + //#endregion id: string; + //#region @websql + @Orm.Column.Version() + //#endregion version: number; } diff --git a/src/lib/base-classes/base-class.ts b/src/lib/base-classes/base-class.ts index fa5d6f09..9f068c7e 100644 --- a/src/lib/base-classes/base-class.ts +++ b/src/lib/base-classes/base-class.ts @@ -3,13 +3,19 @@ import { Symbols } from "../symbols"; export class BaseClass { + get __endpoint_context__() { + return this[Symbols.ctxInClassOrClassObj] as EndpointContext; + } + inject(ctor: new (...args: any[]) => T): T { return new Proxy({}, { get: (_, propName) => { - const res = this[Symbols.ctxInClassOrClassObj] as EndpointContext; + const res = this.__endpoint_context__; let instance: T = res.inject(ctor); return typeof instance[propName] === 'function' ? instance[propName].bind(instance) : instance[propName]; }, }) as T; } + + } diff --git a/src/lib/base-classes/base-controller.ts b/src/lib/base-classes/base-controller.ts index 635a2324..18edce91 100644 --- a/src/lib/base-classes/base-controller.ts +++ b/src/lib/base-classes/base-controller.ts @@ -4,6 +4,11 @@ import { BaseClass } from "./base-class"; export class BaseController extends BaseClass { + /** + * @deprecated + */ + async initExampleDbData() { + } } diff --git a/src/lib/base-classes/base-crud-controller.ts b/src/lib/base-classes/base-crud-controller.ts index 96df6fc6..00b4e22d 100644 --- a/src/lib/base-classes/base-crud-controller.ts +++ b/src/lib/base-classes/base-crud-controller.ts @@ -3,8 +3,9 @@ import { Symbols } from "../symbols"; import { BaseController } from "./base-controller"; -export class BaseCrudController extends BaseController { +export class BaseCrudController extends BaseController { constructor(__entity: Function) { super(); } + } diff --git a/src/lib/base-classes/base.ts b/src/lib/base-classes/base.ts index 23f8c7ce..2bfd783f 100644 --- a/src/lib/base-classes/base.ts +++ b/src/lib/base-classes/base.ts @@ -6,12 +6,12 @@ import * as repository from './base-repository'; import * as provider from './base-provider'; export namespace Base { - export import Controller = controller; - export import CrudController = crudController; - export import Entity = entity; - export import AbstractEntity = abstractEntity; - export import Provider = provider; + export import Controller = controller.BaseController; + export import CrudController = crudController.BaseCrudController; + export import Entity = entity.BaseEntity; + export import AbstractEntity = abstractEntity.BaseAbstractEntity; + export import Provider = provider.BaseProvider; //#region @websql - export import Repository = repository; + export import Repository = repository.BaseRepository; //#endregion } diff --git a/src/lib/create-context.ts b/src/lib/create-context.ts index daae5417..b52146ff 100644 --- a/src/lib/create-context.ts +++ b/src/lib/create-context.ts @@ -24,29 +24,6 @@ export const createContext = < get ref() { return ref; }, - // from(instanceOrContext) { - // let currentCtx: ContextRef = instanceOrContext[Symbols.ctxInClassOrClassObj] ? instanceOrContext[Symbols.ctxInClassOrClassObj] : ref; - - // if ((instanceOrContext as ReturnType)?.ref) { - // currentCtx = (instanceOrContext as ReturnType).ref; - // } - - // const controller = currentCtx.getClassInstanceObjBy(Models.ClassType.CONTROLLER) as { - // [K in keyof CTRL]: InstanceType; - // }; - - // const repository = currentCtx.getClassInstanceObjBy(Models.ClassType.REPOSITORY) as { - // [K in keyof REPO]: InstanceType; - // }; - - // const provider = currentCtx.getClassInstanceObjBy(Models.ClassType.PROVIDER) as { - // [K in keyof PROVIDER]: InstanceType; - // }; - - // return { - // inject: { controller, repository, provider } - // } - // }, /** * - create controller instances for context * - init database (if enable) + migation scripts @@ -57,21 +34,19 @@ export const createContext = < beforeDbInited && await Helpers.runSyncOrAsync({ functionFn: beforeDbInited, }); + ref.initializeMetadata(); await ref.reinitControllersData(); afterDbInited && await Helpers.runSyncOrAsync({ functionFn: afterDbInited }); }, - // /** - // * @deprecated - // * dynamically overwrite host for context - // */ - // setCommunicationMode(mode: ExternalMode) { - // ref.mode = mode; - // }, }; - Helpers.info(`Create context on thost: ${ref.mode.host}`); + if (ref.remoteHost) { + Helpers.info(`Create context on remote host: ${ref.remoteHost}`); + } else { + Helpers.info(`Create context on thost: ${ref.host}`); + } return res; } //#endregion diff --git a/src/lib/decorators/classes/controller-decorator.ts b/src/lib/decorators/classes/controller-decorator.ts index e28c18a7..958644ee 100644 --- a/src/lib/decorators/classes/controller-decorator.ts +++ b/src/lib/decorators/classes/controller-decorator.ts @@ -17,7 +17,8 @@ export function FiredevController(options?: FiredevControllerOptions) { //#endregion ClassHelpers.setName(constructor, options?.className); - ClassHelpers.setOptionsForConstructor(Symbols.metadata.options.controller, options, constructor); + Reflect.defineMetadata(Symbols.metadata.options.controller, options, constructor); + Reflect.defineMetadata(Symbols.metadata.className, options?.className || constructor.name, constructor); }; } diff --git a/src/lib/decorators/classes/entity-decorator.ts b/src/lib/decorators/classes/entity-decorator.ts index e88146c4..104c4b2e 100644 --- a/src/lib/decorators/classes/entity-decorator.ts +++ b/src/lib/decorators/classes/entity-decorator.ts @@ -32,7 +32,8 @@ export function FiredevEntity(options?: FiredevEntityOptions) { } //#endregion - ClassHelpers.setOptionsForConstructor(Symbols.metadata.options.entity, options, constructor); + Reflect.defineMetadata(Symbols.metadata.options.entity, options, constructor); + Reflect.defineMetadata(Symbols.metadata.className, options?.className || constructor.name, constructor); }; } diff --git a/src/lib/decorators/classes/provider-decorator.ts b/src/lib/decorators/classes/provider-decorator.ts index f2b6254d..7dc87bbf 100644 --- a/src/lib/decorators/classes/provider-decorator.ts +++ b/src/lib/decorators/classes/provider-decorator.ts @@ -4,10 +4,11 @@ import { Models } from "../../models"; export function FiredevProvider(options?: FiredevProviderOptions) { return function (constructor: Function) { - ClassHelpers.setOptionsForConstructor(Symbols.metadata.options.provider, options, constructor); + Reflect.defineMetadata(Symbols.metadata.options.provider, options, constructor); + Reflect.defineMetadata(Symbols.metadata.className, options?.className || constructor.name, constructor); }; } export interface FiredevProviderOptions extends Models.DecoratorAbstractOpt { - global: boolean; + global?: boolean; } diff --git a/src/lib/decorators/classes/repository-decorator.ts b/src/lib/decorators/classes/repository-decorator.ts index bedd019d..8b43f4a1 100644 --- a/src/lib/decorators/classes/repository-decorator.ts +++ b/src/lib/decorators/classes/repository-decorator.ts @@ -9,7 +9,8 @@ import { _ } from 'tnp-core/src'; export function FiredevRepository(options: FiredevRepositoryOptions) { return function (constructor: Function) { EntityRepository(options.entity)(constructor) - ClassHelpers.setOptionsForConstructor(Symbols.metadata.options.repository, options, constructor); + Reflect.defineMetadata(Symbols.metadata.options.repository, options, constructor); + Reflect.defineMetadata(Symbols.metadata.className, options?.className || constructor.name, constructor); }; } diff --git a/src/lib/decorators/http/http-methods-decorators.ts b/src/lib/decorators/http/http-methods-decorators.ts index 4f76ea9a..a1a53310 100644 --- a/src/lib/decorators/http/http-methods-decorators.ts +++ b/src/lib/decorators/http/http-methods-decorators.ts @@ -1,14 +1,15 @@ import { CoreModels, _ } from 'tnp-core/src'; import { Models } from '../../models'; import { CLASS } from 'typescript-class-helpers/src'; +import { Symbols } from '../../symbols'; import { Models as ModelsNg2Rest } from 'ng2-rest/src'; - -const defaultResponseType = 'text or JSON'; +; const metaReq = ( method: Models.Http.Rest.HttpMethod, path: string, - target: Function, propertyKey: string, + target: Function, + propertyKey: string, descriptor: PropertyDescriptor, pathOrOptions: string | FiredevHttpDecoratorOptions, pathIsGlobal: boolean, @@ -24,16 +25,12 @@ const metaReq = ( } const { overrideContentType, overridResponseType } = options; - // const className = CLASS.getName(target.constructor); - - const config = CLASS.getConfig(target.constructor as any); - // if (config.vChildren.length > 0) { - // } - config.methods[propertyKey] = ( - !config.methods[propertyKey] ? new Models.MethodConfig() : config.methods[propertyKey] - ) as Models.MethodConfig; - const methodConfig: Models.MethodConfig = config.methods[propertyKey]; + let methodConfig: Models.MethodConfig = Reflect.getMetadata(Symbols.metadata.options.controllerMethod, target.constructor, propertyKey); + if (!methodConfig) { + methodConfig = new Models.MethodConfig(); + Reflect.defineMetadata(Symbols.metadata.options.controllerMethod, methodConfig, target.constructor, propertyKey); + } methodConfig.methodName = propertyKey; methodConfig.type = method; @@ -47,8 +44,7 @@ const metaReq = ( } } } - methodConfig.path = `/${propertyKey}${paramsPathConcatedPath}` - // console.log(`Authogenerated path: `, m.path) + methodConfig.path = `/${propertyKey}${paramsPathConcatedPath}`; } else { methodConfig.path = path; } @@ -57,28 +53,10 @@ const metaReq = ( methodConfig.global = pathIsGlobal; methodConfig.contentType = overrideContentType; methodConfig.responseType = overridResponseType; - checkIfMethodsWithReponseTYpeAlowed(_.values(config.methods).filter(f => f !== methodConfig), methodConfig) + Reflect.defineMetadata(Symbols.metadata.options.controllerMethod, methodConfig, target.constructor, propertyKey); + // console.log('methods updated', methodConfig); } -function checkIfMethodsWithReponseTYpeAlowed(methods: Models.MethodConfig[], current: Models.MethodConfig) { - if (!current.responseType) { - return; - } - for (let index = 0; index < methods.length; index++) { - const m = methods[index]; - if (m.path === current.path && m.responseType !== current.responseType) { - throw new Error(` -[firedev] you can have 2 methods with same path but differetn reponseType-s - - ${(m.methodName)}( ... path: ${m.path} ) -> responseType: ${m.responseType || defaultResponseType} - ${(current.methodName)}( ... path: ${current.path} ) -> responseType: ${current.responseType} - - Please change path name on of the methods. - - `) - } - } -} export interface FiredevHttpDecoratorOptions { path?: string; diff --git a/src/lib/decorators/http/http-params-decorators.ts b/src/lib/decorators/http/http-params-decorators.ts index 975a383f..b65744e5 100644 --- a/src/lib/decorators/http/http-params-decorators.ts +++ b/src/lib/decorators/http/http-params-decorators.ts @@ -1,46 +1,59 @@ import { Models } from '../../models'; -import { CLASS } from 'typescript-class-helpers/src'; +import { Symbols } from '../../symbols'; -function metaParam(param: Models.Http.Rest.ParamType, name: string, expire: number, defaultValue = undefined, ...args: any[]) { - const methodName = args[1]; - const config = CLASS.getConfig(args[0].constructor); - const m = config.methods[methodName] = (!config.methods[methodName] ? new Models.MethodConfig() : config.methods[methodName]); +function metaParam( + param: Models.Http.Rest.ParamType, + name: string, + expire: number, + defaultValue = undefined, + target: Function, + propertyKey: string | symbol, + parameterIndex: number, +) { + + let methodConfig: Models.MethodConfig = Reflect.getMetadata(Symbols.metadata.options.controllerMethod, target.constructor, propertyKey); + if (!methodConfig) { + methodConfig = new Models.MethodConfig(); + Reflect.defineMetadata(Symbols.metadata.options.controllerMethod, methodConfig, target.constructor, propertyKey); + } const nameKey = name ? name : param; - const p = m.parameters[nameKey] = (!m.parameters[nameKey] ? new Models.ParamConfig() : m.parameters[nameKey]); - p.index = args[2]; + const p = methodConfig.parameters[nameKey] = (!methodConfig.parameters[nameKey] ? new Models.ParamConfig() : methodConfig.parameters[nameKey]); + p.index = parameterIndex; p.paramName = name; p.paramType = param; p.defaultType = defaultValue; p.expireInSeconds = expire; + Reflect.defineMetadata(Symbols.metadata.options.controllerMethod, methodConfig, target.constructor, propertyKey); + // console.log('params updated', methodConfig); } export function Path(name: string) { - return function (...args: any[]) { - metaParam('Path', name, undefined, {}, ...args) + return function (target: any, propertyKey: string | symbol, parameterIndex: number) { + metaParam('Path', name, undefined, {}, target, propertyKey, parameterIndex); }; } export function Query(name?: string) { - return function (...args: any[]) { - metaParam('Query', name, undefined, {}, ...args) + return function (target: any, propertyKey: string | symbol, parameterIndex: number) { + metaParam('Query', name, undefined, {}, target, propertyKey, parameterIndex); }; } export function Cookie(name: string, expireInSecond: number = 3600) { - return function (...args: any[]) { - metaParam('Cookie', name, expireInSecond, {}, ...args) + return function (target: any, propertyKey: string | symbol, parameterIndex: number) { + metaParam('Cookie', name, expireInSecond, {}, target, propertyKey, parameterIndex); }; } export function Header(name?: string) { - return function (...args: any[]) { - metaParam('Header', name, undefined, {}, ...args) + return function (target: any, propertyKey: string | symbol, parameterIndex: number) { + metaParam('Header', name, undefined, {}, target, propertyKey, parameterIndex); }; } export function Body(name?: string) { - return function (...args: any[]) { - metaParam('Body', name, undefined, {}, ...args) + return function (target: any, propertyKey: string | symbol, parameterIndex: number) { + metaParam('Body', name, undefined, {}, target, propertyKey, parameterIndex); }; } diff --git a/src/lib/dependency-injection/di-container.ts b/src/lib/dependency-injection/di-container.ts index f2d14af4..607a6f11 100644 --- a/src/lib/dependency-injection/di-container.ts +++ b/src/lib/dependency-injection/di-container.ts @@ -1,28 +1,28 @@ -class DIContainer { +export class DIFiredevContainer { private static instances = new Map(); static resolve(target: Function): T { - if (DIContainer.instances.has(target)) { - return DIContainer.instances.get(target); + if (DIFiredevContainer.instances.has(target)) { + return DIFiredevContainer.instances.get(target); } // const tokens = Reflect.getMetadata('design:paramtypes', target) || []; const injections = []; // tokens.map(token => Container.inject(token)); const instance = new (target as any)(...injections); - DIContainer.instances.set(target, instance); + DIFiredevContainer.instances.set(target, instance); return instance; } static inject(target: new (...args: any[]) => T): T { return new Proxy({}, { get: (_, propName) => { - let instance: T = DIContainer.instances.get(target) || DIContainer.resolve(target); + let instance: T = DIFiredevContainer.instances.get(target) || DIFiredevContainer.resolve(target); return typeof instance[propName] === 'function' ? instance[propName].bind(instance) : instance[propName]; }, set: (_, propName, value) => { - let instance: T = DIContainer.instances.get(target) || DIContainer.resolve(target); + let instance: T = DIFiredevContainer.instances.get(target) || DIFiredevContainer.resolve(target); instance[propName] = value; return true; } diff --git a/src/lib/endpoint-context.ts b/src/lib/endpoint-context.ts index e27f4f22..02556d80 100644 --- a/src/lib/endpoint-context.ts +++ b/src/lib/endpoint-context.ts @@ -3,11 +3,13 @@ import { ClassHelpers } from "./helpers/class-helpers"; import { Symbols } from "./symbols"; import { _, Helpers } from 'tnp-core'; import type { createContext } from './create-context'; +import { DIFiredevContainer } from "./dependency-injection/di-container"; +import { FiredevControllerOptions } from "./decorators/classes/controller-decorator"; export class EndpointContext { //#region fields - private readonly allInstances = {}; + public readonly allInstances = {}; private readonly classInstancesByNameObj = {}; private readonly objWithClassesInstancesArr = {}; @@ -72,7 +74,7 @@ export class EndpointContext { }): T => { // Return a new class that extends the base class return class extends BaseClass { - static [Symbols.classNameProperty] = className; + static [Symbols.classNameStaticProperty] = className; static [Symbols.ctxInClassOrClassObj] = ctx; [Symbols.ctxInClassOrClassObj] = ctx; // You can override prototype properties or methods here if needed @@ -98,7 +100,12 @@ export class EndpointContext { // console.log(Object.keys(classesInput)) for (const key of Object.keys(classesInput || {})) { const BaseClass = classesInput[key]; - const className = ClassHelpers.getName(BaseClass) || key; + + let className = Reflect.getMetadata(Symbols.metadata.className, BaseClass); + // console.log('Metadata className', className, BaseClass); + className = className || key; + BaseClass[Symbols.classNameStaticProperty] = className; + const clonedClass = this.cloneClassWithNewMetadata({ BaseClass, className, @@ -139,7 +146,8 @@ export class EndpointContext { //#region methods & getters / inject inject(ctor: new (...args: any[]) => T): T { - return this.allInstances[ClassHelpers.getName(ctor)]; + const className = ClassHelpers.getName(ctor); + return this.allInstances[className]; } //#endregion @@ -156,14 +164,18 @@ export class EndpointContext { return this.config.repositories } } + + getClassFunByArr(classType: Models.ClassType) { + return Object.values(this.getClassFunBy(classType)) as Function[]; + } //#endregion //#region methods & getters / create class instances private createInstances(classes: any, classType: Models.ClassType, initOnlyStaticClassFn = false) { for (const classFn of [...this.getRecrusiveClassesfromContexts(classType), ...Object.values(classes)]) { - const instance = DIContainer.resolve(classFn as any) as any; + const instance = DIFiredevContainer.resolve(classFn as any) as any; const classInstancesByNameObj = this.classInstancesByNameObj[classType]; - const className = classFn[Symbols.classNameProperty]; + const className = ClassHelpers.getName(classFn); // console.log({ classFn, classType, instance, place, className, 'classInstancesByNameObj': this.classInstancesByNameObj }); classInstancesByNameObj[className] = instance; this.objWithClassesInstancesArr[classType].push(instance); @@ -220,9 +232,18 @@ export class EndpointContext { //#region methods & getters / is active on isActiveOn(classInstance: object): boolean { - let contextRef: ContextRef = classInstance[Symbols.ctxInClassOrClassObj]; + let contextRef: EndpointContext = classInstance[Symbols.ctxInClassOrClassObj]; return this === contextRef; } //#endregion + + initializeMetadata() { + for (const controllerClassFn of this.getClassFunByArr(Models.ClassType.CONTROLLER)) { + const opt = ClassHelpers.getAllMetadataForController(controllerClassFn); + console.log('opt', opt) + // @LAST calcualte path + } + } + } diff --git a/src/lib/helpers/class-helpers.ts b/src/lib/helpers/class-helpers.ts index 957b4925..b54ac8b6 100644 --- a/src/lib/helpers/class-helpers.ts +++ b/src/lib/helpers/class-helpers.ts @@ -1,36 +1,58 @@ +import { Symbols } from '../symbols'; import { Validators } from '../validators'; +import { _ } from 'tnp-core'; +import { Models } from '../models'; +import { FiredevControllerOptions } from '../decorators/classes/controller-decorator'; +import { CLASS } from 'typescript-class-helpers/src'; export namespace ClassHelpers { //#region get name export const getName = (classFnOrObject: any): string => { - throw '' + return (classFnOrObject[Symbols.classNameStaticProperty] + ? classFnOrObject[Symbols.classNameStaticProperty] + : classFnOrObject?.constructor[Symbols.classNameStaticProperty]) || void 0; }; //#endregion //#region get name - export const setName = (target: Function, className: string): string => { + export const setName = (target: Function, className: string): void => { Validators.classNameVlidation(className, target); - throw '' + target[Symbols.classNameStaticProperty] = className; }; //#endregion //#region has parent with class name - export const hasParentClassWithName = (target: Function, name: string, targets = []): boolean => { - throw ''; - } - //#endregion + export const hasParentClassWithName = (target: Function, className: string, targets = []): boolean => { + if (!target) { + return false; + } + targets.push(target) + let targetProto = Object.getPrototypeOf(target); - //#region get options from class fn - export const getOptionsFromClassFn = (targetClassFn: Function, key): Opt | undefined => { - // Retrieve the options using reflect-metadata - return Reflect.getMetadata(key, targetClassFn); + if (_.isFunction(targetProto) && ClassHelpers.getName(targetProto) === className) { + // console.log(`true "${_.first(targets).name}" for ${targets.map(d => d.name).join(',')}`) + return true; + } + return hasParentClassWithName(targetProto, className, targets); } //#endregion - //#region set options for constructor - export const setOptionsForConstructor = (key: string, options: any, constructor) => { - Reflect.defineMetadata(key, options, constructor); + //#region get all metadata for controller + export const getAllMetadataForController = (target: Function): Models.ControllerConfig | undefined => { + const classMetadataOptions: FiredevControllerOptions = Reflect.getMetadata(Symbols.metadata.options.controller, target); + const classMetadata: Models.ControllerConfig = _.merge(new Models.ControllerConfig(), classMetadataOptions); + + // Iterate over all methods of the class + const methodNames = CLASS.getMethodsNames(target); // Object.getOwnPropertyNames(target.prototype); + // console.log('methodNames', methodNames) + for (const methodName of methodNames) { + const methodMetadata: Models.MethodConfig = Reflect + .getMetadata(Symbols.metadata.options.controllerMethod, target, methodName); + // console.log('methodMetadata for ' + methodName, methodMetadata) + classMetadata.methods[methodName] = methodMetadata; + } + return classMetadata; } //#endregion diff --git a/src/lib/helpers/firedev-helpers.ts b/src/lib/helpers/firedev-helpers.ts index 61f553fd..21e52094 100644 --- a/src/lib/helpers/firedev-helpers.ts +++ b/src/lib/helpers/firedev-helpers.ts @@ -68,7 +68,7 @@ export namespace FiredevHelpers { //#endregion //#region get expores path - export const getExpressPath = (c: Models.ClassConfig, pathOrClassConfig: Models.MethodConfig | string) => { + export const getExpressPath = (c: Models.ControllerConfig, pathOrClassConfig: Models.MethodConfig | string) => { if (typeof pathOrClassConfig === 'string') return `${c.calculatedPath}${pathOrClassConfig}`.replace(/\/$/, '') return `${c.calculatedPath}${pathOrClassConfig.path}`.replace(/\/$/, '') } diff --git a/src/lib/index.ts b/src/lib/index.ts index 67fa35d0..8cdcfd48 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -4,13 +4,18 @@ import * as base from './base-classes/base'; import * as controllerDecorator from './decorators/classes/controller-decorator'; import * as entityDecorator from './decorators/classes/entity-decorator'; import * as providerDecorator from './decorators/classes/provider-decorator'; +import * as createContextFn from './create-context'; +import * as orm from './orm'; +import * as models from './models'; export namespace Firedev { - export import Http = http; - export import Base = base; + export import Response = models.Models.Http.Response; + export import Http = http.Http; + export import Base = base.Base; export import Controller = controllerDecorator.FiredevController; export import Entity = entityDecorator.FiredevEntity; export import Provider = providerDecorator.FiredevProvider; - + export const createContext = createContextFn.createContext; + export import Orm = orm.Orm; } diff --git a/src/lib/models.ts b/src/lib/models.ts index cb9eaa13..12df4058 100644 --- a/src/lib/models.ts +++ b/src/lib/models.ts @@ -3,6 +3,7 @@ import { Response, RequestHandler } from 'express'; import { Response as ExpressResponse, Request as ExpressRequest } from 'express'; import { Models as ModelsNg2Rest } from 'ng2-rest/src'; import { ClassHelpers } from "./helpers/class-helpers"; +import { FiredevControllerOptions } from "./decorators/classes/controller-decorator"; export namespace Models { @@ -71,11 +72,10 @@ export namespace Models { //#endregion //#region models / class config - export class ClassConfig { + export class ControllerConfig implements FiredevControllerOptions { + realtime?: boolean; calculatedPath: string; path: string; - vChildren?: ClassConfig[] = []; - vParent?: ClassConfig; className?: string; uniqueKey?: string; methods: { [methodName: string]: MethodConfig } = {}; @@ -83,7 +83,7 @@ export namespace Models { //#endregion export interface DecoratorAbstractOpt { - className: string; + className?: string; } //#region models / http diff --git a/src/lib/orm/column.ts b/src/lib/orm.ts similarity index 95% rename from src/lib/orm/column.ts rename to src/lib/orm.ts index eb01c43d..5f26a252 100644 --- a/src/lib/orm/column.ts +++ b/src/lib/orm.ts @@ -1,9 +1,8 @@ - //#region @websql import * as tsorm from 'firedev-typeorm/src' //#endregion - +//#region orm export namespace Orm { //#region @websql export const Repository = tsorm.Repository; @@ -34,6 +33,7 @@ export namespace Orm { export import UpdateDate = tsorm.UpdateDateColumn export import DeleteDate = tsorm.DeleteDateColumn export import Custom = tsorm.Column; + export const String = () => tsorm.Column({ type: 'string', nullable: true }); export const SimpleJson = () => tsorm.Column({ type: 'simple-json', nullable: true }); export const Boolean = (defaultValue: boolean) => tsorm.Column({ type: 'boolean', default: defaultValue }); @@ -56,3 +56,5 @@ export namespace Orm { } //#endregion } + +//#endregion diff --git a/src/lib/symbols.ts b/src/lib/symbols.ts index e4aa6c32..da768806 100644 --- a/src/lib/symbols.ts +++ b/src/lib/symbols.ts @@ -2,11 +2,13 @@ import { _ } from 'tnp-core/src'; export namespace Symbols { export const ctxInClassOrClassObj = Symbol(); - export const classNameProperty = '$$className$$'; + export const classNameStaticProperty = '$$className$$'; export const metadata = { + className: 'class:realname', options: { controller: 'controller:options', + controllerMethod: 'controller:method:options', entity: 'entity:options', repository: 'repository:options', provider: 'provider:options', diff --git a/src/lib/validators.ts b/src/lib/validators.ts index f85456e2..c547e9d5 100644 --- a/src/lib/validators.ts +++ b/src/lib/validators.ts @@ -1,4 +1,5 @@ import { _ } from 'tnp-core/src' +import { Models } from './models'; export namespace Validators { export const classNameVlidation = (className, target: Function) => { @@ -29,4 +30,26 @@ export namespace Validators { return _.isUndefined(className) ? target.name : className; } + export const checkIfMethodsWithReponseTYpeAlowed = (methods: Models.MethodConfig[], current: Models.MethodConfig) => { + + const defaultResponseType = 'text or JSON' + if (!current.responseType) { + return; + } + for (let index = 0; index < methods.length; index++) { + const m = methods[index]; + if (m.path === current.path && m.responseType !== current.responseType) { + throw new Error(` + [firedev] you can have 2 methods with same path but differetn reponseType-s + + ${(m.methodName)}( ... path: ${m.path} ) -> responseType: ${m.responseType || defaultResponseType} + ${(current.methodName)}( ... path: ${current.path} ) -> responseType: ${current.responseType} + + Please change path name on of the methods. + + `) + } + } + } + }