├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .github
├── ISSUE_TEMPLATE
│ ├── BUG_REPORT.md
│ ├── FEATURE_REQUEST.md
│ └── SUPPORT_QUESTION.md
├── lock.yml
├── pull_request_template.md
└── workflows
│ └── nodejs.yml
├── .gitignore
├── .huskyrc
├── .npmignore
├── AUTHORS
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── README_en.md
├── assets
└── logo.png
├── benchmarks
├── README.md
├── daze-with-1000-routes.js
├── daze-without-routes.js
├── express-with-1000-routes.js
├── express-without-routes.js
├── koa-with-1000-routes.js
└── koa-without-routes.js
├── commitlint.config.js
├── example
├── daze
├── src
│ ├── app
│ │ ├── agent.ts
│ │ ├── example.controller.ts
│ │ ├── example.entity.ts
│ │ └── schedule.ts
│ ├── config
│ │ ├── app.dev.ts
│ │ ├── app.ts
│ │ ├── cache.ts
│ │ ├── database.ts
│ │ ├── proxy.ts
│ │ └── redis.ts
│ ├── example.provider.ts
│ └── index.ts
└── tsconfig.json
├── jest.config.js
├── lerna.json
├── package-lock.json
├── package.json
├── packages
├── cli
│ ├── CHANGELOG.md
│ ├── __tests__
│ │ └── nill.spec.ts
│ ├── g.d.ts
│ ├── jest.config.js
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ ├── actions
│ │ │ ├── build.ts
│ │ │ ├── create.ts
│ │ │ ├── dev.ts
│ │ │ ├── index.ts
│ │ │ ├── make.ts
│ │ │ ├── routes.ts
│ │ │ └── tpl-action.abstract.ts
│ │ ├── bin
│ │ │ └── daze.ts
│ │ ├── commands
│ │ │ ├── build.ts
│ │ │ ├── create.ts
│ │ │ ├── dev.ts
│ │ │ ├── index.ts
│ │ │ ├── make.ts
│ │ │ └── routes.ts
│ │ ├── config.interface.ts
│ │ ├── defaultTsConfig.json
│ │ ├── index.ts
│ │ └── lib
│ │ │ ├── config.ts
│ │ │ ├── constants.ts
│ │ │ ├── index.ts
│ │ │ ├── init.ts
│ │ │ ├── printer.ts
│ │ │ ├── question.ts
│ │ │ ├── render.ts
│ │ │ ├── runner
│ │ │ ├── index.ts
│ │ │ ├── npm.ts
│ │ │ ├── pnpm.ts
│ │ │ ├── runner.ts
│ │ │ └── yarn.ts
│ │ │ └── ts_compile.ts
│ ├── template
│ │ └── application
│ │ │ ├── .gitignore
│ │ │ ├── daze
│ │ │ ├── package.json
│ │ │ ├── public
│ │ │ └── .keep
│ │ │ ├── src
│ │ │ ├── app
│ │ │ │ └── example.controller.ts
│ │ │ ├── config
│ │ │ │ ├── app.ts
│ │ │ │ ├── cache.ts
│ │ │ │ ├── cookie.ts
│ │ │ │ ├── database.ts
│ │ │ │ ├── logger.ts
│ │ │ │ ├── redis.ts
│ │ │ │ └── session.ts
│ │ │ └── index.ts
│ │ │ ├── tsconfig.json
│ │ │ └── views
│ │ │ └── hello.html
│ └── tsconfig.json
├── create-app
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jest.config.js
│ ├── package.json
│ ├── src
│ │ └── create.ts
│ └── tsconfig.json
├── framework
│ ├── .npmignore
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── README_en.md
│ ├── __tests__
│ │ ├── common
│ │ │ ├── assets
│ │ │ │ └── example.txt
│ │ │ └── context.ts
│ │ ├── daze
│ │ │ ├── logs
│ │ │ │ └── .keep
│ │ │ ├── src
│ │ │ │ ├── app
│ │ │ │ │ ├── component
│ │ │ │ │ │ ├── InjectComponent.ts
│ │ │ │ │ │ └── TestLogger.ts
│ │ │ │ │ ├── controller
│ │ │ │ │ │ ├── autoinject.ts
│ │ │ │ │ │ ├── cross.ts
│ │ │ │ │ │ ├── csrf.ts
│ │ │ │ │ │ ├── dto
│ │ │ │ │ │ │ └── daze.dto.ts
│ │ │ │ │ │ ├── example.ts
│ │ │ │ │ │ ├── injectable.ts
│ │ │ │ │ │ ├── middleware.ts
│ │ │ │ │ │ ├── redirect.ts
│ │ │ │ │ │ └── routes.ts
│ │ │ │ │ ├── entities
│ │ │ │ │ │ ├── comment.ts
│ │ │ │ │ │ ├── profile.ts
│ │ │ │ │ │ ├── role.ts
│ │ │ │ │ │ └── user.ts
│ │ │ │ │ ├── middleware
│ │ │ │ │ │ ├── example-1.ts
│ │ │ │ │ │ ├── example-2.ts
│ │ │ │ │ │ └── example-order.ts
│ │ │ │ │ └── service
│ │ │ │ │ │ ├── example.ts
│ │ │ │ │ │ └── injectable.ts
│ │ │ │ ├── config
│ │ │ │ │ ├── app.test.ts
│ │ │ │ │ ├── app.ts
│ │ │ │ │ ├── cookie.ts
│ │ │ │ │ ├── custom.test.ts
│ │ │ │ │ ├── custom.ts
│ │ │ │ │ ├── database.ts
│ │ │ │ │ ├── daze.ts
│ │ │ │ │ ├── logger.ts
│ │ │ │ │ └── session.ts
│ │ │ │ ├── logs
│ │ │ │ └── provider
│ │ │ │ │ ├── app.ts
│ │ │ │ │ └── test-logger-provider.ts
│ │ │ └── views
│ │ │ │ └── hello.html
│ │ ├── features
│ │ │ ├── current
│ │ │ │ ├── app
│ │ │ │ │ └── test.ts
│ │ │ │ ├── config
│ │ │ │ │ └── app.ts
│ │ │ │ └── current.spec.ts
│ │ │ └── index.spec.ts
│ │ └── src
│ │ │ ├── cluster
│ │ │ ├── helpers.spec.ts
│ │ │ └── worker.spec.ts
│ │ │ ├── config
│ │ │ └── index.spec.ts
│ │ │ ├── container
│ │ │ └── index.spec.ts
│ │ │ ├── cookie
│ │ │ └── index.spec.ts
│ │ │ ├── database
│ │ │ ├── builder.spec.ts
│ │ │ ├── database.spec.ts
│ │ │ └── init.ts
│ │ │ ├── decorators
│ │ │ ├── component.spec.ts
│ │ │ ├── factory
│ │ │ │ └── create-inject-decorator.spec.ts
│ │ │ ├── ignore.spec.ts
│ │ │ ├── inject.spec.ts
│ │ │ ├── injectable.spec.ts
│ │ │ ├── multiton.spec.ts
│ │ │ ├── rest.spec.ts
│ │ │ ├── route.spec.ts
│ │ │ ├── validates
│ │ │ │ └── index.spec.ts
│ │ │ └── verb.spec.ts
│ │ │ ├── errors
│ │ │ ├── handle-error.spec.ts
│ │ │ ├── http-error.spec.ts
│ │ │ ├── illegal-argument-error.spec.ts
│ │ │ ├── not-found-http-error.spec.ts
│ │ │ └── validate-http-error.spec.ts
│ │ │ ├── foundation
│ │ │ └── middlewares
│ │ │ │ ├── cross.spec.ts
│ │ │ │ └── csrf.spec.ts
│ │ │ ├── loader
│ │ │ └── index.spec.ts
│ │ │ ├── logger
│ │ │ └── index.spec.ts
│ │ │ ├── middleware
│ │ │ └── index.spec.ts
│ │ │ ├── model
│ │ │ ├── init.ts
│ │ │ └── model.spec.ts
│ │ │ ├── pipeline
│ │ │ └── index.spec.ts
│ │ │ ├── request
│ │ │ ├── index.spec.ts
│ │ │ └── utils
│ │ │ │ └── parse-body.spec.ts
│ │ │ ├── resource
│ │ │ ├── app
│ │ │ │ ├── test.controller.ts
│ │ │ │ ├── test.resource.ts
│ │ │ │ └── wrap.resource.ts
│ │ │ └── resource.spec.ts
│ │ │ ├── response
│ │ │ ├── index.spec.ts
│ │ │ ├── redirect.spec.ts
│ │ │ └── statusable.spec.ts
│ │ │ ├── router
│ │ │ └── routes.spec.ts
│ │ │ ├── session
│ │ │ └── helper.spec.ts
│ │ │ ├── utils
│ │ │ ├── message.spec.ts
│ │ │ └── utils.spec.ts
│ │ │ ├── validate
│ │ │ ├── app
│ │ │ │ ├── test.controller.ts
│ │ │ │ └── test.validator.ts
│ │ │ ├── feature.spec.ts
│ │ │ ├── validate.spec.ts
│ │ │ └── validators.spec.ts
│ │ │ └── view
│ │ │ └── index.spec.ts
│ ├── jest.config.js
│ ├── package.json
│ ├── src
│ │ ├── base
│ │ │ ├── entity.ts
│ │ │ ├── index.ts
│ │ │ ├── pivot-entity.ts
│ │ │ ├── resource.ts
│ │ │ └── validator.ts
│ │ ├── cluster
│ │ │ ├── const.ts
│ │ │ ├── helpers.ts
│ │ │ ├── index.ts
│ │ │ ├── master.ts
│ │ │ └── worker.ts
│ │ ├── config
│ │ │ ├── config.ts
│ │ │ └── index.ts
│ │ ├── container
│ │ │ └── index.ts
│ │ ├── controller
│ │ │ ├── controller-service.ts
│ │ │ └── index.ts
│ │ ├── decorators
│ │ │ ├── autowired.ts
│ │ │ ├── component-type.ts
│ │ │ ├── contexts-http.ts
│ │ │ ├── create-decorator.ts
│ │ │ ├── cross-origin.ts
│ │ │ ├── csrf.ts
│ │ │ ├── disbale.ts
│ │ │ ├── encrypt.ts
│ │ │ ├── factory
│ │ │ │ └── decorator-factory.ts
│ │ │ ├── http-code.ts
│ │ │ ├── ignore.ts
│ │ │ ├── index.ts
│ │ │ ├── inject.ts
│ │ │ ├── model
│ │ │ │ ├── column.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── relation.ts
│ │ │ ├── multiton.ts
│ │ │ ├── order.ts
│ │ │ ├── provider
│ │ │ │ ├── index.ts
│ │ │ │ ├── provide-on-config.ts
│ │ │ │ ├── provide-on-missing.ts
│ │ │ │ ├── provide-on.ts
│ │ │ │ ├── provide.ts
│ │ │ │ └── provider.ts
│ │ │ ├── rest.ts
│ │ │ ├── schedule
│ │ │ │ ├── corntab.ts
│ │ │ │ └── index.ts
│ │ │ ├── singleton.ts
│ │ │ ├── stereotype
│ │ │ │ ├── agent.ts
│ │ │ │ ├── component.ts
│ │ │ │ ├── controller.ts
│ │ │ │ ├── entity.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── injectable.ts
│ │ │ │ ├── job.ts
│ │ │ │ ├── middleware.ts
│ │ │ │ ├── resourcer.ts
│ │ │ │ ├── schedule.ts
│ │ │ │ ├── service.ts
│ │ │ │ └── validator.ts
│ │ │ ├── use
│ │ │ │ ├── index.ts
│ │ │ │ ├── interface.ts
│ │ │ │ └── use-middleware.ts
│ │ │ ├── validates
│ │ │ │ ├── factory.ts
│ │ │ │ └── index.ts
│ │ │ └── verb.ts
│ │ ├── errors
│ │ │ ├── handle.ts
│ │ │ ├── http-error.ts
│ │ │ ├── illegal-argument-error.ts
│ │ │ ├── not-found-http-error.ts
│ │ │ ├── validate-http-error.ts
│ │ │ └── views
│ │ │ │ └── errors
│ │ │ │ ├── 401.njk
│ │ │ │ ├── 404.njk
│ │ │ │ ├── 500.njk
│ │ │ │ ├── 503.njk
│ │ │ │ ├── error.njk
│ │ │ │ └── layout.njk
│ │ ├── foundation
│ │ │ ├── application.ts
│ │ │ ├── auto-providers
│ │ │ │ ├── common.provider.ts
│ │ │ │ ├── depends
│ │ │ │ │ ├── cache.provider.ts
│ │ │ │ │ ├── database.provider.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── logger.provider.ts
│ │ │ │ │ ├── mailer.provider.ts
│ │ │ │ │ ├── messenger.provider.ts
│ │ │ │ │ ├── proxy.provider.ts
│ │ │ │ │ ├── redis.provider.ts
│ │ │ │ │ ├── router.provider.ts
│ │ │ │ │ ├── schedule.provider.ts
│ │ │ │ │ ├── server.provider.ts
│ │ │ │ │ ├── stereotype.provider.ts
│ │ │ │ │ └── template-engine.provider.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── worker.provider.ts
│ │ │ └── buildin-app
│ │ │ │ ├── agents
│ │ │ │ └── schedule.ts
│ │ │ │ └── middlewares
│ │ │ │ ├── cors.ts
│ │ │ │ ├── proxy.ts
│ │ │ │ └── verify-csrf-token.ts
│ │ ├── helpers.ts
│ │ ├── http
│ │ │ ├── cookie
│ │ │ │ └── index.ts
│ │ │ ├── middleware
│ │ │ │ ├── index.ts
│ │ │ │ └── middleware-service.ts
│ │ │ ├── proxy
│ │ │ │ ├── index.ts
│ │ │ │ └── proxy.ts
│ │ │ ├── request
│ │ │ │ ├── index.ts
│ │ │ │ └── utils
│ │ │ │ │ └── parse-body.ts
│ │ │ ├── response
│ │ │ │ ├── index.ts
│ │ │ │ ├── manager.ts
│ │ │ │ ├── redirect.ts
│ │ │ │ └── statusable.ts
│ │ │ ├── router
│ │ │ │ ├── dispatcher.ts
│ │ │ │ ├── helpers.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── node.ts
│ │ │ │ ├── route.ts
│ │ │ │ └── trie.ts
│ │ │ ├── server
│ │ │ │ ├── index.ts
│ │ │ │ └── server.ts
│ │ │ └── session
│ │ │ │ ├── index.ts
│ │ │ │ └── stores
│ │ │ │ └── redis.ts
│ │ ├── index.ts
│ │ ├── interfaces
│ │ │ ├── agent.interface.ts
│ │ │ ├── external
│ │ │ │ └── https-options.ts
│ │ │ ├── index.ts
│ │ │ ├── middleware.interface.ts
│ │ │ ├── provider.interface.ts
│ │ │ └── resource.interface.ts
│ │ ├── loader
│ │ │ ├── index.ts
│ │ │ └── loader.ts
│ │ ├── messenger
│ │ │ ├── index.ts
│ │ │ └── messenger.ts
│ │ ├── pagination
│ │ │ ├── index.ts
│ │ │ └── paginator.ts
│ │ ├── pipeline
│ │ │ └── index.ts
│ │ ├── provider
│ │ │ ├── index.ts
│ │ │ └── provider.ts
│ │ ├── resource
│ │ │ ├── index.ts
│ │ │ └── resource.ts
│ │ ├── supports
│ │ │ ├── cache
│ │ │ │ ├── cache.ts
│ │ │ │ ├── config.interface.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── store
│ │ │ │ │ ├── fs.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── memory.ts
│ │ │ │ │ ├── redis.ts
│ │ │ │ │ └── store.ts
│ │ │ ├── database
│ │ │ │ ├── actuator
│ │ │ │ │ ├── actuator.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── mysql-actuator.ts
│ │ │ │ │ └── mysql-tansaction-actuator.ts
│ │ │ │ ├── builder
│ │ │ │ │ ├── builder.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── join.ts
│ │ │ │ ├── connector
│ │ │ │ │ ├── connector.ts
│ │ │ │ │ └── mysql-connector.ts
│ │ │ │ ├── database.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── manager
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── manager.ts
│ │ │ │ │ └── mysql-manager.ts
│ │ │ │ └── parser
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── mysql-parser.ts
│ │ │ │ │ └── parser.ts
│ │ │ ├── logger
│ │ │ │ ├── cluster.ts
│ │ │ │ ├── consts.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── logger.ts
│ │ │ ├── mailer
│ │ │ │ ├── builder.ts
│ │ │ │ ├── connector.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── mailer.ts
│ │ │ │ └── manager.ts
│ │ │ ├── orm
│ │ │ │ ├── base-model.ts
│ │ │ │ ├── builder.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── model.ts
│ │ │ │ ├── pivot-model.ts
│ │ │ │ ├── relations
│ │ │ │ │ ├── belongs-to-many.ts
│ │ │ │ │ ├── belongs-to.ts
│ │ │ │ │ ├── has-many.ts
│ │ │ │ │ ├── has-one.ts
│ │ │ │ │ ├── has-relations.abstract.ts
│ │ │ │ │ └── index.ts
│ │ │ │ └── repository.ts
│ │ │ ├── redis
│ │ │ │ ├── config.interface.ts
│ │ │ │ ├── connector.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── redis.ts
│ │ │ ├── schedule
│ │ │ │ ├── corn-parser.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── matcher.ts
│ │ │ │ ├── schedule-service.ts
│ │ │ │ ├── scheduler.ts
│ │ │ │ └── task.ts
│ │ │ └── template-engine
│ │ │ │ ├── index.ts
│ │ │ │ └── template.ts
│ │ ├── symbol.ts
│ │ ├── utils
│ │ │ ├── defered.ts
│ │ │ ├── encrypt.ts
│ │ │ ├── fake-base-class.ts
│ │ │ ├── index.ts
│ │ │ ├── message.ts
│ │ │ ├── str.ts
│ │ │ └── tool.ts
│ │ ├── validate
│ │ │ ├── index.ts
│ │ │ ├── validate.ts
│ │ │ └── validators.ts
│ │ └── view
│ │ │ ├── factory.ts
│ │ │ └── index.ts
│ ├── tsconfig.json
│ └── vendors.d.ts
└── trace-page
│ ├── .npmignore
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ └── index.spec.ts
│ ├── global.d.ts
│ ├── images.d.ts
│ ├── index.ts
│ ├── jest.config.js
│ ├── package.json
│ ├── template
│ ├── images
│ │ └── logo.svg
│ ├── index.html
│ ├── index.ts
│ ├── js
│ │ ├── prettify.js
│ │ └── zepto.min.js
│ └── less
│ │ ├── code.less
│ │ └── index.less
│ ├── tsconfig-for-webpack-config.json
│ ├── tsconfig.json
│ └── webpack.config.ts
├── scripts
└── build.sh
├── tools
└── benchmarks
│ └── benchmarks.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | charset = utf-8
7 | trim_trailing_whitespace = false
8 | insert_final_newline = false
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | benchmarks
2 | *.json
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "plugin:@typescript-eslint/recommended"
4 | ],
5 | "plugins": [
6 | "@typescript-eslint"
7 | ],
8 | "parser": "@typescript-eslint/parser",
9 | "parserOptions": {
10 | "ecmaVersion": 2018,
11 | "sourceType": "module"
12 | },
13 | "rules": {
14 | "semi": [
15 | "error",
16 | "always"
17 | ],
18 | "@typescript-eslint/no-this-alias": "off",
19 | "@typescript-eslint/explicit-function-return-type": "off",
20 | "@typescript-eslint/no-explicit-any": "off",
21 | "@typescript-eslint/explicit-member-accessibility": "off",
22 | "@typescript-eslint/indent": [
23 | "error",
24 | 2
25 | ]
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BUG_REPORT.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F41B Bug Report"
3 | about: "If something isn't working as expected \U0001F914."
4 | title: ''
5 | labels: 'type: potential issue :broken_heart:,needs triage'
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Bug Report
11 |
12 | ## Current behavior
13 |
14 |
15 | ## Input Code
16 |
17 |
18 | ```ts
19 | const your = (code) => here;
20 | ```
21 |
22 | ## Expected behavior
23 |
24 |
25 | ## Possible Solution
26 |
27 |
28 | ## Environment
29 |
30 |
31 |
32 | Daze version: X.Y.Z
33 |
34 |
35 | For Tooling issues:
36 | - Node version: XX
37 | - Platform:
38 |
39 | Others:
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F680 Feature Request"
3 | about: "I have a suggestion \U0001F63B!"
4 | title: ''
5 | labels: 'type: enhancement :wolf:,needs triage'
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Feature Request
11 |
12 | ## Is your feature request related to a problem? Please describe.
13 |
14 |
15 | ## Describe the solution you'd like
16 |
17 |
18 | ## Teachability, Documentation, Adoption, Migration Strategy
19 |
20 |
21 | ## What is the motivation / use case for changing the behavior?
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F917 Support Question"
3 | about: "I have a question \U0001F4AC"
4 | title: ''
5 | labels: 'type: question 🙌,needs triage'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
--------------------------------------------------------------------------------
/.github/lock.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before a closed issue or pull request is locked
2 | daysUntilLock: 90
3 |
4 | # Skip issues and pull requests created before a given timestamp. Timestamp must
5 | # follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
6 | skipCreatedBefore: false
7 |
8 | # Issues and pull requests with these labels will be ignored. Set to `[]` to disable
9 | exemptLabels: []
10 |
11 | # Label to add before locking, such as `outdated`. Set to `false` to disable
12 | lockLabel: false
13 |
14 | # Comment to post before locking. Set to `false` to disable
15 | lockComment: >
16 | This thread has been automatically locked since there has not been
17 | any recent activity after it was closed. Please open a new issue for
18 | related bugs.
19 | # Assign `resolved` as the reason for locking. Set to `false` to disable
20 | setLockReason: true
21 |
22 | # Limit to only `issues` or `pulls`
23 | # only: issues
24 |
25 | # Optionally, specify configuration settings just for `issues` or `pulls`
26 | # issues:
27 | # exemptLabels:
28 | # - help-wanted
29 | # lockLabel: outdated
30 |
31 | # pulls:
32 | # daysUntilLock: 30
33 |
34 | # Repository to extend settings from
35 | # _extends: repo
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Feature Request
2 |
3 | ## Is your feature request related to a problem? Please describe.
4 |
5 |
6 | ## Describe the solution you'd like
7 |
8 |
9 | ## Teachability, Documentation, Adoption, Migration Strategy
10 |
11 |
12 | ## What is the motivation / use case for changing the behavior?
13 |
14 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Node CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | test:
13 |
14 | runs-on: ubuntu-latest
15 |
16 | strategy:
17 | matrix:
18 | node-version: [14, 16]
19 |
20 | # container: node:12
21 |
22 | services:
23 | mysql:
24 | image: mysql:5.7
25 | ports:
26 | - 3306:3306
27 | env:
28 | MYSQL_ROOT_PASSWORD: root
29 | MYSQL_DATABASE: daze
30 | options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
31 |
32 | steps:
33 | - name: Checkout
34 | uses: actions/checkout@v1
35 | with:
36 | fetch-depth: 1
37 | - name: Setup Node.js
38 | uses: actions/setup-node@v3
39 | with:
40 | node-version: ${{ matrix.node }}
41 | - name: Dependences Install
42 | run: |
43 | npm install
44 | npm install codecov
45 | ./node_modules/.bin/lerna bootstrap
46 | - name: Run Test
47 | run: |
48 | npm run test:coverage
49 | - name: Codecov
50 | run: |
51 | ./node_modules/.bin/codecov -t ${{ secrets.CODECOV_TOKEN }}
52 |
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # dependencies
2 | node_modules/
3 |
4 | # IDE
5 | /.idea
6 | /.awcache
7 | /.vscode
8 | *.code-workspace
9 |
10 | # dist
11 | packages/*/dist
12 |
13 |
14 | # logs
15 | logs/*.log
16 | **/logs/**.log
17 |
18 | # misc
19 | .DS_Store
20 | lerna-debug.log
21 | npm-debug.log
22 | yarn-error.log
23 | packages/*/__debug__
24 | .clinic
25 |
26 | # test
27 | packages/*/coverage
28 |
29 | # future and deprecated
30 | FUTURE_*
31 | DEPRECATED_*
32 |
33 | # dev example
34 | __example__
35 | example/dist
--------------------------------------------------------------------------------
/.huskyrc:
--------------------------------------------------------------------------------
1 | {
2 | "hooks": {
3 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
4 | }
5 | }
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | src
3 | coverage
4 | __tests__
5 | __debug__
6 | .idea
7 | .vscode
8 | logs
9 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | czewail
2 | yinggaozhen
3 | IceMimosa
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT LICENSE
2 |
3 | Copyright (c) 2018-present Chan Zewail, chanzewail@gmail.com
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README_en.md:
--------------------------------------------------------------------------------
1 |
2 | [](https://github.com/dazejs/daze/issues)
3 | [](https://www.npmjs.com/package/@dazejs/framework)
4 | [](https://www.npmjs.com/package/@dazejs/framework)
5 | [](https://github.com/dazejs/daze/actions)
6 | [](https://codecov.io/gh/dazejs/daze)
7 | [](https://www.codacy.com/manual/dazejs/daze?utm_source=github.com&utm_medium=referral&utm_content=dazejs/daze&utm_campaign=Badge_Grade)
8 | [](https://github.com/dazejs/daze/blob/master/LICENSE)
9 |
10 |
11 |
12 |
13 |
14 |
Daze.js
15 |
Web framwork for Node.js
16 |
17 |
18 | English | [中文](README_zh.md)
19 |
20 |
21 | Visit [https://dazejs.org/](https://dazejs.org/) to learn more
22 |
23 | ## Introduction
24 |
25 | `Daze.js` is an efficient, highly extensible and powerful `Node.js` server-side Web development daze.
26 |
27 |
28 | ## Getting Started
29 |
30 | #### Install cli tool
31 | ```bash
32 | $ npm install -g @dazejs/cli
33 | ```
34 |
35 | #### Create application
36 |
37 | ```bash
38 | $ daze create example
39 | $ cd example
40 | $ npm start
41 | ```
42 |
43 | visit `http://localhost:8080` to preview
44 |
45 | ## Docs & Community
46 |
47 | - [Documentations](https://dazejs.org/)
48 |
49 | ## Benchmarks
50 | The benchmark compares a number of other frameworks, mainly with no routes and with 1000 routes defined, see [benchmarks](benchmarks/README.md)
51 |
52 | ## License
53 |
54 | Daze.js is [MIT licensed](https://github.com/dazejs/daze/blob/master/LICENSE)
55 |
56 |
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dazejs/daze/e9d67d915a33c70cb5cdd731fc585a48a5872a5a/assets/logo.png
--------------------------------------------------------------------------------
/benchmarks/README.md:
--------------------------------------------------------------------------------
1 | # Benchmarks
2 |
3 | ### daze-without-routes
4 |
5 | | Stat | Avg | Stdev | Min |
6 | | --------- | -------- | ------- | ------- |
7 | | Req/Sec | 64801.46 | 4141.42 | 51921 |
8 | | Bytes/Sec | 9.39 MB | 4.04 KB | 50.7 KB |
9 |
10 |
11 | ### express-without-routes
12 |
13 | | Stat | Avg | Stdev | Min |
14 | | --------- | -------- | ------- | -------- |
15 | | Req/Sec | 33246.55 | 3611.47 | 22052 |
16 | | Bytes/Sec | 6.82 MB | 3.53 KB | 21.54 KB |
17 |
18 |
19 | ### koa-without-routes
20 |
21 | | Stat | Avg | Stdev | Min |
22 | | --------- | -------- | ------- | -------- |
23 | | Req/Sec | 60670.55 | 4490.95 | 48478 |
24 | | Bytes/Sec | 8.79 MB | 4.39 KB | 47.34 KB |
25 |
26 |
27 | ### daze-with-1000-routes
28 |
29 | | Stat | Avg | Stdev | Min |
30 | | --------- | -------- | ------- | -------- |
31 | | Req/Sec | 39210.91 | 3903.57 | 26911 |
32 | | Bytes/Sec | 5.68 MB | 3.81 KB | 26.28 KB |
33 |
34 |
35 | ### express-with-1000-routes
36 |
37 | | Stat | Avg | Stdev | Min |
38 | | --------- | -------- | ------- | ------- |
39 | | Req/Sec | 11745.64 | 1323.05 | 7712 |
40 | | Bytes/Sec | 2.41 MB | 1.29 KB | 7.53 KB |
41 |
42 |
43 | ### koa-with-1000-routes
44 |
45 | | Stat | Avg | Stdev | Min |
46 | | --------- | ------- | ------ | ------- |
47 | | Req/Sec | 8803.28 | 758.07 | 6684 |
48 | | Bytes/Sec | 1.28 MB | 758 B | 6.53 KB |
49 |
50 |
--------------------------------------------------------------------------------
/benchmarks/daze-with-1000-routes.js:
--------------------------------------------------------------------------------
1 | const { Application, BaseController, BaseProvider, Response } = require('../packages/framework/dist')
2 |
3 | const app = new Application(__dirname)
4 |
5 | class Hello extends BaseController {
6 | index() {
7 | return 'Hello World'
8 | }
9 | }
10 |
11 | app.multiton(Hello, Hello)
12 |
13 | class RoutesProvider extends BaseProvider {
14 | launch() {
15 | const router = this.app.get('router')
16 | for (let index1 = 0; index1 < 10; index1++) {
17 | for (let index2 = 0; index2 < 10; index2++) {
18 | for (let index3 = 0; index3 < 10; index3++) {
19 | const url = `/uuid${index1}/uuid${index2}/uuid${index3}`
20 | router.register(url, ['GET'], Hello, 'index', [])
21 | }
22 | }
23 | }
24 | }
25 | }
26 |
27 | app.disableBodyParser()
28 |
29 | app.disableSession()
30 |
31 | app.register(new RoutesProvider(app))
32 |
33 | app.run(3000)
34 |
35 |
36 |
--------------------------------------------------------------------------------
/benchmarks/daze-without-routes.js:
--------------------------------------------------------------------------------
1 | const { Application, Controller, BaseProvider, Response } = require('../packages/framework/dist')
2 |
3 | const app = new Application(__dirname)
4 |
5 |
6 | class RoutesProvider extends BaseProvider {
7 | launch() {
8 | this.app.get('middleware').register(() => (new Response()).OK('Hello World'))
9 | }
10 | }
11 |
12 | app.disableBodyParser()
13 |
14 | app.disableSession()
15 |
16 | app.register(new RoutesProvider(app))
17 |
18 | app.run(3000)
19 |
20 |
21 |
--------------------------------------------------------------------------------
/benchmarks/express-with-1000-routes.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const app = express();
3 |
4 | const controller = (req, res) => {
5 | res.send('Hello World')
6 | }
7 |
8 | for (let index1 = 1; index1 <= 10; index1++) {
9 | for (let index2 = 1; index2 <= 10; index2++) {
10 | for (let index3 = 1; index3 <= 10; index3++) {
11 | const url = `/uuid${index1}/uuid${index2}/uuid${index3}`
12 | app.get(url, controller)
13 | }
14 | }
15 | }
16 |
17 |
18 | app.listen(3000);
--------------------------------------------------------------------------------
/benchmarks/express-without-routes.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const app = express();
3 |
4 | // app.get('/hello', function (req, res) {
5 | // res.send('Hello World');
6 | // });
7 |
8 | const controller = (req, res) => {
9 | res.send('Hello World')
10 | }
11 |
12 | app.use(controller)
13 |
14 | // for (let index1 = 1; index1 <= 10; index1++) {
15 | // for (let index2 = 1; index2 <= 10; index2++) {
16 | // for (let index3 = 1; index3 <= 10; index3++) {
17 | // const url = `/uuid${index1}/uuid${index2}/uuid${index3}`
18 | // app.get(url, controller)
19 | // app.post(url, controller)
20 | // app.put(url, controller)
21 | // app.delete(url, controller)
22 | // app.patch(url, controller)
23 | // }
24 | // }
25 | // }
26 |
27 | app.listen(3000);
--------------------------------------------------------------------------------
/benchmarks/koa-with-1000-routes.js:
--------------------------------------------------------------------------------
1 |
2 | const Koa = require('koa');
3 | const Router = require('koa-router')
4 |
5 | const app = new Koa()
6 |
7 | const router = new Router()
8 |
9 | const controller = (ctx, next) => {
10 | ctx.body = 'Hello World'
11 | }
12 |
13 | for (let index1 = 1; index1 <= 10; index1++) {
14 | for (let index2 = 1; index2 <= 10; index2++) {
15 | for (let index3 = 1; index3 <= 10; index3++) {
16 | const url = `/uuid${index1}/uuid${index2}/uuid${index3}`
17 | router.get(url, controller)
18 | }
19 | }
20 | }
21 |
22 | app.use(router.routes(), router.allowedMethods())
23 |
24 | app.listen(3000)
--------------------------------------------------------------------------------
/benchmarks/koa-without-routes.js:
--------------------------------------------------------------------------------
1 |
2 | const Koa = require('koa');
3 |
4 | const app = new Koa()
5 |
6 |
7 | const controller = (ctx, next) => {
8 | ctx.body = 'Hello World'
9 | }
10 |
11 | app.use(controller)
12 |
13 | app.listen(3000)
14 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional']
3 | };
4 |
--------------------------------------------------------------------------------
/example/daze:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const daze = require('../packages/cli/dist');
4 |
5 | daze.terminate(process.argv);
6 |
--------------------------------------------------------------------------------
/example/src/app/agent.ts:
--------------------------------------------------------------------------------
1 | import { Agent, AgentInterface } from '../../../packages/framework/dist';
2 |
3 | @Agent()
4 | export default class ExampleAgent implements AgentInterface {
5 | resolve() {
6 | // console.log(1111111);setInterval(() => {
7 | // console.log(12312312312);
8 | // }, 1000);
9 | // setTimeout(() => {
10 | // process.exit(1);
11 | // }, 3000);
12 | }
13 | }
--------------------------------------------------------------------------------
/example/src/app/example.controller.ts:
--------------------------------------------------------------------------------
1 | import { app, Autowired, Controller, http, Logger } from '../../../packages/framework/dist';
2 |
3 | @Controller()
4 | export class Example {
5 | @Autowired
6 | logger: Logger;
7 | // @Get()
8 | // async index(request: Request, @Query('name') anme = '') {
9 | // return new View('hello', {
10 | // name: anme || 'daze'
11 | // });
12 | // }
13 |
14 | @http.Get('set')
15 | async set() {
16 | return 'set';
17 | }
18 |
19 | @http.Get('/route')
20 | async route() {
21 | console.dir(app().get('router'), {
22 | customInspect: true,
23 | depth: 7
24 | });
25 | return 'route';
26 | }
27 |
28 | @http.Get('/del-route')
29 | async delroute() {
30 | app().get('router').unRegistry('/set', ['GET'], {});
31 | return 'route';
32 | }
33 | }
--------------------------------------------------------------------------------
/example/src/app/example.entity.ts:
--------------------------------------------------------------------------------
1 | import { Entity, BaseEntity, AutoIncrementPrimaryColumn, Column, CreateTimestampColumn, UpdateTimestampColumn } from '../../../packages/framework/dist';
2 |
3 | @Entity('packages')
4 | export class ExampleEntity extends BaseEntity {
5 | @AutoIncrementPrimaryColumn()
6 | id: number;
7 |
8 | @Column()
9 | author: string;
10 |
11 | @Column()
12 | name: string;
13 |
14 | @Column()
15 | description: string;
16 |
17 | @CreateTimestampColumn('datetime')
18 | created_at: number;
19 |
20 | @UpdateTimestampColumn('datetime')
21 | updated_at: number;
22 | }
--------------------------------------------------------------------------------
/example/src/app/schedule.ts:
--------------------------------------------------------------------------------
1 | // import { Schedule, Corntab } from '../../../packages/framework/dist';
2 |
3 |
4 | // @Schedule()
5 | export class ExampleSchedule {
6 | // @Corntab.everyFifteenSeconds()
7 | myname() {
8 | console.log('runrunrun======');
9 | }
10 |
11 | myass() {
12 | console.log('assassin');
13 | }
14 | }
--------------------------------------------------------------------------------
/example/src/config/app.dev.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | cluster: false,
3 | };
--------------------------------------------------------------------------------
/example/src/config/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import { ExampleProvider } from '../example.provider';
3 |
4 | export default {
5 | cluster: true,
6 | workers: 2,
7 | sticky: false,
8 | baseUrl: '/example',
9 |
10 | public: true,
11 | publicPrefix: '',
12 | ssrDevPort: 9988,
13 | providers: [
14 | ExampleProvider,
15 | ]
16 | };
--------------------------------------------------------------------------------
/example/src/config/cache.ts:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | /**
4 | * 默认使用的存储器
5 | * 可选:memory | redis | fs
6 | */
7 | store: 'fs'
8 |
9 | };
--------------------------------------------------------------------------------
/example/src/config/database.ts:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | default: {
4 | type: 'mysql',
5 | host: '127.0.0.1',
6 | user: 'root',
7 | password: 'root',
8 | port: 3306,
9 | database: 'yxnpm'
10 | }
11 | };
--------------------------------------------------------------------------------
/example/src/config/proxy.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | '/xhr/*': {
3 | target: 'https://baidu.com',
4 | // only: ['/xhr/set'],
5 | rewrite: (p: string) => {
6 | return p.replace('/xhr', '');
7 | }
8 | }
9 | };
--------------------------------------------------------------------------------
/example/src/config/redis.ts:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | /**
4 | * 默认 Redis 连接
5 | */
6 | default: {
7 | host: 'localhost',
8 | port: 6379
9 | },
10 |
11 | /**
12 | * 缓存专用默认 reids 连接
13 | * 未定义的情况下,默认使用 default 连接
14 | */
15 | // cache: {
16 | // host: 'localhost',
17 | // port: 6379
18 | // },
19 |
20 | /**
21 | * 任务调度专用默认 reids 连接
22 | * 未定义的情况下,默认使用 default 连接
23 | */
24 | // schedule: {
25 | // host: 'localhost',
26 | // port: 6379
27 | // },
28 | };
--------------------------------------------------------------------------------
/example/src/example.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provider, AppendMaster, AppendAgent, Autowired, Application } from '../../packages/framework/dist';
2 |
3 | @Provider()
4 | @AppendMaster()
5 | @AppendAgent()
6 | export class ExampleProvider {
7 | @Autowired
8 | app: Application;
9 |
10 | launch() {
11 | // console.dir(this.app.get('router'), {
12 | // customInspect: true,
13 | // depth: 7
14 | // });
15 | }
16 | }
--------------------------------------------------------------------------------
/example/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Application } from '../../packages/framework/dist';
2 |
3 | const app = new Application();
4 |
5 | app.run(8080);
6 |
--------------------------------------------------------------------------------
/example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2017",
4 | "module": "commonjs",
5 | "baseUrl": "./",
6 | "outDir": "dist",
7 | "lib": [
8 | "esnext"
9 | ],
10 | "allowJs": false,
11 | "declaration": true,
12 | "sourceMap": true,
13 | "removeComments": true,
14 | "strict": true,
15 | "noImplicitAny": true,
16 | "strictNullChecks": true,
17 | "strictFunctionTypes": true,
18 | "strictPropertyInitialization": false,
19 | "noImplicitThis": true,
20 | "alwaysStrict": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "noImplicitReturns": true,
24 | "moduleResolution": "node",
25 | "allowSyntheticDefaultImports": true,
26 | "esModuleInterop": true,
27 | "experimentalDecorators": true,
28 | "emitDecoratorMetadata": true,
29 | "skipLibCheck": true,
30 | "preserveSymlinks": true
31 | },
32 | "include": [
33 | "src/**/*.ts"
34 | ],
35 | "exclude": [
36 | "node_modules"
37 | ]
38 | }
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "packages/*"
4 | ],
5 | "command": {
6 | "bootstrap": {
7 | "hoist": true,
8 | "noCi": true,
9 | "npmClientArgs": [
10 | "--no-package-lock"
11 | ]
12 | },
13 | "version": {
14 | "message": "chore(release): publish"
15 | },
16 | "publish": {
17 | "ignoreChanges": [
18 | "*.md"
19 | ],
20 | "allowBranch": "master",
21 | "exact": true,
22 | "conventionalCommits": true
23 | }
24 | },
25 | "version": "independent"
26 | }
27 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "root",
3 | "private": true,
4 | "scripts": {
5 | "dev": "lerna run dev --parallel --stream",
6 | "dev:trace-page": "lerna run --scope @dazejs/trace-page dev",
7 | "install": "lerna bootstrap",
8 | "build": "sh scripts/build.sh",
9 | "publish": "npm run build && lerna publish",
10 | "next": "npm run build && lerna publish --dist-tag next",
11 | "bootstrap": "lerna bootstrap",
12 | "test": "lerna run test --stream",
13 | "test:coverage": "lerna run test:coverage --stream",
14 | "benchmarks": "ts-node tools/benchmarks/benchmarks.ts",
15 | "commitlint": "commitlint -e $GIT_PARAMS"
16 | },
17 | "devDependencies": {
18 | "@commitlint/cli": "8.3.5",
19 | "@commitlint/config-conventional": "8.2.0",
20 | "@types/debug": "4.1.5",
21 | "@types/express": "4.17.1",
22 | "@types/jest": "25.1.4",
23 | "@types/koa": "2.11.2",
24 | "@types/koa-router": "7.4.0",
25 | "@types/node": "14.0.26",
26 | "@types/supertest": "2.0.8",
27 | "@types/type-is": "1.6.3",
28 | "@types/uuid": "7.0.2",
29 | "@types/validator": "12.0.1",
30 | "@typescript-eslint/eslint-plugin": "5.46.0",
31 | "@typescript-eslint/parser": "5.46.0",
32 | "autocannon": "4.6.0",
33 | "copyfiles": "2.2.0",
34 | "cross-env": "6.0.0",
35 | "eslint": "8.29.0",
36 | "eslint-config-airbnb-base": "15.0.0",
37 | "eslint-plugin-import": "2.26.0",
38 | "express": "4.17.1",
39 | "filesize": "6.1.0",
40 | "husky": "4.2.5",
41 | "jest": "29.3.1",
42 | "koa": "2.11.0",
43 | "koa-router": "8.0.8",
44 | "lerna": "6.4.0",
45 | "markdown-table": "2.0.0",
46 | "rimraf": "3.0.2",
47 | "supertest": "4.0.2",
48 | "ts-jest": "29.0.3",
49 | "ts-node": "10.9.1",
50 | "typescript": "4.9.4"
51 | },
52 | "dependencies": {
53 | "reflect-metadata": "0.1.13"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/cli/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [1.0.2](https://github.com/dazejs/daze/compare/@dazejs/cli@1.0.1...@dazejs/cli@1.0.2) (2025-02-19)
7 |
8 | **Note:** Version bump only for package @dazejs/cli
9 |
10 |
11 |
12 |
13 |
14 | ## [1.0.1](https://github.com/dazejs/daze/compare/@dazejs/cli@1.0.0-alpha.0...@dazejs/cli@1.0.1) (2023-01-10)
15 |
16 | **Note:** Version bump only for package @dazejs/cli
17 |
18 |
19 |
20 |
21 |
22 | # [1.0.0](https://github.com/dazejs/daze/compare/@dazejs/cli@1.0.0-alpha.0...@dazejs/cli@1.0.0) (2023-01-10)
23 |
24 | **Note:** Version bump only for package @dazejs/cli
25 |
26 |
27 |
28 |
29 |
30 | # 1.0.0-alpha.0 (2023-01-09)
31 |
32 | **Note:** Version bump only for package @dazejs/cli
33 |
--------------------------------------------------------------------------------
/packages/cli/__tests__/nill.spec.ts:
--------------------------------------------------------------------------------
1 |
2 | describe('nill', () => {
3 | it('nill', () => {
4 | expect(1).toBe(1)
5 | })
6 | })
--------------------------------------------------------------------------------
/packages/cli/g.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'ascii-table' {
2 | const x: any;
3 | export = x;
4 | }
5 | declare module 'ts-node/register' {
6 | const x: any;
7 | export = x;
8 | }
--------------------------------------------------------------------------------
/packages/cli/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@dazejs/cli",
3 | "version": "1.0.2",
4 | "description": "Node 服务端 WEB 框架",
5 | "main": "dist/index.js",
6 | "bin": {
7 | "daze": "dist/bin/daze.js"
8 | },
9 | "scripts": {
10 | "copy": "copyfiles -u 1 src/**/*.njk dist && copyfiles -u 1 src/*.json dist",
11 | "clean": "rimraf dist/*",
12 | "build": "npm run clean && npm run copy && tsc",
13 | "test": "node -v",
14 | "test:coverage": "node -v",
15 | "dev": "npm run clean && npm run copy && tsc -w"
16 | },
17 | "keywords": [],
18 | "author": "",
19 | "license": "UNLICENSE",
20 | "dependencies": {
21 | "@dazejs/framework": "5.0.2",
22 | "ascii-table": "^0.0.9",
23 | "chalk": "^4.1.0",
24 | "chokidar": "^3.5.3",
25 | "commander": "^7.2.0",
26 | "concurrently": "^6.2.0",
27 | "fs-extra": "^9.1.0",
28 | "glob": "^7.1.6",
29 | "inquirer": "^8.0.0",
30 | "node-fetch": "^2.6.1",
31 | "nodemon": "^2.0.7",
32 | "nunjucks": "^3.2.3",
33 | "ora": "^5.4.0",
34 | "pluralize": "^8.0.0",
35 | "reflect-metadata": "0.1.13",
36 | "table": "^6.7.1",
37 | "ts-node": "^10.0.0",
38 | "typescript": "^4.9.4"
39 | },
40 | "devDependencies": {
41 | "@types/concurrently": "^6.2.0",
42 | "@types/fs-extra": "^9.0.11",
43 | "@types/inquirer": "^7.3.1",
44 | "@types/node-fetch": "^2.5.10",
45 | "@types/nodemon": "^1.19.0",
46 | "@types/pluralize": "0.0.29"
47 | },
48 | "gitHead": "4d87844d5c3483689a94a63ac992c98ab9ff1224"
49 | }
50 |
--------------------------------------------------------------------------------
/packages/cli/src/actions/build.ts:
--------------------------------------------------------------------------------
1 | import { Application } from '@dazejs/framework';
2 | import chalk from 'chalk';
3 | import fs from 'fs';
4 | import path from 'path';
5 | import { DAZE_SERVER_PREFIX } from '../lib/constants';
6 | import { TsCompile } from '../lib/ts_compile';
7 |
8 | const cwd = process.cwd();
9 |
10 | /**
11 | * 开发模式 Action
12 | */
13 | export class BuildAction {
14 |
15 | /**
16 | * 默认的 tsconfig 文件路径
17 | */
18 | private defaultTsConfigPath = path.join(__dirname, '../defaultTsConfig.json');
19 |
20 | /**
21 | * 项目自定义的 tsconfig 文件路径
22 | */
23 | private customTsConfigPath = path.join(cwd, './tsconfig.json');
24 |
25 | /**
26 | * 项目自定义的 client 特殊 tsconfig 文件路径
27 | */
28 | // private _customClientTsConfigPath = path.join(fePath, './tsconfig.json')
29 |
30 | /**
31 | * 项目自定义的 server 特殊 tsconfig 文件路径
32 | */
33 | private customServerTsConfigPath = path.join(cwd, './src', './tsconfig.json');
34 |
35 |
36 | /**
37 | * Action Hook
38 | */
39 | public async resolve(_destination: any) {
40 | const app = new Application({
41 | rootPath: path.join(cwd, './src')
42 | });
43 | await app.initializeForCli();
44 |
45 | this.resolveServer();
46 | }
47 |
48 |
49 | /**
50 | * 启动服务端测开发模式
51 | */
52 | private resolveServer() {
53 | if (fs.existsSync(path.join(cwd, './src'))) {
54 | console.log(DAZE_SERVER_PREFIX, '准备编译服务端代码...');
55 | if (fs.existsSync(this.customServerTsConfigPath)) {
56 | this._compile(this.customServerTsConfigPath);
57 | } else {
58 | if (fs.existsSync(this.customTsConfigPath)) {
59 | this._compile(this.customTsConfigPath);
60 | } else {
61 | this._compile(this.defaultTsConfigPath);
62 | }
63 | }
64 | }
65 | }
66 |
67 | private async _compile(configPath: string) {
68 |
69 | const tsCompile = new TsCompile();
70 |
71 | tsCompile.compile(configPath, (config) => {
72 | console.log(DAZE_SERVER_PREFIX, '编译成功');
73 | console.log(DAZE_SERVER_PREFIX, '输出目录: ', chalk.green(config.options.outDir));
74 | });
75 | }
76 | }
--------------------------------------------------------------------------------
/packages/cli/src/actions/create.ts:
--------------------------------------------------------------------------------
1 | import { Render, Question, Printer } from '../lib';
2 | import { TPLActionAbstract } from './tpl-action.abstract';
3 | import { NpmRunner, YarnRunner, PNpmRunner} from '../lib/runner';
4 |
5 | export class CreateAction extends TPLActionAbstract {
6 |
7 | async resolve(name: string) {
8 | const answer = await new Question()
9 | .packageManager()
10 | .ask();
11 |
12 | const renderer = new Render();
13 |
14 | renderer.source(this._source);
15 | renderer.destination(name);
16 |
17 | await renderer.apply();
18 |
19 | if (answer.packageManager === 'npm') {
20 | await new NpmRunner()
21 | .directory(name)
22 | .run('install');
23 | } else if (answer.packageManager === 'yarn') {
24 | await new YarnRunner()
25 | .directory(name)
26 | .run('install');
27 | } else if (answer.packageManager === 'pnpm') {
28 | await new PNpmRunner()
29 | .directory(name)
30 | .run('install');
31 | }
32 |
33 | Printer.power();
34 | }
35 | }
--------------------------------------------------------------------------------
/packages/cli/src/actions/index.ts:
--------------------------------------------------------------------------------
1 | export * from './tpl-action.abstract';
2 | export * from './create';
3 | export * from './make';
4 | export * from './routes';
5 | export * from './build';
6 | export * from './dev';
--------------------------------------------------------------------------------
/packages/cli/src/actions/make.ts:
--------------------------------------------------------------------------------
1 | import { TPLActionAbstract } from './tpl-action.abstract';
2 | // import { Command } from 'commander';
3 | import { Render } from '../lib';
4 | import pluralize from 'pluralize';
5 | import chalk from 'chalk';
6 |
7 |
8 | export class MakeAction extends TPLActionAbstract {
9 |
10 | getFilename(name: string) {
11 | return `${name}.ts`;
12 | }
13 |
14 |
15 | async resolve(name: string, destination: Record) {
16 | const renderer = new Render();
17 |
18 | renderer.source(this._source);
19 | renderer.destination(destination.path ?? pluralize.plural(this._source));
20 |
21 | renderer.assign({
22 | name,
23 | });
24 |
25 | const distname = this.getFilename(name);
26 |
27 | switch(this._source) {
28 | case 'controller':
29 | if (destination.rest) {
30 | await renderer.make('rest.tpl', distname);
31 | } else {
32 | await renderer.make('controller.tpl', distname);
33 | }
34 | break;
35 | case 'service':
36 | await renderer.make('service.tpl', distname);
37 | break;
38 | case 'schedule':
39 | await renderer.make('schedule.tpl', distname);
40 | break;
41 | case 'middleware':
42 | await renderer.make('middleware.tpl', distname);
43 | break;
44 | default:
45 | console.log(
46 | chalk.red(`不支持该模板`)
47 | );
48 | process.exit(1);
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/packages/cli/src/actions/tpl-action.abstract.ts:
--------------------------------------------------------------------------------
1 | import { SourceType } from '../lib/render';
2 |
3 | export abstract class TPLActionAbstract {
4 | protected _source: SourceType;
5 |
6 | abstract resolve(name: string, destination: Record): any
7 | source(_source: SourceType) {
8 | this._source = _source;
9 | return this;
10 | }
11 | }
--------------------------------------------------------------------------------
/packages/cli/src/bin/daze.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import { init } from '../lib/init';
4 |
5 | init();
--------------------------------------------------------------------------------
/packages/cli/src/commands/build.ts:
--------------------------------------------------------------------------------
1 | import commander from 'commander';
2 | import { BuildAction } from '../actions';
3 |
4 | export class BuildCommand {
5 |
6 | private program: commander.Command;
7 |
8 | constructor(program: commander.Command) {
9 | this.program = program;
10 | }
11 |
12 | resolve(action: BuildAction) {
13 | this.program
14 | .command('build')
15 | .alias('b')
16 | .description('编译应用程序.')
17 | .option('--env ', '环境变量')
18 | .action(async (destination: any) => {
19 | if (destination.env) {
20 | process.env.DAZE_ENV = destination.env;
21 | }
22 | process.env.NODE_ENV = process.env.DAZE_ENV;
23 | action.resolve(destination);
24 | });
25 | }
26 | }
--------------------------------------------------------------------------------
/packages/cli/src/commands/create.ts:
--------------------------------------------------------------------------------
1 | import * as commander from 'commander';
2 | import { TPLActionAbstract } from '../actions';
3 |
4 |
5 | export class CreateCommand {
6 |
7 | private program: commander.Command;
8 |
9 | constructor(program: commander.Command) {
10 | this.program = program;
11 | }
12 |
13 | resolve(action: TPLActionAbstract) {
14 | this.program
15 | .command('create [name]')
16 | .alias('c')
17 | .description('创建应用程序.')
18 | .action(async (name = '', destination: any) => {
19 | await action.source('application').resolve(name, destination);
20 | });
21 | }
22 | }
--------------------------------------------------------------------------------
/packages/cli/src/commands/dev.ts:
--------------------------------------------------------------------------------
1 | import commander from 'commander';
2 | import { DevAction } from '../actions';
3 |
4 | /**
5 | * 开发模式命令声明
6 | */
7 | export class DevCommand {
8 | /**
9 | * Command
10 | */
11 | private program: commander.Command;
12 |
13 | /**
14 | * constructor
15 | * @param program
16 | */
17 | constructor(program: commander.Command) {
18 | this.program = program;
19 | }
20 |
21 | /**
22 | * 命令的实现
23 | * @param action
24 | */
25 | resolve(action: DevAction) {
26 | this.program
27 | .command('dev')
28 | .alias('d')
29 | .description('应用程序开发模式.')
30 | .option('--inspect [hostport]', '启动服务端调试模式')
31 | .option('--debug', '启动 debug 模式')
32 | .action(async (destination: any) => {
33 | if (!process.env.DAZE_ENV) {
34 | process.env.DAZE_ENV = 'dev';
35 | }
36 | action.resolve(destination);
37 | });
38 | }
39 | }
--------------------------------------------------------------------------------
/packages/cli/src/commands/index.ts:
--------------------------------------------------------------------------------
1 | export * from './create';
2 | export * from './make';
3 | export * from './routes';
4 | export * from './build';
5 | export * from './dev';
--------------------------------------------------------------------------------
/packages/cli/src/commands/make.ts:
--------------------------------------------------------------------------------
1 | import * as commander from 'commander';
2 | import { TPLActionAbstract } from '../actions';
3 |
4 |
5 | export class MakeCommand {
6 |
7 | private program: commander.Command;
8 |
9 | constructor(program: commander.Command) {
10 | this.program = program;
11 | }
12 |
13 | resolve(action: TPLActionAbstract) {
14 | this.program
15 | .command('make:controller [name]')
16 | .alias('mc')
17 | .description('创建 Controller 模板文件.')
18 | .option('-r, --rest', '使用 Rest 风格')
19 | .option('-p, --path ', '控制器所在目录, 默认 [controllers]')
20 | .action(async (name = '', destination: Record) => {
21 | await action.source('controller').resolve(name, destination);
22 | });
23 |
24 | this.program
25 | .command('make:service [name]')
26 | .alias('ms')
27 | .description('创建 Service 模板文件.')
28 | .action(async (name = '', destination: any) => {
29 | await action.source('service').resolve(name, destination);
30 | });
31 |
32 | this.program
33 | .command('make:schedule [name]')
34 | .alias('mskd')
35 | .description('创建 Schedule 模板文件.')
36 | .action(async (name = '', destination: any) => {
37 | await action.source('schedule').resolve(name, destination);
38 | });
39 |
40 | this.program
41 | .command('make:middleware [name]')
42 | .alias('mm')
43 | .description('创建 Middleware 模板文件.')
44 | .action(async (name = '', destination: any) => {
45 | await action.source('middleware').resolve(name, destination);
46 | });
47 |
48 | this.program
49 | .command('make:entity [name]')
50 | .alias('mm')
51 | .description('创建 Entity 模板文件.')
52 | .action(async (name = '', destination: any) => {
53 | await action.source('entity').resolve(name, destination);
54 | });
55 |
56 | }
57 | }
--------------------------------------------------------------------------------
/packages/cli/src/commands/routes.ts:
--------------------------------------------------------------------------------
1 | import * as commander from 'commander';
2 | import { RoutesAction } from '../actions';
3 |
4 |
5 | export class RoutesCommand {
6 |
7 | private program: commander.Command;
8 |
9 | constructor(program: commander.Command) {
10 | this.program = program;
11 | }
12 |
13 | resolve(action: RoutesAction) {
14 | this.program
15 | .command('routes')
16 | .alias('r')
17 | .description('输出项目路由信息.')
18 | .action(async () => {
19 | await action.resolve();
20 | });
21 | }
22 | }
--------------------------------------------------------------------------------
/packages/cli/src/config.interface.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | interface NativeTigerConfigInterface {
4 | [key: string]: any
5 | }
6 |
7 | export type TigerConfigInterface = NativeTigerConfigInterface
--------------------------------------------------------------------------------
/packages/cli/src/defaultTsConfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2017",
4 | "lib": [
5 | "esnext"
6 | ],
7 | "baseUrl": "./",
8 | "outDir": "dist",
9 | "module": "commonjs",
10 | "allowJs": false,
11 | "declaration": true,
12 | "sourceMap": true,
13 | "removeComments": true,
14 | "strict": true,
15 | "noImplicitAny": true,
16 | "strictNullChecks": true,
17 | "strictFunctionTypes": true,
18 | "strictPropertyInitialization": false,
19 | "noImplicitThis": true,
20 | "alwaysStrict": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "noImplicitReturns": true,
24 | "moduleResolution": "node",
25 | "allowSyntheticDefaultImports": true,
26 | "esModuleInterop": true,
27 | "experimentalDecorators": true,
28 | "emitDecoratorMetadata": true,
29 | "skipLibCheck": true,
30 | "preserveSymlinks": true
31 | },
32 | "include": [
33 | "src"
34 | ],
35 | "exclude": [
36 | "node_modules"
37 | ]
38 | }
--------------------------------------------------------------------------------
/packages/cli/src/index.ts:
--------------------------------------------------------------------------------
1 | import { CreateAction, MakeAction } from './actions';
2 | import { SourceType } from './lib/render';
3 | import { init } from './lib/init';
4 |
5 | export * from './config.interface';
6 |
7 | export function terminate(argv: string[]) {
8 | init(argv);
9 | }
10 |
11 | /**
12 | * 创建应用
13 | * @param name
14 | */
15 | export function create(name: string) {
16 | new CreateAction().source('application').resolve(name);
17 | }
18 |
19 | /**
20 | * 创建模块模板文件
21 | * @param name
22 | * @param type
23 | * @param options
24 | */
25 | export function make(name: string, type: SourceType, options: any) {
26 | new MakeAction().source(type).resolve(name, options);
27 | }
--------------------------------------------------------------------------------
/packages/cli/src/lib/config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-var-requires */
2 | import fs from 'fs';
3 | import path from 'path';
4 |
5 | /**
6 | * 注入默认值
7 | * @param target
8 | */
9 | function resolveDefaultValues(target: Record = {}) {
10 | target.dynamic = target.dynamic ?? true;
11 | return target;
12 | }
13 |
14 | /**
15 | * 加载用户自定义配置
16 | * tiger.config.ts
17 | * @returns
18 | */
19 | export async function loadCustomConfig() {
20 | const cwd = process.cwd();
21 | const ts = path.resolve(cwd, 'tiger.config.ts');
22 | const js = path.resolve(cwd, 'tiger.config.js');
23 | let deflector: any;
24 | if (fs.existsSync(ts)) {
25 | deflector = (await import(ts)).default;
26 | } else if (fs.existsSync(js)) {
27 | deflector = (await import(js)).default;
28 | }
29 | // 未找到文件
30 | if (!deflector) return resolveDefaultValues();
31 | // 定义的类格式
32 | if (typeof deflector === 'function') {
33 | return resolveDefaultValues(new deflector());
34 | }
35 | // 对象格式
36 | return resolveDefaultValues(deflector);
37 |
38 | }
--------------------------------------------------------------------------------
/packages/cli/src/lib/constants.ts:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 |
3 | export const DAZE_SERVER_PREFIX = chalk.yellow('[DAZE][Server]');
4 | export const DAZE_CLIENT_PREFIX = chalk.greenBright('[DAZE][Client]');
--------------------------------------------------------------------------------
/packages/cli/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | export * from './render';
2 | export * from './question';
3 | export * from './printer';
4 | export * from './ts_compile';
5 | export * from './constants';
--------------------------------------------------------------------------------
/packages/cli/src/lib/init.ts:
--------------------------------------------------------------------------------
1 | import { Command } from 'commander';
2 | import { CreateCommand, MakeCommand, RoutesCommand, BuildCommand, DevCommand } from '../commands';
3 | import { CreateAction, MakeAction, RoutesAction, BuildAction, DevAction } from '../actions';
4 |
5 | export function init(argv?: string[]) {
6 |
7 | const program = new Command();
8 |
9 | program
10 | // eslint-disable-next-line @typescript-eslint/no-var-requires
11 | .version(require('../../package.json').version, '-v, --version');
12 |
13 | new CreateCommand(program)
14 | .resolve(
15 | new CreateAction()
16 | );
17 |
18 | new MakeCommand(program)
19 | .resolve(
20 | new MakeAction()
21 | );
22 |
23 | new RoutesCommand(program)
24 | .resolve(
25 | new RoutesAction()
26 | );
27 |
28 | new DevCommand(program)
29 | .resolve(
30 | new DevAction()
31 | );
32 |
33 | new BuildCommand(program)
34 | .resolve(
35 | new BuildAction()
36 | );
37 |
38 | program.parse(argv??process.argv);
39 | }
--------------------------------------------------------------------------------
/packages/cli/src/lib/printer.ts:
--------------------------------------------------------------------------------
1 | export class Printer {
2 | static power() {
3 | console.log('');
4 | }
5 | }
--------------------------------------------------------------------------------
/packages/cli/src/lib/question.ts:
--------------------------------------------------------------------------------
1 | import inquirer from 'inquirer';
2 |
3 | export class Question {
4 | private inquirer = inquirer;
5 |
6 | private promptList: inquirer.QuestionCollection[] = [];
7 |
8 | projectType() {
9 | return this;
10 | }
11 |
12 | packageManager() {
13 | this.promptList.push({
14 | type: 'list',
15 | name: 'packageManager',
16 | message: '选择包管理工具',
17 | choices: [{
18 | name: 'npm',
19 | value: 'npm',
20 | }, {
21 | name: 'yarn',
22 | value: 'yarn'
23 | }, {
24 | name: 'pnpm',
25 | value: 'pnpm'
26 | }, {
27 | name: '自行安装依赖',
28 | value: 'disable'
29 | }]
30 | });
31 | return this;
32 | }
33 | async ask() {
34 | return this.inquirer.prompt(this.promptList);
35 | }
36 | }
--------------------------------------------------------------------------------
/packages/cli/src/lib/runner/index.ts:
--------------------------------------------------------------------------------
1 | export * from './npm';
2 | export * from './yarn';
3 | export * from './pnpm';
--------------------------------------------------------------------------------
/packages/cli/src/lib/runner/npm.ts:
--------------------------------------------------------------------------------
1 | import { Runner } from './runner';
2 |
3 | export class NpmRunner extends Runner {
4 | constructor() {
5 | super('npm');
6 | }
7 | }
--------------------------------------------------------------------------------
/packages/cli/src/lib/runner/pnpm.ts:
--------------------------------------------------------------------------------
1 | import { Runner } from './runner';
2 |
3 | export class PNpmRunner extends Runner {
4 | constructor() {
5 | super('pnpm');
6 | }
7 | }
--------------------------------------------------------------------------------
/packages/cli/src/lib/runner/runner.ts:
--------------------------------------------------------------------------------
1 | import { ChildProcess, spawn, SpawnOptions } from 'child_process';
2 | import chalk from 'chalk';
3 | import * as path from 'path';
4 |
5 | type RunnerBinary = 'npm' | 'yarn' | 'pnpm'
6 |
7 | export class Runner {
8 |
9 | private binary: RunnerBinary;
10 | private _directory = '';
11 |
12 | constructor(binary: RunnerBinary) {
13 | this.binary = binary;
14 | }
15 |
16 | directory(directory: string) {
17 | this._directory = directory;
18 | return this;
19 | }
20 |
21 | async run(...args: string[]) {
22 | return new Promise((resolve, reject) => {
23 | const options: SpawnOptions = {
24 | cwd: path.join(process.cwd(), this._directory),
25 | stdio: 'inherit',
26 | shell: true,
27 | };
28 | const child: ChildProcess = spawn('npx', [this.binary, ...args], options);
29 | child.on('close', code => {
30 | if (code === 0) {
31 | resolve(null);
32 | } else {
33 | console.error(
34 | chalk.red(
35 | `\nFailed to execute command: npx ${this.binary} ${args.join(' ')}`,
36 | ),
37 | );
38 | reject();
39 | }
40 | });
41 | });
42 | }
43 | }
--------------------------------------------------------------------------------
/packages/cli/src/lib/runner/yarn.ts:
--------------------------------------------------------------------------------
1 | import { Runner } from './runner';
2 |
3 | export class YarnRunner extends Runner {
4 | constructor() {
5 | super('yarn');
6 | }
7 | }
--------------------------------------------------------------------------------
/packages/cli/template/application/.gitignore:
--------------------------------------------------------------------------------
1 | # dependencies
2 | node_modules/
3 |
4 | # IDE
5 | /.idea
6 | /.awcache
7 | /.vscode
8 | *.code-workspace
9 |
10 |
11 | # logs
12 | logs/*.log
13 | **/logs/**.log
14 |
15 | # misc
16 | .DS_Store
17 | lerna-debug.log
18 | npm-debug.log
19 | yarn-error.log
20 | packages/*/__debug__
21 | .clinic
22 |
23 | # custom
24 | /dist
--------------------------------------------------------------------------------
/packages/cli/template/application/daze:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const daze = require('@dazejs/cli');
4 |
5 | daze.terminate(process.argv);
6 |
--------------------------------------------------------------------------------
/packages/cli/template/application/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "daze dev",
5 | "build": "daze build"
6 | },
7 | "keywords": [],
8 | "author": "",
9 | "license": "UNLICENSE",
10 | "dependencies": {
11 | {% for pkg, version in depensMap %}
12 | "{{ pkg }}": "{{ version }}"{% if loop.last %}{% else %},{% endif %}
13 |
14 | {% endfor %}
15 | },
16 | "devDependencies": {
17 | {% for pkg, version in devDepensMap %}
18 | "{{ pkg }}": "{{ version }}"{% if loop.last %}{% else %},{% endif %}
19 |
20 | {% endfor %}
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/cli/template/application/public/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dazejs/daze/e9d67d915a33c70cb5cdd731fc585a48a5872a5a/packages/cli/template/application/public/.keep
--------------------------------------------------------------------------------
/packages/cli/template/application/src/app/example.controller.ts:
--------------------------------------------------------------------------------
1 | import { view, Controller, Get } from '@dazejs/framework';
2 |
3 | @Controller()
4 | export class Example {
5 | @Get()
6 | index() {
7 | return view('hello.html')
8 | }
9 | }
--------------------------------------------------------------------------------
/packages/cli/template/application/src/config/app.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | /**
3 | * debug mode
4 | *
5 | * Be sure to turn debug off in a production environment
6 | */
7 | debug: true,
8 |
9 | /**
10 | * static server with public path
11 | *
12 | * public - enabled or disabled public static resource request
13 | *
14 | * public_prefix - public resource request root dir
15 | */
16 | public: true,
17 |
18 | publicPrefix: '/assets',
19 |
20 |
21 | /**
22 | * Turn on compression
23 | *
24 | * compress - enable compression
25 | *
26 | * threshold - The compression threshold
27 | */
28 | compress: true,
29 |
30 | threshold: 1024,
31 |
32 | /**
33 | * View config
34 | *
35 | * view_extension - The view defaults to the HTML suffix
36 | */
37 |
38 | viewExtension: 'html',
39 |
40 | /**
41 | * Cluster
42 | *
43 | * enable - enable or disable cluster mode
44 | *
45 | * workers - Number of work processes, set to 0 by default using CPU cores
46 | *
47 | * sticky - ticky session
48 | */
49 |
50 | cluster: false,
51 |
52 | workers: 0,
53 |
54 | sticky: false,
55 |
56 | /**
57 | * template
58 | */
59 | httpErrorTemplate: {
60 | /* ex: 404: 'errors/404.njk', root path: /views */
61 | },
62 |
63 | providers: [],
64 | };
--------------------------------------------------------------------------------
/packages/cli/template/application/src/config/cache.ts:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | /**
4 | * 默认使用的存储器
5 | * 可选:memory | redis | fs
6 | */
7 | store: 'fs'
8 | }
--------------------------------------------------------------------------------
/packages/cli/template/application/src/config/cookie.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | /** 浏览器的最长保存时间。是一个从服务器当前时刻开始的毫秒数。 */
3 | maxAge: 0,
4 |
5 | /** 失效时间,如果设置了 maxAge,expires 将会被覆盖。 */
6 | expires: '',
7 |
8 | /** 生效的 URL 路径,默认设置在根路径上(/) */
9 | path: '/',
10 |
11 | /** 设置是否对 Cookie 进行签名 */
12 | signed: false,
13 |
14 | /** 生效的域名 */
15 | domain: '',
16 |
17 | /** 是否可以被 js 访问,默认为 true,不允许被 js 访问 */
18 | httpOnly: true,
19 |
20 | /** 设置 key 相同的键值对如何处理,如果设置为 true,则后设置的值会覆盖前面设置的,否则将会发送两个 set-cookie 响应头 */
21 | overwrite: false,
22 |
23 | /** 设置只在 HTTPS 连接上传输 */
24 | secure: false,
25 | };
--------------------------------------------------------------------------------
/packages/cli/template/application/src/config/database.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | default: {
3 | type: 'mysql',
4 | host: '127.0.0.1',
5 | user: 'root',
6 | password: 'root',
7 | port: 3306,
8 | database: 'daze'
9 | },
10 | };
--------------------------------------------------------------------------------
/packages/cli/template/application/src/config/logger.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 |
3 | export default {
4 | default: 'console',
5 | channels: {
6 | compose: {
7 | driver: 'compose',
8 | channels: ['console', 'dailyFile'],
9 | },
10 | console: {
11 | driver: 'console',
12 | },
13 | dailyFile: {
14 | driver: 'dailyFile',
15 | filename: 'common-%DATE%.log',
16 | dirname: path.resolve(__dirname, '../../logs'),
17 | },
18 | },
19 | };
--------------------------------------------------------------------------------
/packages/cli/template/application/src/config/redis.ts:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | /**
4 | * 默认 Redis 连接
5 | */
6 | default: {
7 | host: 'localhost',
8 | port: 6379
9 | },
10 |
11 | /**
12 | * 缓存专用默认 reids 连接
13 | * 未定义的情况下,默认使用 default 连接
14 | */
15 | // cache: {
16 | // host: 'localhost',
17 | // port: 6379
18 | // },
19 |
20 | /**
21 | * 任务调度专用默认 reids 连接
22 | * 未定义的情况下,默认使用 default 连接
23 | */
24 | // schedule: {
25 | // host: 'localhost',
26 | // port: 6379
27 | // },
28 | }
--------------------------------------------------------------------------------
/packages/cli/template/application/src/config/session.ts:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | /**
4 | * ===============================================
5 | * Session Store
6 | * ===============================================
7 | * Supported: cookie | redis
8 | */
9 | store: 'cookie',
10 | /**
11 | * ===============================================
12 | * Cookie Session Key
13 | * ===============================================
14 | */
15 | key: 'dazejs:sess',
16 |
17 | /**
18 | * ===============================================
19 | * Renew Session
20 | * ===============================================
21 | * Should renew session expried time when true
22 | */
23 | renew: false,
24 |
25 | /**
26 | * ===============================================
27 | * Session MaxAge
28 | * ===============================================
29 | */
30 | maxAge: 8640000,
31 |
32 | /**
33 | * ===============================================
34 | * HttpOnly Session Cookie
35 | * ===============================================
36 | */
37 | httpOnly: true,
38 |
39 | /**
40 | * ===============================================
41 | * Signed Session
42 | * ===============================================
43 | */
44 | signed: true,
45 |
46 | /**
47 | * ===============================================
48 | * Session auto commit
49 | * ===============================================
50 | */
51 | autoCommit: true,
52 |
53 | /**
54 | * ===============================================
55 | * Redis Store Connection
56 | * ===============================================
57 | */
58 | connection: 'session',
59 | };
--------------------------------------------------------------------------------
/packages/cli/template/application/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Application } from '@dazejs/framework'
2 |
3 | const app = new Application()
4 |
5 | app.run()
--------------------------------------------------------------------------------
/packages/cli/template/application/views/hello.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Daze.js
8 |
33 |
34 |
35 |
36 |
37 | Hello, Daze.js!
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/packages/cli/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "dist",
6 | "module": "commonjs"
7 | },
8 | "include": [
9 | "src",
10 | "g.d.ts"
11 | ],
12 | "exclude": [
13 | "node_modules"
14 | ]
15 | }
--------------------------------------------------------------------------------
/packages/create-app/README.md:
--------------------------------------------------------------------------------
1 | # `create`
2 |
3 | > TODO: description
4 |
5 | ## Usage
6 |
7 | ```
8 | const create = require('create');
9 |
10 | // TODO: DEMONSTRATE API
11 | ```
12 |
--------------------------------------------------------------------------------
/packages/create-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@dazejs/create-app",
3 | "version": "1.0.2",
4 | "description": "create dazejs app",
5 | "author": "czewail ",
6 | "homepage": "",
7 | "license": "UNLICENSE",
8 | "files": [
9 | "lib"
10 | ],
11 | "bin": {
12 | "create-app": "dist/create.js"
13 | },
14 | "scripts": {
15 | "clean": "rimraf dist/*",
16 | "build": "npm run clean && tsc",
17 | "test": "node -v",
18 | "test:coverage": "node -v",
19 | "dev": "npm run clean && tsc -w"
20 | },
21 | "dependencies": {
22 | "@dazejs/cli": "1.0.2",
23 | "chalk": "^4.1.1",
24 | "commander": "^7.2.0"
25 | },
26 | "gitHead": "4d87844d5c3483689a94a63ac992c98ab9ff1224"
27 | }
28 |
--------------------------------------------------------------------------------
/packages/create-app/src/create.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import { create } from '@dazejs/cli';
4 | import { Command } from 'commander';
5 | import chalk from 'chalk';
6 |
7 | // eslint-disable-next-line @typescript-eslint/no-var-requires
8 | const packageJson = require('../package.json');
9 |
10 |
11 | const program = new Command(packageJson.name);
12 |
13 | program
14 | .version(packageJson.version, '-v, --version')
15 | .arguments('')
16 | .usage(`${chalk.green('')}`)
17 | .action(name => {
18 | create(name);
19 | });
20 |
21 | program.parse(process.argv);
22 |
23 |
--------------------------------------------------------------------------------
/packages/create-app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "dist",
6 | "module": "commonjs"
7 | },
8 | "include": [
9 | "src",
10 | ],
11 | "exclude": [
12 | "node_modules"
13 | ]
14 | }
--------------------------------------------------------------------------------
/packages/framework/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | __tests__
4 | __debug__
5 | .idea
6 | .vscode
7 | logs
8 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/common/assets/example.txt:
--------------------------------------------------------------------------------
1 | example
--------------------------------------------------------------------------------
/packages/framework/__tests__/common/context.ts:
--------------------------------------------------------------------------------
1 |
2 | import Stream from 'stream';
3 | import { IncomingMessage, ServerResponse } from 'http';
4 |
5 | export function context(_req?: object, _res?: object) {
6 | const socket = new Stream.Duplex();
7 | const req = Object.assign({ headers: {}, socket }, Stream.Readable.prototype, _req) as IncomingMessage;
8 | const res = Object.assign({ _headers: {}, socket }, Stream.Writable.prototype, _res) as unknown as ServerResponse;
9 | // eslint-disable-next-line
10 | // @ts-ignore
11 | req.socket.remoteAddress = req.socket.remoteAddress || '127.0.0.1';
12 | return { req, res };
13 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/logs/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dazejs/daze/e9d67d915a33c70cb5cdd731fc585a48a5872a5a/packages/framework/__tests__/daze/logs/.keep
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/component/InjectComponent.ts:
--------------------------------------------------------------------------------
1 | import { Component, Injectable } from '../../../../../src';
2 |
3 | @Component()
4 | @Injectable
5 | export class InjectComponent {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/component/TestLogger.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Test for Logger
3 | */
4 | export class TestLogger {
5 | private readonly props: any;
6 |
7 | constructor(props: any) {
8 | this.props = props;
9 | }
10 |
11 | log(l: any): string {
12 | return `TestLogger(${this.props}) => ${l}`;
13 | }
14 |
15 | }
16 |
17 | export class TestLogger2 {
18 | private readonly props: any;
19 |
20 | constructor(props: any) {
21 | this.props = props;
22 | }
23 |
24 | log(l: any): string {
25 | return `TestLogger2(${this.props}) => ${l}`;
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/autoinject.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller, Get
3 | } from '../../../../../src';
4 | import ExampleService from '../service/example';
5 |
6 | @Controller('autoinject')
7 | export default class {
8 | @Get()
9 | index(example: ExampleService) {
10 | return example.sayHello();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/cross.ts:
--------------------------------------------------------------------------------
1 | import {
2 | CrossOrigin, Controller, Post,
3 | } from '../../../../../src';
4 |
5 | @Controller('cross')
6 | export default class {
7 | @Post()
8 | @CrossOrigin()
9 | store() {
10 | return 'hello';
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/csrf.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller, Post, Get, Csrf,
3 | } from '../../../../../src';
4 |
5 | @Controller('/csrf')
6 | export default class {
7 | @Post()
8 | @Csrf()
9 | store() {
10 | return 'hello';
11 | }
12 |
13 | @Get('/get')
14 | @Csrf()
15 | show() {
16 | return 'hello';
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/dto/daze.dto.ts:
--------------------------------------------------------------------------------
1 |
2 | export class DazeDto {
3 | readonly id: number;
4 | readonly name: string;
5 | readonly age: number;
6 | }
7 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/example.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller, Get, Autowired, Post, request, View
3 | } from '../../../../../src';
4 | import ExampleService from '../service/example';
5 |
6 |
7 | @Controller('/example')
8 | export default class {
9 | @Autowired
10 | exampleService: ExampleService;
11 |
12 | @Get('/template')
13 | template() {
14 | return new View('hello', {
15 | name: 'dazejs'
16 | });
17 | }
18 |
19 | @Get()
20 | index() {
21 | return this.exampleService.sayHello();
22 | }
23 |
24 | @Post('post')
25 | store() {
26 | return {
27 | body: request().body,
28 | files: request().files,
29 | };
30 | }
31 |
32 | @Get('/null')
33 | sayNull() {
34 | return null;
35 | }
36 |
37 | @Get('/number')
38 | sayNumber(): number {
39 | return 0;
40 | }
41 |
42 | @Get('/boolean')
43 | sayBoolean(): boolean {
44 | return true;
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/injectable.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller, Get, Query, Params, Body, Header, Post
3 | } from '../../../../../src';
4 | import { DazeDto } from "./dto/daze.dto";
5 |
6 | @Controller('/injectable')
7 | export default class {
8 | @Get()
9 | index(@Query('id') id: number) {
10 | return id || 'hello world';
11 | }
12 |
13 | @Get('name')
14 | getName(@Query('id') id: number, @Query('name') name: string) {
15 | return `${id}:${name}` || 'hello world';
16 | }
17 |
18 | @Get('name/default')
19 | getNameDefault(@Query('name', "daze") name: string) {
20 | return name;
21 | }
22 |
23 | @Get('params')
24 | getParams(@Params() params: any) {
25 | return params;
26 | }
27 |
28 | @Post('body')
29 | getDazeBody(@Body() dto: DazeDto): DazeDto {
30 | return dto;
31 | }
32 |
33 | @Post('body2')
34 | getDazeBody2(@Body('key2.key1') dto: DazeDto): DazeDto {
35 | return dto;
36 | }
37 |
38 | @Get('header')
39 | getHeader(@Header('my-header') host: string) {
40 | return host;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/middleware.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller, Get, UseMiddleware
3 | } from '../../../../../src';
4 | import { Example1 } from '../middleware/example-1';
5 | import { Example2 } from '../middleware/example-2';
6 |
7 | @Controller('/middleware')
8 | @UseMiddleware(Example2)
9 | export class MiddlewareController {
10 | @Get('/example1')
11 | @UseMiddleware(Example1)
12 | store() {
13 | return 'Hello Dazejs';
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/redirect.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller, Get, Redirect
3 | } from '../../../../../src';
4 |
5 |
6 | @Controller('/redirect')
7 | export default class {
8 | @Get()
9 | show() {
10 | return new Redirect().go('https://www.google.com');
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/controller/routes.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Controller, Get,
3 | } from '../../../../../src';
4 |
5 | @Controller('routes')
6 | export default class {
7 | @Get('*')
8 | all1() {
9 | return 'all1';
10 | }
11 |
12 | @Get('all2')
13 | all2() {
14 | return 'all2';
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/entities/comment.ts:
--------------------------------------------------------------------------------
1 | import { BaseEntity, AutoIncrementPrimaryColumn, Column, BelongsTo, Entity } from '../../../../../src';
2 | import User from './user';
3 |
4 | @Entity('comments')
5 | export default class extends BaseEntity {
6 | @AutoIncrementPrimaryColumn()
7 | id: number;
8 |
9 | @Column()
10 | user_id: number;
11 |
12 | @Column()
13 | comment: string;
14 |
15 | @BelongsTo(() => User)
16 | user: User;
17 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/entities/profile.ts:
--------------------------------------------------------------------------------
1 | import { BaseEntity, AutoIncrementPrimaryColumn, Column, BelongsTo, Entity } from '../../../../../src';
2 | import User from './user';
3 |
4 | @Entity('profiles')
5 | export default class extends BaseEntity {
6 | @AutoIncrementPrimaryColumn()
7 | id: number;
8 |
9 | @Column()
10 | user_id: number;
11 |
12 | @Column()
13 | motto: string;
14 |
15 | @BelongsTo(() => User)
16 | user: User;
17 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/entities/role.ts:
--------------------------------------------------------------------------------
1 | import { BaseEntity, AutoIncrementPrimaryColumn, Column, BelongsToMany, Entity } from '../../../../../src';
2 | import User from './user';
3 |
4 |
5 | @Entity('roles')
6 | export default class extends BaseEntity {
7 | @AutoIncrementPrimaryColumn()
8 | id: number;
9 |
10 | @Column()
11 | description: string;
12 |
13 | @BelongsToMany(() => User)
14 | users: User[];
15 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/entities/user.ts:
--------------------------------------------------------------------------------
1 | import { BaseEntity, AutoIncrementPrimaryColumn, Column, BelongsToMany, HasOne, Entity, HasMany } from '../../../../../src';
2 | import Profile from './profile';
3 | import Comment from './comment';
4 | import Role from './role';
5 |
6 | @Entity('users')
7 | export default class extends BaseEntity {
8 | @AutoIncrementPrimaryColumn()
9 | id: number;
10 |
11 | @Column()
12 | name: string;
13 |
14 | @Column()
15 | age: number;
16 |
17 | @Column()
18 | description: string;
19 |
20 | @HasOne(() => Profile)
21 | profile: Profile;
22 |
23 | @HasMany(() => Comment)
24 | comments: Comment[];
25 |
26 | @BelongsToMany(() => Role)
27 | roles: Role[];
28 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/middleware/example-1.ts:
--------------------------------------------------------------------------------
1 | import { Request, Next, Middleware, Response } from '../../../../../src';
2 |
3 | @Middleware()
4 | export class Example1 {
5 | resolve(request: Request, next: Next) {
6 | if (request.getQuery('name') === 'example1') {
7 | return new Response().success('Hello Example1');
8 | }
9 | return next();
10 | }
11 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/middleware/example-2.ts:
--------------------------------------------------------------------------------
1 | import { Request, Next, Middleware, Response } from '../../../../../src';
2 |
3 | @Middleware()
4 | export class Example2 {
5 | resolve(request: Request, next: Next) {
6 | if (request.getQuery('name') === 'example2') {
7 | return new Response().success('Hello Example2');
8 | }
9 | return next();
10 | }
11 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/middleware/example-order.ts:
--------------------------------------------------------------------------------
1 | import { Order, Middleware } from '../../../../../src';
2 |
3 | @Middleware()
4 | export class ExampleMiddlewareOrder {
5 | resolve(): any | Promise {
6 | return 'ExampleMiddlewareOrder';
7 | }
8 | }
9 |
10 | @Order(0)
11 | @Middleware()
12 | export class ExampleMiddlewareOrder0 {
13 | resolve(): any | Promise {
14 | return 'ExampleMiddlewareOrder0';
15 | }
16 | }
17 |
18 | @Order(1)
19 | @Middleware()
20 | export class ExampleMiddlewareOrder1 {
21 | resolve(): any | Promise {
22 | return 'ExampleMiddlewareOrder1';
23 | }
24 | }
25 |
26 | @Order(Number.MAX_SAFE_INTEGER)
27 | @Middleware()
28 | export class ExampleMiddlewareOrderMax {
29 | resolve(): any | Promise {
30 | return 'ExampleMiddlewareOrderMax';
31 | }
32 | }
33 |
34 | @Order(Number.MIN_SAFE_INTEGER)
35 | @Middleware()
36 | export class ExampleMiddlewareOrderMin {
37 | resolve(): any | Promise {
38 | return 'ExampleMiddlewareOrderMin';
39 | }
40 | }
41 |
42 | @Order(Number.MAX_SAFE_INTEGER + 1)
43 | @Middleware()
44 | export class ExampleMiddlewareOrderMax1 {
45 | resolve(): any | Promise {
46 | return 'ExampleMiddlewareOrderMax1';
47 | }
48 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/service/example.ts:
--------------------------------------------------------------------------------
1 | import { Service } from '../../../../../src';
2 |
3 | @Service('example-service')
4 | export default class {
5 | sayHello() {
6 | return 'Hello Dazejs';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/app/service/injectable.ts:
--------------------------------------------------------------------------------
1 | import { Query, Service } from '../../../../../src';
2 |
3 |
4 | @Service('injectable-service')
5 | export default class {
6 | sayId(
7 | @Query('id') id: number
8 | ) {
9 | return id ?? 'Hello Dazejs';
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/app.test.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | name: 'dazejs',
3 | };
4 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/app.ts:
--------------------------------------------------------------------------------
1 | import { TestLoggerProvider } from '../provider/test-logger-provider';
2 | export default {
3 | port: 0,
4 | proxy: false,
5 | cluster: false,
6 | workers: 0,
7 | sticky: false,
8 | viewExtension: 'html',
9 | providers: [
10 | TestLoggerProvider
11 | ]
12 | };
13 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/cookie.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | /** 浏览器的最长保存时间。是一个从服务器当前时刻开始的毫秒数。 */
3 | maxAge: 0,
4 |
5 | /** 失效时间,如果设置了 maxAge,expires 将会被覆盖。 */
6 | expires: '',
7 |
8 | /** 生效的 URL 路径,默认设置在根路径上(/) */
9 | path: '/',
10 |
11 | /** 设置是否对 Cookie 进行签名 */
12 | signed: true,
13 |
14 | /** 生效的域名 */
15 | domain: '',
16 |
17 | /** 是否可以被 js 访问,默认为 true,不允许被 js 访问 */
18 | httpOnly: true,
19 |
20 | /** 设置 key 相同的键值对如何处理,如果设置为 true,则后设置的值会覆盖前面设置的,否则将会发送两个 set-cookie 响应头 */
21 | overwrite: false,
22 |
23 | /** 设置只在 HTTPS 连接上传输 */
24 | secure: false,
25 | };
26 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/custom.test.ts:
--------------------------------------------------------------------------------
1 | export default () => {
2 | //
3 | };
4 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/custom.ts:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | a: {
4 | b: {
5 | c: 'c',
6 | },
7 | },
8 | };
9 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/database.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | default: {
3 | type: 'mysql',
4 | host: 'localhost',
5 | user: 'root',
6 | password: 'root',
7 | port: 3306,
8 | database: 'daze'
9 | },
10 | session: {
11 | type: 'redis',
12 | host: '127.0.0.1',
13 | port: 6379
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/daze.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | redis: {
3 | host: '127.0.0.1',
4 | port: 6379,
5 | }
6 | };
7 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/logger.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import fs from 'fs';
3 |
4 | export default {
5 | default: 'console',
6 | channels: {
7 | compose: {
8 | driver: 'compose',
9 | channels: ['console', 'dailyFile'],
10 | },
11 | console: {
12 | driver: 'console',
13 | },
14 | console3: {
15 | driver: 'console3',
16 | },
17 | file: {
18 | driver: 'file',
19 | filename: path.resolve(__dirname, '../logs'),
20 | },
21 | http: {
22 | driver: 'http',
23 | },
24 | stream: {
25 | driver: 'stream',
26 | stream: fs.createWriteStream('/dev/null'),
27 | },
28 | dailyFile: {
29 | driver: 'dailyFile',
30 | filename: 'common-%DATE%.log',
31 | dirname: path.resolve(__dirname, '../../logs'),
32 | },
33 | },
34 | };
35 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/config/session.ts:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | /**
4 | * ===============================================
5 | * Session Store
6 | * ===============================================
7 | * Supported: cookie | redis
8 | */
9 | store: 'cookie',
10 | /**
11 | * ===============================================
12 | * Cookie Session Key
13 | * ===============================================
14 | */
15 | key: 'dazejs:sess',
16 |
17 | /**
18 | * ===============================================
19 | * Renew Session
20 | * ===============================================
21 | * Should renew session expried time when true
22 | */
23 | renew: false,
24 |
25 | /**
26 | * ===============================================
27 | * Session MaxAge
28 | * ===============================================
29 | */
30 | maxAge: 8640000,
31 |
32 | /**
33 | * ===============================================
34 | * HttpOnly Session Cookie
35 | * ===============================================
36 | */
37 | httpOnly: true,
38 |
39 | /**
40 | * ===============================================
41 | * Signed Session
42 | * ===============================================
43 | */
44 | signed: true,
45 |
46 | /**
47 | * ===============================================
48 | * Session auto commit
49 | * ===============================================
50 | */
51 | autoCommit: true,
52 |
53 | /**
54 | * ===============================================
55 | * Redis Store Connection
56 | * ===============================================
57 | */
58 | connection: 'session',
59 | };
60 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/logs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dazejs/daze/e9d67d915a33c70cb5cdd731fc585a48a5872a5a/packages/framework/__tests__/daze/src/logs
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/provider/app.ts:
--------------------------------------------------------------------------------
1 |
2 | import { Provider } from '../../../../src';
3 |
4 | @Provider()
5 | export default class {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/src/provider/test-logger-provider.ts:
--------------------------------------------------------------------------------
1 | import { Depends, Provide, ProvideOn, ProvideOnMissing } from "../../../../src/decorators";
2 | import { config } from "../../../../src";
3 | import { TestLogger, TestLogger2 } from "../app/component/TestLogger";
4 |
5 | @Depends()
6 | export class TestLoggerProvider {
7 | @Provide()
8 | @ProvideOnMissing('testLogger')
9 | testLogger() {
10 | return new TestLogger(config("custom.a.b.c", 'testConfig'));
11 | }
12 |
13 | @Provide()
14 | @ProvideOn("not-exists")
15 | testLogger2() {
16 | return new TestLogger2(config("custom.a.b.c1", "testConfig2"));
17 | }
18 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/daze/views/hello.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Daze.js
8 |
33 |
34 |
35 |
36 |
37 | Hello, {{name}}!
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/features/current/app/test.ts:
--------------------------------------------------------------------------------
1 | import { Get, Controller } from '../../../../src';
2 |
3 | @Controller('/features/current')
4 | export class App {
5 | @Get()
6 | index() {
7 | return 'hello current';
8 | }
9 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/features/current/config/app.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | cluster: false
3 | };
--------------------------------------------------------------------------------
/packages/framework/__tests__/features/current/current.spec.ts:
--------------------------------------------------------------------------------
1 | import request from 'supertest';
2 | import { Application } from '../../../src';
3 |
4 | const app = new Application();
5 |
6 |
7 | beforeAll(() => app.run(7677), 10);
8 | afterAll(() => app.close(), 10);
9 |
10 |
11 | it('should work base', async () => {
12 | await request((app as any)._server).get('/features/current').expect(200, 'hello current');
13 | });
14 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/features/index.spec.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import request from 'supertest';
3 | import { Application } from '../../src';
4 |
5 | const app = new Application({
6 | rootPath: path.resolve(__dirname, '../daze/src')
7 | });
8 |
9 |
10 | beforeAll(() => app.run(7676));
11 | afterAll(() => app.close());
12 |
13 |
14 | it('should work base', async () => {
15 | await request((app as any)._server).get('/example').expect(200, 'Hello Dazejs');
16 | await request((app as any)._server).get('/example/template').expect(200);
17 | await request((app as any)._server).get('/example/null').expect(204, '');
18 | await request((app as any)._server).get('/example/number').expect(200, '0');
19 | await request((app as any)._server).get('/example/boolean').expect(200, 'true');
20 | });
21 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/cluster/worker.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { Worker } from '../../../src/cluster/worker';
3 | import * as http from 'http';
4 | import request from 'supertest';
5 |
6 | describe('Worker Process', () => {
7 | it('should run with createServer', async () => {
8 | const worker = new Worker({
9 | port: 0,
10 | sticky: false,
11 | createServer: (...args) => {
12 | const server = http.createServer((_req, res) => {
13 | res.end('cluster');
14 | });
15 | return server.listen(...args);
16 | }
17 | });
18 | const server = await worker.run();
19 | const res = await request(server).get('/');
20 | expect(res.text).toBe('cluster');
21 | server.close();
22 | });
23 | });
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/database/init.ts:
--------------------------------------------------------------------------------
1 | import * as mysql from 'mysql2';
2 |
3 | async function dropTable(connection: mysql.Connection, table: string) {
4 | await new Promise((resolve, reject) => {
5 | connection.query(`DROP TABLE \`${table}\``, (err) => {
6 | if (err) {
7 | if (err.code === 'ER_BAD_TABLE_ERROR') {
8 | return resolve(true);
9 | } else {
10 | console.error('[DROP ERROR] - ', err.message);
11 | return reject(err);
12 | }
13 | }
14 | return resolve(true);
15 | });
16 | });
17 | }
18 |
19 | async function createTable(connection: mysql.Connection, sql: string) {
20 | await new Promise((resolve, reject) => {
21 | connection.query(sql, (err) => {
22 | if (err) {
23 | console.error('[CREATE ERROR] - ', err.message);
24 | return reject(err);
25 | }
26 | return resolve(true);
27 | });
28 | });
29 | }
30 |
31 |
32 | export async function initDb() {
33 | const connection = mysql.createConnection({
34 | host: 'localhost',
35 | user: 'root',
36 | password: 'root',
37 | database: 'daze',
38 | port: 3306
39 | });
40 |
41 | connection.connect();
42 |
43 | // 删除 users 表
44 | await dropTable(connection, 'users');
45 | // 删除 comments 表
46 | await dropTable(connection, 'comments');
47 | // 创建 users 表
48 | await createTable(connection, `CREATE TABLE \`users\` (
49 | \`id\` int(11) unsigned NOT NULL AUTO_INCREMENT,
50 | \`name\` varchar(255) NOT NULL DEFAULT '',
51 | \`age\` int(11) NOT NULL,
52 | \`description\` varchar(255) DEFAULT NULL,
53 | PRIMARY KEY (\`id\`)
54 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`);
55 | // 创建 comments 表
56 | await createTable(connection, `CREATE TABLE \`comments\` (
57 | \`id\` int(11) unsigned NOT NULL AUTO_INCREMENT,
58 | \`user_id\` int(11) NOT NULL,
59 | \`comment\` varchar(11) NOT NULL DEFAULT '',
60 | PRIMARY KEY (\`id\`)
61 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;`);
62 |
63 | connection.end();
64 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/decorators/component.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { Component } from '../../../src/decorators/stereotype/component';
3 |
4 | describe('Component Decorator', () => {
5 | it('should patch injectable and name in Component', () => {
6 | @Component('example')
7 | class Example { }
8 | expect(Reflect.getMetadata('name', Example)).toBe('example');
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/decorators/factory/create-inject-decorator.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { decoratorFactory } from '../../../../src/decorators/factory/decorator-factory';
3 | import * as symbols from '../../../../src/symbol';
4 |
5 | describe('Descrators/factory/create-inject-decorator', () => {
6 | describe('patchClass', () => {
7 | it('should patch injectable and types in constructor', () => {
8 | @decoratorFactory('request', ['a', 'b'])
9 | class Klass {
10 | testname: string;
11 | constructor() {
12 | this.testname = '';
13 | }
14 | }
15 | expect(Reflect.getMetadata(symbols.INJECTABLE, Klass)).toBeTruthy();
16 | expect(Reflect.getMetadata(symbols.INJECTTYPE_METADATA, Klass)).toEqual([
17 | {
18 | abstract: 'request',
19 | params: ['a', 'b'],
20 | handler: undefined
21 | }
22 | ]);
23 | });
24 | });
25 |
26 | describe('patchProperty', () => {
27 | it('should patch injectable and types in property', () => {
28 | class Klass {
29 | @decoratorFactory('request', ['a', 'b'])
30 | testname = '';
31 | }
32 | expect(Reflect.getMetadata(symbols.INJECTABLE, Klass)).toBeTruthy();
33 | expect(Reflect.getMetadata(symbols.INJECTTYPE_METADATA, Klass, 'testname')).toEqual([
34 | {
35 | abstract: 'request',
36 | params: ['a', 'b'],
37 | handler: undefined
38 | }
39 | ]);
40 | });
41 | });
42 |
43 | describe('patchMethod', () => {
44 | it('should patch injectable and types in method', () => {
45 | class Klass {
46 | @decoratorFactory('request', ['a', 'b'])
47 | index() {
48 | //
49 | }
50 | }
51 | expect(Reflect.getMetadata(symbols.INJECTABLE, Klass)).toBeTruthy();
52 | expect(Reflect.getMetadata(symbols.INJECTTYPE_METADATA, Klass, 'index')).toEqual([
53 | {
54 | abstract: 'request',
55 | params: ['a', 'b'],
56 | handler: undefined
57 | }
58 | ]);
59 | });
60 | });
61 | });
62 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/decorators/ignore.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { Ignore } from '../../../src/decorators/ignore';
3 |
4 | describe('Ignore Decorator', () => {
5 | it('should patch Ignore by @Ignore', () => {
6 | @Ignore
7 | class Example { }
8 | expect(Reflect.getMetadata('ignore', Example)).toBeTruthy();
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/decorators/inject.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import * as path from 'path';
3 | import { Application, Inject } from '../../../src';
4 | // import { InjectComponent } from '../../daze/src/app/component/InjectComponent';
5 |
6 | const app = new Application(
7 | {
8 | rootPath: path.resolve(__dirname, '../../daze/src')
9 | }
10 | );
11 |
12 | beforeAll(() => app.initialize());
13 |
14 |
15 | describe('@Inject', () => {
16 | it('should inject with class prop', () => {
17 | app.singleton('example1', () => 'hello example1', true);
18 | class Example1 {
19 | @Inject('example1') example1: string;
20 | }
21 | app.singleton(Example1, Example1);
22 | expect(app.get(Example1).example1).toBe('hello example1');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/decorators/injectable.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { Injectable } from '../../../src/decorators/stereotype/injectable';
3 | import * as symbols from '../../../src/symbol';
4 |
5 | describe('Injectable Decorator', () => {
6 | it('should patch Injectable by @Injectable', () => {
7 | @Injectable
8 | class Example { }
9 | expect(Reflect.getMetadata(symbols.INJECTABLE, Example)).toBeTruthy();
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/decorators/multiton.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { Multiton } from '../../../src/decorators/multiton';
3 | import { MULTITON } from '../../../src/symbol';
4 |
5 | describe('Multiton Decorator', () => {
6 | it('should patch Multiton flag in Multiton', () => {
7 | @Multiton
8 | class Example {
9 |
10 | }
11 | expect(Reflect.getMetadata(MULTITON, Example)).toBeTruthy();
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/decorators/rest.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { Rest } from '../../../src';
3 |
4 | describe('Rest Decorator', () => {
5 | it('should patch rest routes and prefix by @Rest', () => {
6 | @Rest('example')
7 | class Example { }
8 | expect(Reflect.getMetadata('routes', Example)).toEqual({
9 | index: [{ uri: '/', method: 'get' }],
10 | create: [{ uri: '/create', method: 'get' }],
11 | show: [{ uri: '/:id', method: 'get' }],
12 | store: [{ uri: '/', method: 'post' }],
13 | edit: [{ uri: '/:id/edit', method: 'get' }],
14 | update: [{ uri: '/:id', method: 'put' }],
15 | destroy: [{ uri: '/:id', method: 'delete' }],
16 | });
17 | expect(Reflect.getMetadata('prefixs', Example)).toEqual(['/example']);
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/decorators/route.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import { Controller } from '../../../src';
3 |
4 | describe('Controller Decorator', () => {
5 | it('should patch type and prefix in Controller', () => {
6 | @Controller('example')
7 | class Example { }
8 | expect(Reflect.getMetadata('prefixs', Example)).toEqual(['/example']);
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/errors/handle-error.spec.ts:
--------------------------------------------------------------------------------
1 | import { ErrorHandler } from '../../../src/errors/handle';
2 | import { HttpError } from '../../../src/errors/http-error';
3 | import { Application } from '../../../src';
4 | import * as path from 'path';
5 |
6 | const app = new Application({
7 | rootPath: path.resolve(__dirname, '../../daze/src')
8 | });
9 |
10 | beforeAll(() => app.initialize());
11 |
12 | describe('handle error', () => {
13 | it('report shoud do nothing with http-error', () => {
14 | const fn = jest.fn();
15 | const handler = new ErrorHandler(new HttpError());
16 | app.on('error', fn);
17 | handler.report();
18 | expect(fn).not.toBeCalled();
19 | });
20 |
21 | it ('report should emit app error with other error', () => {
22 | const fn = jest.fn();
23 | const handler = new ErrorHandler(new Error());
24 | app.on('error', fn);
25 | handler.report();
26 | expect(fn).toBeCalled();
27 | });
28 | });
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/errors/http-error.spec.ts:
--------------------------------------------------------------------------------
1 | import { HttpError } from '../../../src/errors/http-error';
2 |
3 | describe('src/errors/http-error', () => {
4 | it('http-error', () => {
5 | const err = new HttpError(500, 'error');
6 | expect(err).toBeInstanceOf(Error);
7 | expect(err.code).toBe(500);
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/errors/illegal-argument-error.spec.ts:
--------------------------------------------------------------------------------
1 | import { IllegalArgumentError } from '../../../src/errors/illegal-argument-error';
2 |
3 | describe('src/errors/illegal-argument-error', () => {
4 | it('illegal-argument-error', () => {
5 | const err = new IllegalArgumentError('error');
6 | expect(err).toBeInstanceOf(Error);
7 | expect(err.message).toBe('error');
8 | });
9 |
10 | it('should return default message error: Illegal Argument', () => {
11 | const err = new IllegalArgumentError();
12 | expect(err.message).toBe('Illegal Argument');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/errors/not-found-http-error.spec.ts:
--------------------------------------------------------------------------------
1 | import { HttpError } from '../../../src/errors/http-error';
2 | import { NotFoundHttpError } from '../../../src/errors/not-found-http-error';
3 |
4 | describe('src/errors/not-found-http-error', () => {
5 | it('not-found-http-error', () => {
6 | const err = new NotFoundHttpError('error');
7 | expect(err).toBeInstanceOf(HttpError);
8 | expect(err.code).toBe(404);
9 | expect(err.message).toBe('error');
10 | });
11 |
12 | it('should return default message error: Not Found', () => {
13 | const err = new NotFoundHttpError();
14 | expect(err.message).toBe('Not Found');
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/errors/validate-http-error.spec.ts:
--------------------------------------------------------------------------------
1 | import { HttpError } from '../../../src/errors/http-error';
2 | import { ValidateHttpError } from '../../../src/errors/validate-http-error';
3 | import { Validate } from '../../../src/validate';
4 |
5 | describe('src/errors/validate-error', () => {
6 | it('validate-error', () => {
7 | const err = new ValidateHttpError('error', new Validate());
8 | expect(err).toBeInstanceOf(HttpError);
9 | expect(err.code).toBe(422);
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/foundation/middlewares/cross.spec.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import request from 'supertest';
3 | import { Application } from '../../../../src';
4 |
5 | const app = new Application({
6 | rootPath: path.resolve(__dirname, '../../../daze/src')
7 | });
8 |
9 | beforeAll(() => app.run());
10 | afterAll(() => app.close());
11 |
12 | describe('cross origin', () => {
13 | it('should add options route with cross origin', async () => {
14 | await request((app as any)._server)
15 | .options('/cross')
16 | .expect(200);
17 | });
18 |
19 | it('should return 204 code when Preflight Request', async () => {
20 | await request((app as any)._server)
21 | .options('/cross')
22 | .set('Access-Control-Request-Method', 'Get')
23 | .set('Origin', 'http://localhost:8888/')
24 | .expect(204);
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/foundation/middlewares/csrf.spec.ts:
--------------------------------------------------------------------------------
1 |
2 | import path from 'path';
3 | import request from 'supertest';
4 | import { Application } from '../../../../src';
5 |
6 | const app = new Application({
7 | rootPath: path.resolve(__dirname, '../../../daze/src')
8 | });
9 |
10 | beforeAll(() => app.run());
11 | afterAll(() => app.close());
12 |
13 | describe('csrf token', () => {
14 | it('should return 403 code without token', async () => {
15 | await request((app as any)._server)
16 | .post('/csrf')
17 | .expect(403);
18 | });
19 |
20 | it('do not verify with read verb [get, head, options]', async () => {
21 | await request((app as any)._server)
22 | .get('/csrf/get')
23 | .expect(200);
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/loader/index.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import {
3 | Loader,
4 | BaseValidator,
5 | Controller,
6 | Component,
7 | Service, Resourcer, Middleware, Validator
8 | } from '../../../src';
9 |
10 | describe('Loader', () => {
11 | it('should parse module each type', () => {
12 | const loader = new Loader();
13 |
14 | @Controller()
15 | class ExampleController { }
16 |
17 | @Service('example')
18 | class ExampleService{ }
19 |
20 | @Resourcer('example')
21 | class ExampleResource {
22 | resolve(data: any) {
23 | return data;
24 | }
25 | }
26 |
27 | @Validator('example')
28 | class ExampleValidator extends BaseValidator { }
29 |
30 | @Middleware('example')
31 | class ExampleMiddleware {
32 | resolve(_request: any, next: any) {
33 | return next();
34 | }
35 | }
36 |
37 | @Component('example')
38 | class ExampleComponent { }
39 |
40 | loader.load(ExampleController, '');
41 | loader.load(ExampleService, '');
42 | loader.load(ExampleResource, '');
43 | loader.load(ExampleMiddleware, '');
44 | loader.load(ExampleValidator, '');
45 | loader.load(ExampleComponent, '');
46 |
47 | expect(loader.loadedComponents.get('controller')?.map(t => t.target)?.includes(ExampleController)).toBeTruthy();
48 | expect(loader.loadedComponents.get('middleware')?.map(t => t.target)?.includes(ExampleMiddleware)).toBeTruthy();
49 | expect(loader.loadedComponents.get('service')?.map(t => t.target)?.includes(ExampleService)).toBeTruthy();
50 | expect(loader.loadedComponents.get('resource')?.map(t => t.target)?.includes(ExampleResource)).toBeTruthy();
51 | expect(loader.loadedComponents.get('validator')?.map(t => t.target)?.includes(ExampleValidator)).toBeTruthy();
52 | expect(loader.loadedComponents.get('component')?.map(t => t.target)?.includes(ExampleComponent)).toBeTruthy();
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/logger/index.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import path from 'path';
3 | import { Logger, Application } from '../../../src';
4 | import { IllegalArgumentError } from '../../../src/errors/illegal-argument-error';
5 |
6 | const app = new Application({
7 | rootPath: path.resolve(__dirname, '../../daze/src')
8 | });
9 |
10 | beforeAll(() => app.initialize());
11 |
12 | const log = new Logger(app);
13 | describe('src/logger', () => {
14 | it('Logger#isDefaultDriverSupported', () => {
15 | expect(log.isDefaultDriverSupported('console')).toBeTruthy();
16 | expect(log.isDefaultDriverSupported('file')).toBeTruthy();
17 | expect(log.isDefaultDriverSupported('http')).toBeTruthy();
18 | expect(log.isDefaultDriverSupported('stream')).toBeTruthy();
19 | // expect(log.isDefaultDriverSupported('mongodb')).toBeTruthy();
20 | expect(log.isDefaultDriverSupported('dailyFile')).toBeTruthy();
21 | expect(log.isDefaultDriverSupported('custom')).toBeFalsy();
22 | });
23 |
24 | it('Logger#channl', () => {
25 | expect((log.channel('console'))).toBe(log.getContainer().get('console'));
26 | expect(log.channel('dailyFile')).toBe(log.getContainer().get('dailyFile'));
27 | expect(log.channel('file')).toBe(log.getContainer().get('file'));
28 | expect(log.channel('http')).toBe(log.getContainer().get('http'));
29 | expect(log.channel('stream')).toBe(log.getContainer().get('stream'));
30 | expect(log.channel('compose')).toEqual(log.getContainer().get('compose'));
31 | });
32 |
33 | it('Logger#getTransports error', () => {
34 | expect(() => {
35 | log.getTransports('console2');
36 | }).toThrowError(IllegalArgumentError);
37 | expect(() => {
38 | log.getTransports('console3');
39 | }).toThrowError(IllegalArgumentError);
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/pipeline/index.spec.ts:
--------------------------------------------------------------------------------
1 | import { Pipeline } from '../../../src/pipeline';
2 |
3 |
4 | describe('Pipeline', () => {
5 | describe('Pipeline#pipe', () => {
6 | it('should add stage to pipeline stages', () => {
7 | const pipeline = new Pipeline();
8 | const piper = (num: number) => num + 1;
9 | pipeline.pipe(piper);
10 | expect(pipeline.stages[0]).toBe(piper);
11 | });
12 | });
13 |
14 | describe('Pipeline#send', () => {
15 | it('should set payloads array', () => {
16 | const pipeline = new Pipeline();
17 | pipeline.send(1);
18 | expect(pipeline.payload).toEqual([1]);
19 | });
20 | it('should set payloads array when muilt params', () => {
21 | const pipeline = new Pipeline();
22 | pipeline.send(1, 2, 3);
23 | expect(pipeline.payload).toEqual([1, 2, 3]);
24 | });
25 | });
26 |
27 | describe('Pipeline#process', () => {
28 | it('should return stages apply result', async () => {
29 | const pipeline = new Pipeline();
30 | pipeline.pipe((target: any, next: any) => {
31 | target.a = 1;
32 | return next();
33 | });
34 | pipeline.pipe((target: any, next: any) => {
35 | target.b = 1;
36 | return next();
37 | });
38 | pipeline.pipe((target: any, next: any) => {
39 | target.c = 1;
40 | return next();
41 | });
42 | pipeline.send({});
43 | expect(await pipeline.process((target: any) => target)).toEqual({
44 | a: 1,
45 | b: 1,
46 | c: 1,
47 | });
48 | });
49 |
50 | it('should return process apply result whithout stages', async () => {
51 | const pipeline = new Pipeline();
52 | pipeline.send({});
53 | expect(await pipeline.process((target: any) => target)).toEqual({});
54 | });
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/resource/app/test.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '../../../../src';
2 | import { TestResource } from './test.resource';
3 | import { WrapResource } from './wrap.resource';
4 |
5 | @Controller('/resource')
6 | export class TestController {
7 | @Get('/item')
8 | itemAction() {
9 | return TestResource.item({
10 | name: 'dazejs'
11 | });
12 | }
13 |
14 | @Get('/collection')
15 | collectionAction() {
16 | return TestResource.collection([
17 | {
18 | name: 'dazejs'
19 | },
20 | {
21 | name: 'dazejs'
22 | }
23 | ]);
24 | }
25 |
26 |
27 | @Get('/wrap')
28 | wrapAction() {
29 | return new WrapResource().item({
30 | name: 'dazejs',
31 | wrap: {
32 | key: 'daze',
33 | }
34 | });
35 | }
36 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/resource/app/test.resource.ts:
--------------------------------------------------------------------------------
1 | import { Resourcer, BaseResource, ResourceInterface } from '../../../../src';
2 |
3 |
4 | @Resourcer()
5 | export class TestResource extends BaseResource implements ResourceInterface {
6 | resolve(data: any) {
7 | return {
8 | ...data,
9 | type: 'node',
10 | };
11 | }
12 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/resource/app/wrap.resource.ts:
--------------------------------------------------------------------------------
1 | import { Resourcer, BaseResource, ResourceInterface } from '../../../../src';
2 | import { TestResource } from './test.resource';
3 |
4 | @Resourcer()
5 | export class WrapResource extends BaseResource implements ResourceInterface {
6 | resolve(data: any) {
7 | return {
8 | ...data,
9 | wrap: TestResource.item(data.wrap)
10 | };
11 | }
12 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/response/redirect.spec.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import request from 'supertest';
3 | import { Application } from '../../../src';
4 |
5 | const app = new Application({
6 | rootPath: path.resolve(__dirname, '../../daze/src')
7 | });
8 |
9 | beforeAll(() => app.run());
10 | afterAll(() => app.close());
11 |
12 | describe('redirect feature', () => {
13 | it('should return 302 code default', async () => {
14 | await request((app as any)._server)
15 | .get('/redirect')
16 | .expect(302)
17 | .expect('Location', 'https://www.google.com');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/router/routes.spec.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import request from 'supertest';
3 | import { Application } from '../../../src';
4 |
5 | const app = new Application({
6 | rootPath: path.resolve(__dirname, '../../daze/src')
7 | });
8 |
9 | beforeAll(() => app.run());
10 | afterAll(() => app.close());
11 |
12 | describe('routes', () => {
13 | it('should return 200 code and all1', async () => {
14 | await request((app as any)._server)
15 | .get('/routes/all1')
16 | .expect(200, 'all1');
17 | });
18 |
19 | it('should return 200 code and all2', async () => {
20 | await request((app as any)._server)
21 | .get('/routes/all2')
22 | .expect(200, 'all2');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/session/helper.spec.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | import { isBase64 } from '../../../src/validate/validators';
4 | import { Str } from '../../../src/utils/';
5 |
6 | describe('Session#helper', () => {
7 | it('should encode base64 with object by encode', () => {
8 | const code = Str.encodeBASE64({ a: 'aaa' });
9 | expect(isBase64(code)).toBeTruthy();
10 | });
11 |
12 | it('should decode base64 to object by decode', () => {
13 | const body = Str.decodeBASE64('eyJhIjoiYWFhIn0=');
14 | expect(body).toEqual({
15 | a: 'aaa',
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/validate/app/test.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, response, Request, Get } from '../../../../src';
2 | import { TestValidator } from './test.validator';
3 |
4 | @Controller('/validate')
5 | export class TestController {
6 | @Get('/test1')
7 | test1(request: Request) {
8 | request.validate(TestValidator);
9 | return 'hello dazejs';
10 | }
11 |
12 | @Get('/test3')
13 | test3(request: Request) {
14 | if (!TestValidator.check(request.getParams())) {
15 | return response().badRequest();
16 | }
17 | return 'hello dazejs';
18 | }
19 |
20 | @Get('/test4')
21 | test4(request: Request) {
22 | try {
23 | request.validate(TestValidator);
24 | } catch (err) {
25 | return response().badRequest();
26 | }
27 | return 'hello dazejs';
28 | }
29 |
30 | @Get('/test5')
31 | test5(request: Request) {
32 | const validate = new TestValidator().make(request.getParams());
33 | if (validate.fails) {
34 | return response().badRequest();
35 | }
36 | return 'hello dazejs';
37 | }
38 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/validate/app/test.validator.ts:
--------------------------------------------------------------------------------
1 | import { Validator, BaseValidator, IsEmail } from '../../../../src';
2 |
3 | @Validator()
4 | export class TestValidator extends BaseValidator {
5 | @IsEmail()
6 | username: string;
7 | }
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/validate/feature.spec.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import request from 'supertest';
3 | import { Application } from '../../../src';
4 |
5 | const app = new Application({
6 | rootPath: path.resolve(__dirname, './')
7 | });
8 |
9 | beforeAll(() => app.run(7777));
10 | afterAll(() => app.close());
11 |
12 | describe('Validate Feature', () => {
13 | it('should success when request legal', async () => {
14 | await request((app as any)._server)
15 | .get('/validate/test1?username=test@example.com')
16 | .expect(200);
17 | });
18 |
19 | it('should success when request ilegal', async () => {
20 | await request((app as any)._server)
21 | .get('/validate/test1?username=ilegal')
22 | .expect(422);
23 | });
24 |
25 | it('should success when request legal (check)', async () => {
26 | await request((app as any)._server)
27 | .get('/validate/test3?username=test@example.com')
28 | .expect(200);
29 | });
30 |
31 | it('should success when request ilegal (check)', async () => {
32 | await request((app as any)._server)
33 | .get('/validate/test3?username=ilegal')
34 | .expect(400);
35 | });
36 |
37 | it('should success when request legal (custom)', async () => {
38 | await request((app as any)._server)
39 | .get('/validate/test4?username=test@example.com')
40 | .expect(200);
41 | });
42 |
43 | it('should success when request ilegal (custom)', async () => {
44 | await request((app as any)._server)
45 | .get('/validate/test4?username=ilegal')
46 | .expect(400);
47 | });
48 |
49 | it('should success when request legal (make)', async () => {
50 | await request((app as any)._server)
51 | .get('/validate/test5?username=test@example.com')
52 | .expect(200);
53 | });
54 |
55 | it('should success when request ilegal (make)', async () => {
56 | await request((app as any)._server)
57 | .get('/validate/test5?username=ilegal')
58 | .expect(400);
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/packages/framework/__tests__/src/view/index.spec.ts:
--------------------------------------------------------------------------------
1 | import 'reflect-metadata';
2 | import path from 'path';
3 | import { Application, View } from '../../../src';
4 |
5 | const app = new Application({
6 | rootPath: path.resolve(__dirname, '../../daze/src')
7 | });
8 |
9 | beforeAll(() => app.initialize());
10 |
11 | describe('View', () => {
12 | it('View#assign', () => {
13 | const view = new View();
14 | view.assign('color', 'blue');
15 | view.assign({
16 | name: 'color',
17 | });
18 | expect(view.getVars()).toEqual({
19 | color: 'blue',
20 | name: 'color',
21 | });
22 | });
23 |
24 | it('View#render with ext name', () => {
25 | const view = new View();
26 | view.render('index.html', {
27 | color: 'blue',
28 | });
29 | expect(view.getTemplate()).toBe('index.html');
30 | expect(view.getVars()).toEqual({
31 | color: 'blue',
32 | });
33 | });
34 |
35 | it('View#render without ext name', () => {
36 | const view = new View();
37 | view.render('index', {
38 | color: 'blue',
39 | });
40 | expect(view.getTemplate()).toBe('index.html');
41 | expect(view.getVars()).toEqual({
42 | color: 'blue',
43 | });
44 | });
45 |
46 | it('View#render without template ', () => {
47 | const view = new View('index');
48 | view.render({
49 | color: 'blue',
50 | });
51 | expect(view.getTemplate()).toBe('index.html');
52 | expect(view.getVars()).toEqual({
53 | color: 'blue',
54 | });
55 | });
56 |
57 | it('View#render without template and vars', () => {
58 | const view = new View('index', {
59 | color: 'blue',
60 | });
61 | view.render();
62 | expect(view.getTemplate()).toBe('index.html');
63 | expect(view.getVars()).toEqual({
64 | color: 'blue',
65 | });
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/packages/framework/src/base/entity.ts:
--------------------------------------------------------------------------------
1 | import { ComponentType } from '../decorators/component-type';
2 | import { Model } from '../supports/orm/model';
3 | import { Repository } from '../supports/orm/repository';
4 | import { ModelBuilder } from '../supports/orm/builder';
5 | import { Builder } from '../supports/database/builder';
6 |
7 | @ComponentType('entity')
8 | @Reflect.metadata('connection', 'default')
9 | export class BaseEntity {
10 | /**
11 | * 根据主键获取单挑记录
12 | * @param id
13 | */
14 | async get(id: number | string): Promise & this> {
15 | return (new Model(this.constructor as any)).createRepository().get(id) as any;
16 | }
17 |
18 | /**
19 | * 创建模型的查询构建器
20 | */
21 | createQueryBuilder(): ModelBuilder & Builder {
22 | return (new Model(this.constructor as any)).createRepository().createQueryBuilder() as any;
23 | }
24 |
25 | /**
26 | * 关联预加载
27 | * @param relations
28 | */
29 | with(relation: string, callback?: (query: Builder) => void): Repository & this {
30 | return (new Model(this.constructor as any)).createRepository().with(relation, callback) as any;
31 | }
32 |
33 | /**
34 | * 自动保存/新建记录
35 | */
36 | async save() {
37 | const repos = (new Model(this.constructor as any)).createRepository();
38 | repos.fill(this);
39 | await repos.save();
40 | Object.assign(this, repos.getAttributes());
41 | return repos;
42 | }
43 |
44 | /**
45 | * 创建记录
46 | * @param attributes
47 | */
48 | async create(attributes: Record): Promise & this> {
49 | const repos = (new Model(this.constructor as any)).createRepository();
50 | return repos.create(attributes) as any;
51 | }
52 |
53 | /**
54 | * 根据主键 id 删除记录
55 | * @param ids
56 | */
57 | async destroy(...ids: (number | string)[]) {
58 | const repos = (new Model(this.constructor as any)).createRepository();
59 | return repos.destroy(...ids);
60 | }
61 | }
--------------------------------------------------------------------------------
/packages/framework/src/base/index.ts:
--------------------------------------------------------------------------------
1 | export { BaseEntity } from './entity';
2 | export { BasePivotEntity } from './pivot-entity';
3 | export * from './validator';
4 | export * from './resource';
--------------------------------------------------------------------------------
/packages/framework/src/base/pivot-entity.ts:
--------------------------------------------------------------------------------
1 | import { BaseEntity } from './entity';
2 |
3 | export class BasePivotEntity extends BaseEntity {
4 | //
5 | }
6 |
--------------------------------------------------------------------------------
/packages/framework/src/base/resource.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019 zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { Resource } from '../resource';
8 | import { ComponentType } from '../decorators/component-type';
9 |
10 | @ComponentType('resource')
11 | export abstract class BaseResource {
12 |
13 | collection(data: any): Resource {
14 | return new Resource(this.constructor as any).collection(data);
15 | }
16 |
17 | item(data: any): Resource {
18 | return new Resource(this.constructor as any).item(data);
19 | }
20 |
21 | static collection(data: any): Resource {
22 | return new Resource(this as any).collection(data);
23 | }
24 |
25 | static item(data: any): Resource {
26 | return new Resource(this as any).item(data);
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/packages/framework/src/base/validator.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019 zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { ComponentType } from '../decorators/component-type';
8 | import { Validate } from '../validate';
9 |
10 | @ComponentType('validator')
11 | export abstract class BaseValidator {
12 | check(data: Record) {
13 | return new Validate(this.constructor as any).check(data);
14 | }
15 |
16 | make(data: Record) {
17 | return new Validate(this.constructor as any).make(data);
18 | }
19 |
20 | static check(data: Record) {
21 | return new Validate(this).check(data);
22 | }
23 |
24 | static make(data: Record) {
25 | return new Validate(this).make(data);
26 | }
27 |
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/packages/framework/src/cluster/const.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | // The main process receives an interrupt signal to restart the working process
9 | // 主进程接收中断信号来重启工作进程
10 | export const RELOAD_SIGNAL = 'SIGUSR2';
11 |
12 | // Whether the work process has been restarted
13 | // 工作进程是否已进行重启
14 | export const WORKER_DYING = 'daze-worker-dying';
15 |
16 | // After the main process reforks the worker process,
17 | // it notifies the corresponding worker process to terminate the service
18 | // 主进程重新 fork 工作进程后通知对应工作进程让其结束服务的信号
19 | export const WORKER_DID_FORKED = 'daze-worker-did-fork';
20 |
21 | // Signal that the work process is about to stop providing service to the main process
22 | // 工作进程即将停止提供服务通知主进程的信号
23 | export const WORKER_DISCONNECT = 'daze-worker-disconnect';
24 |
25 | // sticky sessions for websocket communication
26 | export const STIKCY_CONNECTION = 'daze-sticky-connection';
27 |
28 | // 框架进程类型
29 | export const DAZE_PROCESS_TYPE = 'daze:process:type';
30 |
--------------------------------------------------------------------------------
/packages/framework/src/cluster/helpers.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import cluster, { Worker } from 'cluster';
8 | import os from 'os';
9 |
10 | import { WORKER_DYING } from './const';
11 | import { MasterOptions } from './master';
12 |
13 | const cpus = os.cpus().length;
14 |
15 | /**
16 | * Analyze the parameters of Cluster module
17 | * Adds the number of work processes to the parameters
18 | * 解析 Cluster 模块的参数
19 | * 添加工作进程数量数量到参数中
20 | */
21 | export function parseMasterOpts(opts: MasterOptions) {
22 | opts.workers = opts.workers || cpus;
23 | return opts;
24 | }
25 |
26 |
27 | /**
28 | * Determine if the work process is alive
29 | * 判断工作进程是否存活状态
30 | */
31 | export function isAliveWorker(worker: Worker) {
32 | if (!worker.isConnected() || worker.isDead()) return false;
33 | if (Reflect.getMetadata(WORKER_DYING, worker)) return false;
34 | return true;
35 | }
36 |
37 | /**
38 | * Capture the surviving work process
39 | * Return an array
40 | * 获取存活的工作进程
41 | * 返回一个数组
42 | */
43 | export function getAlivedWorkers(): Worker[] {
44 | const workers: Worker[] = [];
45 | for (const id in cluster.workers) {
46 | if (Object.prototype.hasOwnProperty.call(cluster.workers, id)) {
47 | const worker: any = cluster.workers[id];
48 | if (isAliveWorker(worker)) {
49 | workers.push(worker);
50 | }
51 | }
52 | }
53 | return workers;
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/packages/framework/src/cluster/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | export * from './master';
9 | export * from './worker';
10 |
--------------------------------------------------------------------------------
/packages/framework/src/config/index.ts:
--------------------------------------------------------------------------------
1 | export * from './config';
2 |
--------------------------------------------------------------------------------
/packages/framework/src/controller/controller-service.ts:
--------------------------------------------------------------------------------
1 | import { Application } from '../foundation/application';
2 | import { UseMiddlewareOption } from '../decorators/use/interface';
3 | import { Router } from '../http/router';
4 |
5 | /**
6 | * 控制器解析类
7 | */
8 | export class ControllerService {
9 | /**
10 | * 应用实例
11 | */
12 | public app: Application;
13 |
14 | /**
15 | * 控制器解析类构造函数
16 | * @param app
17 | */
18 | constructor(app: Application) {
19 | this.app = app;
20 | }
21 |
22 | /**
23 | * 注册一个控制器
24 | */
25 | public register(controller: any) {
26 | if (Reflect.getMetadata('type', controller) !== 'controller') return this;
27 | this.resolve(controller);
28 | return this;
29 | }
30 |
31 | /**
32 | * 解析控制器
33 | */
34 | public resolve(controller: any) {
35 | const routes = Reflect.getMetadata('routes', controller) || {};
36 | const prefixs = Reflect.getMetadata('prefixs', controller) || [''];
37 | for (const prefix of prefixs) {
38 | this.registerRoutes(controller, routes, prefix);
39 | }
40 | }
41 |
42 | /**
43 | * 注册控制器路由
44 | */
45 | private registerRoutes(controller: any, routes: any, prefix = '') {
46 | const router = this.app.get('router');
47 | const controllerMiddlewareOptions: UseMiddlewareOption[] = Reflect.getMetadata('use-middlewares', controller) ?? [];
48 | for (const key of Object.keys(routes)) {
49 | const routeMiddlewares: { [key: string]: UseMiddlewareOption[] } = Reflect.getMetadata('use-middlewares', controller, key) ?? {};
50 | for (const route of routes[key]) {
51 | const { uri, method, option } = route;
52 | const actionMiddlewareOptions = routeMiddlewares[key] ?? [];
53 | router.register(`${prefix}${uri}`, [method], option, controller, key, [...controllerMiddlewareOptions, ...actionMiddlewareOptions]);
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/packages/framework/src/controller/index.ts:
--------------------------------------------------------------------------------
1 | export * from './controller-service';
--------------------------------------------------------------------------------
/packages/framework/src/decorators/autowired.ts:
--------------------------------------------------------------------------------
1 |
2 | import { PROPERTYTYPE_METADATA } from '../symbol';
3 |
4 | export const Autowired: PropertyDecorator = function (target, propertyKey) {
5 | const type = Reflect.getMetadata('design:type', target, propertyKey);
6 | Reflect.defineMetadata(PROPERTYTYPE_METADATA, type, target.constructor, propertyKey);
7 | };
8 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/component-type.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | /**
9 | * set type for component
10 | * @param type
11 | */
12 | export const ComponentType = function (type: any): ClassDecorator {
13 | return function (constructor) {
14 | Reflect.defineMetadata('type', type, constructor);
15 | return constructor;
16 | };
17 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/create-decorator.ts:
--------------------------------------------------------------------------------
1 | import { decoratorFactory } from './factory/decorator-factory';
2 |
3 | export const createCustomDecorator =
4 | (abstract: any, params: any[] = [], handler?: (injectedParam: any) => any) =>
5 | decoratorFactory(abstract, params, handler);
--------------------------------------------------------------------------------
/packages/framework/src/decorators/cross-origin.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | export const CrossOrigin = function (options: any = {}) {
9 | return function (...args: any[]) {
10 | // class decorator
11 | if (args.length === 1) {
12 | const [target] = args;
13 | Reflect.defineMetadata('controllerCrossOrigin', {
14 | ...options,
15 | }, target);
16 | }
17 | // method decorator
18 | else {
19 | const [target, name] = args;
20 | const corses = Reflect.getMetadata('routeCrossOrigin', target.constructor) || {};
21 | corses[name] = {
22 | ...options,
23 | };
24 | Reflect.defineMetadata('routeCrossOrigin', corses, target.constructor);
25 | }
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/csrf.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import { UseMiddleware } from './use/use-middleware';
9 | import { VerifyCsrfToken } from '../foundation/buildin-app/middlewares/verify-csrf-token';
10 |
11 | export const CSRF = function () {
12 | return UseMiddleware(VerifyCsrfToken);
13 | };
14 | export const Csrf = CSRF;
15 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/disbale.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 | import { DISABLE_INJECT } from '../symbol';
8 |
9 | export const Disable = (target: any, propertyKey?: string | symbol) => {
10 | if (!propertyKey) { // Class
11 | Reflect.defineMetadata(DISABLE_INJECT, true, target);
12 | } else {
13 | Reflect.defineMetadata(DISABLE_INJECT, true, target.constructor, propertyKey);
14 | }
15 | };
16 |
17 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/encrypt.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const EncryptResponse: MethodDecorator | ClassDecorator = function (...args: any[]) {
4 | // decorator class
5 | if (args.length === 1) {
6 | const [target] = args;
7 | Reflect.defineMetadata('encrypt', true, target);
8 | }
9 | // decorator method
10 | else {
11 | const [target, name] = args;
12 | Reflect.defineMetadata('encrypt', true, target.constructor, name);
13 | }
14 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/http-code.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { HTTP_CODE } from '../symbol';
8 |
9 | export const HttpCode = function (code = 200): MethodDecorator {
10 | return function (target: Record, propertyKey: string | symbol) {
11 | target[propertyKey.toString()][HTTP_CODE] = code;
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/ignore.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | export const Ignore: ClassDecorator = function (constructor: any) {
9 | Reflect.defineMetadata('ignore', true, constructor);
10 | };
11 |
12 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | // import * as httpContext from './contexts-http';
9 | // import * as verbs from './verb';
10 |
11 | export * from './stereotype';
12 | export * from './disbale';
13 | export * from './component-type';
14 | export * from './cross-origin';
15 | export * from './csrf';
16 | export * from './http-code';
17 | export * from './ignore';
18 | export * from './inject';
19 | export * from './autowired';
20 | export * from './model';
21 | export * from './multiton';
22 | export * from './order';
23 | export * from './provider';
24 | export * from './rest';
25 | export * from './singleton';
26 | export * from './use';
27 | export * from './encrypt';
28 | export * from './validates';
29 | export * from './create-decorator';
30 | // export const http = {
31 | // ...verbs,
32 | // ...httpContext
33 | // };
34 | export * from './verb';
35 | export * from './contexts-http';
36 | export * from './schedule';
37 |
38 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/inject.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import { decoratorFactory } from './factory/decorator-factory';
9 |
10 | /**
11 | * for javascript
12 | * Inject by custom name
13 | * Supports injection in a variety of ways, including but not limited to methods, properties, and constructors
14 | *
15 | * @param name
16 | * @param args
17 | */
18 | export const Inject = function (name?: any, ...args: any[]) {
19 | return decoratorFactory(name, args);
20 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/model/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | export * from './column';
9 | export * from './relation';
--------------------------------------------------------------------------------
/packages/framework/src/decorators/multiton.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import { MULTITON, SINGLETON } from '../symbol';
9 |
10 | export const Multiton: ClassDecorator = function (target: any) {
11 | Reflect.defineMetadata(SINGLETON, false, target);
12 | Reflect.defineMetadata(MULTITON, true, target);
13 | };
14 |
15 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/order.ts:
--------------------------------------------------------------------------------
1 | import { ProviderType } from '../symbol';
2 |
3 | /**
4 | * Organize the order in which components are executed by priority, such as the order in which Middleware is executed
5 | *
6 | * @param value Priority, the smaller the higher the priority
7 | */
8 | export const Order = function (value: number = Number.MAX_SAFE_INTEGER): ClassDecorator {
9 | return function (target: any) {
10 | Reflect.defineMetadata(ProviderType.ORDER, value, target);
11 | };
12 | };
13 |
14 | export const Priority = Order;
--------------------------------------------------------------------------------
/packages/framework/src/decorators/provider/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | export * from './provider';
9 | export * from './provide';
10 | export * from './provide-on-config';
11 | export * from './provide-on-missing';
12 | export * from './provide-on';
13 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/provider/provide-on-config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/ban-types */
2 | /**
3 | * Copyright (c) 2020 Chan Zewail
4 | *
5 | * This software is released under the MIT License.
6 | * https: //opensource.org/licenses/MIT
7 | */
8 |
9 | import { ProviderType } from '../../symbol';
10 | import { ProvideMetaData } from './provide';
11 |
12 | /**
13 | * Provides the service when the specified configuration item exists
14 | *
15 | * @param key
16 | */
17 | export const ProvideOnConfig = function (key: string): ClassDecorator | MethodDecorator | any {
18 | return function (
19 | target: Function | object,
20 | name?: string | symbol | undefined,
21 | descriptor?: TypedPropertyDescriptor | undefined,
22 | ) {
23 | // Decorator on method
24 | if (!!name && !!descriptor) {
25 | const metaMap: Map =
26 | Reflect.getMetadata(ProviderType.PROVIDE, target.constructor) ?? new Map();
27 | if (metaMap.has(name)) {
28 | const options = (metaMap.get(name) ?? {}) as ProvideMetaData;
29 | options.onConfigKey = key;
30 | metaMap.set(name, options);
31 | } else {
32 | metaMap.set(name, { onConfigKey: key });
33 | }
34 | Reflect.defineMetadata(ProviderType.PROVIDE, metaMap, target.constructor);
35 | }
36 | // Decorator on class
37 | else {
38 | const metaMap: Map =
39 | Reflect.getMetadata(ProviderType.PROVIDE, target) ?? new Map();
40 | if (metaMap.has(target)) {
41 | const options = (metaMap.get(target) ?? {}) as ProvideMetaData;
42 | options.onConfigKey = key;
43 | metaMap.set(target, options);
44 | } else {
45 | metaMap.set(target, { onConfigKey: key });
46 | }
47 | Reflect.defineMetadata(ProviderType.PROVIDE, metaMap, target);
48 | }
49 | };
50 | };
51 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/provider/provide-on-missing.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/ban-types */
2 | /**
3 | * Copyright (c) 2020 Chan Zewail
4 | *
5 | * This software is released under the MIT License.
6 | * https: //opensource.org/licenses/MIT
7 | */
8 |
9 | import { ProviderType } from '../../symbol';
10 | import { ProvideMetaData } from './provide';
11 |
12 | /**
13 | * Provide a service when no specified service exists
14 | *
15 | * @param provider
16 | */
17 | export const ProvideOnMissing = function (provider: string | Function): MethodDecorator {
18 | return function (target: object, name: string | symbol) {
19 | const metaMap: Map =
20 | Reflect.getMetadata(ProviderType.PROVIDE, target.constructor) ?? new Map();
21 | if (metaMap.has(name)) {
22 | const options = (metaMap.get(name) ?? {}) as ProvideMetaData;
23 | options.onMissingProviderkey = provider;
24 | metaMap.set(name, options);
25 | } else {
26 | metaMap.set(name, { onMissingProviderkey: provider });
27 | }
28 | Reflect.defineMetadata(ProviderType.PROVIDE, metaMap, target.constructor);
29 | };
30 | };
31 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/provider/provide-on.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/ban-types */
2 | /**
3 | * Copyright (c) 2020 Chan Zewail
4 | *
5 | * This software is released under the MIT License.
6 | * https: //opensource.org/licenses/MIT
7 | */
8 |
9 | import { ProviderType } from '../../symbol';
10 | import { ProvideMetaData } from './provide';
11 |
12 | /**
13 | * Provides a service when a specified service exists
14 | *
15 | * @param provider
16 | */
17 | export const ProvideOn = function (provider: string | Function): MethodDecorator {
18 | return function (target: object, key: string | symbol) {
19 | const metaMap: Map =
20 | Reflect.getMetadata(ProviderType.PROVIDE, target.constructor) ?? new Map();
21 |
22 | if (metaMap.has(key)) {
23 | const options = (metaMap.get(key) ?? {}) as ProvideMetaData;
24 | options.onProviderKey = provider;
25 | metaMap.set(key, options);
26 | } else {
27 | metaMap.set(key, { onProviderKey: provider });
28 | }
29 | Reflect.defineMetadata(ProviderType.PROVIDE, metaMap, target.constructor);
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/provider/provide.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import { ProviderType } from '../../symbol';
9 |
10 | export interface ProvideMetaData {
11 | provideName?: any;
12 | isShared?: boolean;
13 | onMissingProviderkey?: any;
14 | onConfigKey?: string;
15 | onProviderKey?: any;
16 | }
17 |
18 | /**
19 | * To provide services
20 | *
21 | * @param name
22 | * @param isShared
23 | */
24 | export const Provide = function (name?: any, isShared = true): MethodDecorator {
25 | return function (target: object, key: string | symbol) {
26 | const metaMap: Map =
27 | Reflect.getMetadata(ProviderType.PROVIDE, target.constructor) ?? new Map();
28 | const _name = name ?? key.toString();
29 | if (metaMap.has(key)) {
30 | const options = (metaMap.get(key) ?? {}) as ProvideMetaData;
31 | options.provideName = _name;
32 | options.isShared = isShared;
33 | metaMap.set(key, options);
34 | } else {
35 | metaMap.set(key, { provideName: _name, isShared });
36 | }
37 | Reflect.defineMetadata(ProviderType.PROVIDE, metaMap, target.constructor);
38 | };
39 | };
40 |
41 |
42 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/rest.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { Str } from '../utils';
8 | import { INJECTABLE } from '../symbol';
9 |
10 | const defaultRestRoutes = {
11 | index: [{ uri: '/', method: 'get' }],
12 | create: [{ uri: '/create', method: 'get' }],
13 | show: [{ uri: '/:id', method: 'get' }],
14 | store: [{ uri: '/', method: 'post' }],
15 | edit: [{ uri: '/:id/edit', method: 'get' }],
16 | update: [{ uri: '/:id', method: 'put' }],
17 | destroy: [{ uri: '/:id', method: 'delete' }],
18 | };
19 |
20 | export const Rest = function (...prefixs: string[]): ClassDecorator {
21 | return function (constructor) {
22 | Reflect.defineMetadata(INJECTABLE, true, constructor);
23 | Reflect.defineMetadata('prefixs', prefixs?.map(prefix => Str.formatPrefix(prefix)) ?? ['/'], constructor);
24 | const routes = Reflect.getMetadata('routes', constructor);
25 | Reflect.defineMetadata('routes', {
26 | ...defaultRestRoutes,
27 | ...routes,
28 | }, constructor);
29 | };
30 | };
31 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/schedule/index.ts:
--------------------------------------------------------------------------------
1 |
2 | import * as _ from './corntab';
3 |
4 | export const Corntab = {
5 | ..._
6 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/singleton.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { MULTITON, SINGLETON } from '../symbol';
8 |
9 |
10 | export const Singleton: ClassDecorator = function (target: any) {
11 | Reflect.defineMetadata(MULTITON, false, target);
12 | Reflect.defineMetadata(SINGLETON, true, target);
13 | };
14 |
15 |
16 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/agent.ts:
--------------------------------------------------------------------------------
1 | import { Component } from './component';
2 |
3 | export const agent = function (name?: string): ClassDecorator {
4 | return function (constructor) {
5 | Component(name, 'agent')(constructor);
6 | };
7 | };
8 |
9 | export const Agent = agent;
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/component.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import { Injectable } from './injectable';
9 |
10 | /**
11 | * component metadata
12 | * @param name
13 | * @param type
14 | */
15 | export const Component = function (name?: string, type = 'component'): ClassDecorator {
16 | return function (constructor) {
17 | Injectable(constructor);
18 | Reflect.defineMetadata('name', name, constructor);
19 | Reflect.defineMetadata('type', type, constructor);
20 | };
21 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/controller.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import { Str } from '../../utils';
9 | import { Component } from './component';
10 |
11 | export const Controller = function (...prefixs: string[]): ClassDecorator {
12 | return function (constructor) {
13 | Component('', 'controller')(constructor);
14 | Reflect.defineMetadata('prefixs', prefixs.length > 0 ? prefixs.map(prefix => Str.formatPrefix(prefix)) : [Str.formatPrefix()], constructor);
15 | };
16 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/entity.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { Component } from './component';
8 |
9 | export const Entity = function (name: string): ClassDecorator {
10 | return function (constructor) {
11 | Component(undefined, 'entity')(constructor);
12 | Reflect.defineMetadata('table', name, constructor);
13 | };
14 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/index.ts:
--------------------------------------------------------------------------------
1 |
2 | export * from './component';
3 | export * from './controller';
4 | export * from './service';
5 | export * from './entity';
6 | export * from './injectable';
7 | export * from './middleware';
8 | export * from './resourcer';
9 | export * from './validator';
10 | export * from './job';
11 | export * from './agent';
12 | export * from './schedule';
13 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/injectable.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | import { INJECTABLE } from '../../symbol';
9 |
10 | export const Injectable: ClassDecorator = function (constructor: any) {
11 | Reflect.defineMetadata(INJECTABLE, true, constructor);
12 | };
13 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/job.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { Component } from './component';
8 |
9 | export const Job = function (name?: string): ClassDecorator {
10 | return function (constructor) {
11 | Component(name, 'job')(constructor);
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/middleware.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { Component } from './component';
8 |
9 | export const Middleware = function (name?: string): ClassDecorator {
10 | return function (constructor) {
11 | Component(name, 'middleware')(constructor);
12 | };
13 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/resourcer.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { Component } from './component';
8 |
9 | export const Resourcer = function (name?: string): ClassDecorator {
10 | return function (constructor) {
11 | Component(name, 'resource')(constructor);
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/schedule.ts:
--------------------------------------------------------------------------------
1 | import { Component } from './component';
2 |
3 |
4 | export const schedule = function (name?: string): ClassDecorator {
5 | return function (constructor) {
6 | Component(name, 'schedule')(constructor);
7 | };
8 | };
9 |
10 | export const Schedule = schedule;
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/service.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 | import { Component } from './component';
8 |
9 | export const Service = function (name?: string): ClassDecorator {
10 | return function (constructor) {
11 | Component(name, 'service')(constructor);
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/stereotype/validator.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { Component } from './component';
8 |
9 | export const Validator = function (name = ''): ClassDecorator {
10 | return function (constructor) {
11 | Component(name, 'validator')(constructor);
12 | };
13 | };
--------------------------------------------------------------------------------
/packages/framework/src/decorators/use/index.ts:
--------------------------------------------------------------------------------
1 | export * from './use-middleware';
--------------------------------------------------------------------------------
/packages/framework/src/decorators/use/interface.ts:
--------------------------------------------------------------------------------
1 | export interface UseMiddlewareOption {
2 | middleware: any;
3 | args: any[];
4 | }
--------------------------------------------------------------------------------
/packages/framework/src/decorators/use/use-middleware.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | import { UseMiddlewareOption } from './interface';
9 |
10 | /**
11 | * use middleware on controller
12 | *
13 | * @param middleware
14 | */
15 | export const UseMiddleware = function (middleware: any, middlewareArgs: any[] = []) {
16 | return function (...args: any[]) {
17 | // decorator class
18 | if (args.length === 1) {
19 | const [target] = args;
20 | // const middlewares = Reflect.getMetadata('controllerMiddlewares', target) || [];
21 | const middlewaresMeta: UseMiddlewareOption[] = Reflect.getMetadata('use-middlewares', target) ?? [];
22 | middlewaresMeta.push({
23 | middleware,
24 | args: middlewareArgs
25 | });
26 | Reflect.defineMetadata('use-middlewares', middlewaresMeta, target);
27 | }
28 | // decorator method
29 | else {
30 | const [target, name] = args;
31 | const middlewaresMeta = Reflect.getMetadata('use-middlewares', target.constructor, name) || {};
32 | if (!middlewaresMeta[name]) {
33 | middlewaresMeta[name] = [];
34 | }
35 | middlewaresMeta[name].push({
36 | middleware,
37 | args: middlewareArgs
38 | });
39 | Reflect.defineMetadata('use-middlewares', middlewaresMeta, target.constructor, name);
40 | }
41 | };
42 | };
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/validates/factory.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | export function validatorFactory(validatorMethod: any, args: any[] = [], options: any = {}): PropertyDecorator {
9 | return (target, name) => {
10 | const rules = Reflect.getMetadata('rules', target.constructor) || [];
11 | rules.push({
12 | field: name,
13 | handler: validatorMethod,
14 | args,
15 | options,
16 | });
17 | Reflect.defineMetadata('rules', rules, target.constructor);
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/packages/framework/src/decorators/verb.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import * as http from 'http';
9 | import { Str } from '../utils';
10 |
11 | function verb(methods: any[], uri = '/'): MethodDecorator {
12 | return function (target, propertyKey) {
13 | const routes = Reflect.getMetadata('routes', target.constructor) || {};
14 | if (!routes[propertyKey]) routes[propertyKey] = [];
15 | for (const method of methods) {
16 | routes[propertyKey].push({
17 | uri: Str.formatPrefix(uri),
18 | method,
19 | });
20 | }
21 | Reflect.defineMetadata('routes', routes, target.constructor);
22 | };
23 | }
24 |
25 | export const Get = function (uri = '') {
26 | return verb(['GET'], uri);
27 | };
28 |
29 | export const Post = function (uri = '') {
30 | return verb(['POST'], uri);
31 | };
32 |
33 | export const Put = function (uri = '') {
34 | return verb(['PUT'], uri);
35 | };
36 |
37 | export const Patch = function (uri = '') {
38 | return verb(['PATCH'], uri);
39 | };
40 |
41 | export const Options = function (uri = '') {
42 | return verb(['OPTIONS'], uri);
43 | };
44 |
45 | export const Head = function (uri = '') {
46 | return verb(['HEAD'], uri);
47 | };
48 |
49 | export const Del = function (uri = '') {
50 | return verb(['DELETE'], uri);
51 | };
52 |
53 | export const All = function (uri = '', methods: any[] = http.METHODS) {
54 | return verb(methods, uri);
55 | };
56 |
--------------------------------------------------------------------------------
/packages/framework/src/errors/http-error.ts:
--------------------------------------------------------------------------------
1 | import { OutgoingHttpHeaders } from "http";
2 |
3 | /**
4 | * Copyright (c) 2018 Chan Zewail
5 | *
6 | * This software is released under the MIT License.
7 | * https://opensource.org/licenses/MIT
8 | */
9 |
10 | export class HttpError extends Error {
11 | code: number;
12 |
13 | headers: OutgoingHttpHeaders;
14 |
15 | errors: any[];
16 |
17 | constructor(code = 500, message = '', headers = {}, errors: any[] = []) {
18 | super(message);
19 | this.code = code;
20 | this.headers = headers;
21 | this.errors = errors;
22 | Error.captureStackTrace(this, this.constructor);
23 | }
24 |
25 | getErrors() {
26 | return this.errors;
27 | }
28 | }
--------------------------------------------------------------------------------
/packages/framework/src/errors/illegal-argument-error.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | export class IllegalArgumentError extends Error {
9 | constructor(message = 'Illegal Argument') {
10 | super(message);
11 | Error.captureStackTrace(this, this.constructor);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/framework/src/errors/not-found-http-error.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { HttpError } from './http-error';
8 |
9 |
10 | export class NotFoundHttpError extends HttpError {
11 | constructor(message = 'Not Found') {
12 | super(404, message);
13 | Error.captureStackTrace(this, this.constructor);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/framework/src/errors/validate-http-error.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { HttpError } from './http-error';
8 | import { Validate } from '../validate';
9 |
10 |
11 | export class ValidateHttpError extends HttpError {
12 | _validate: Validate;
13 | constructor(message = 'Validation error', validate: Validate) {
14 | super(422, message, {}, validate && validate.errors);
15 | this._validate = validate;
16 | Error.captureStackTrace(this, this.constructor);
17 | }
18 |
19 | get validate() {
20 | return this._validate;
21 | }
22 |
23 | getValidate() {
24 | return this._validate;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/packages/framework/src/errors/views/errors/401.njk:
--------------------------------------------------------------------------------
1 | {% extends "errors/layout.njk" %}
2 |
3 | {% block content %}
4 | Sorry, you are not authorized to access this page.
5 | {% endblock %}
--------------------------------------------------------------------------------
/packages/framework/src/errors/views/errors/404.njk:
--------------------------------------------------------------------------------
1 | {% extends "errors/layout.njk" %}
2 |
3 | {% block content %}
4 | Sorry, the page you are looking for could not be found.
5 | {% endblock %}
--------------------------------------------------------------------------------
/packages/framework/src/errors/views/errors/500.njk:
--------------------------------------------------------------------------------
1 | {% extends "errors/layout.njk" %}
2 |
3 | {% block content %}
4 | Sorry, something went wrong on our servers.
5 | {% endblock %}
--------------------------------------------------------------------------------
/packages/framework/src/errors/views/errors/503.njk:
--------------------------------------------------------------------------------
1 | {% extends "errors/layout.njk" %}
2 |
3 | {% block content %}
4 | Sorry, we are doing some maintenance. Please check back soon.
5 | {% endblock %}
--------------------------------------------------------------------------------
/packages/framework/src/errors/views/errors/error.njk:
--------------------------------------------------------------------------------
1 | {% extends "errors/layout.njk" %}
2 |
3 | {% block content %}
4 | Oops! Something went wrong.
5 | {% endblock %}
6 |
--------------------------------------------------------------------------------
/packages/framework/src/errors/views/errors/layout.njk:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Daze.js
8 |
33 | {% block head %}
34 | {% endblock %}
35 |
36 |
37 | {% block header %}
38 | {% endblock %}
39 |
40 |
41 | {% block content %}
42 | {% endblock %}
43 |
44 |
45 | {% block footer %}
46 | {% endblock %}
47 |
48 |
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/common.provider.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import path from 'path';
8 | import { Depends, Provider, AppendAgent, AppendMaster } from '../../decorators';
9 | import { app } from '../../helpers';
10 | import { Loader } from '../../loader';
11 | import * as providers from './depends';
12 |
13 | @Depends([
14 | providers.RouterProvider,
15 | providers.StereotypeProvider,
16 | providers.MessengerProvider,
17 | providers.LoggerProvider,
18 | providers.DatabaseProvider,
19 | providers.RedisProvider,
20 | providers.ProxyProvider,
21 | providers.CacheProvider,
22 | providers.MailerProvider,
23 | providers.ScheduleProvider,
24 | ])
25 | @AppendAgent()
26 | @AppendMaster()
27 | @Provider()
28 | export class CommonProvider {
29 | async register() {
30 | const loader = app().get('loader');
31 | await loader.scan(
32 | path.resolve(__dirname, '../buildin-app')
33 | );
34 | await loader.autoScanApp();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/cache.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Provider, AppendAgent } from '../../../decorators';
2 | import { Cache } from '../../../supports/cache';
3 | import { app } from '../../../helpers';
4 |
5 |
6 | @Provider()
7 | @AppendAgent()
8 | export class CacheProvider{
9 | @Provide(Cache)
10 | _cache() {
11 | return new Cache();
12 | }
13 |
14 | @Provide('cache')
15 | _cacheAlias() {
16 | return app().get(Cache);
17 | }
18 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/database.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Disable } from '../../../decorators';
2 | import { Database } from '../../../supports/database/database';
3 | import { Application } from '../../application';
4 |
5 | export class DatabaseProvider{
6 | @Provide(Database)
7 | @Disable
8 | _database(app: Application) {
9 | return new Database(app);
10 | }
11 |
12 | @Provide('db')
13 | @Disable
14 | _databaseAlias(app: Application) {
15 | return app.get(Database);
16 | }
17 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/index.ts:
--------------------------------------------------------------------------------
1 | export * from './database.provider';
2 | export * from './logger.provider';
3 | export * from './template-engine.provider';
4 | export * from './stereotype.provider';
5 | export * from './router.provider';
6 | export * from './messenger.provider';
7 | export * from './redis.provider';
8 | export * from './server.provider';
9 | export * from './proxy.provider';
10 | export * from './cache.provider';
11 | export * from './schedule.provider';
12 | export * from './mailer.provider';
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/logger.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Provider, AppendAgent, AppendMaster } from '../../../decorators';
2 | import { ProviderInterface } from '../../../interfaces';
3 | import { Application } from '../../application';
4 | import { Logger } from '../../../supports/logger';
5 | import { app } from '../../../helpers';
6 |
7 | @Provider()
8 | @AppendAgent()
9 | @AppendMaster()
10 | export class LoggerProvider implements ProviderInterface {
11 | @Provide(Logger)
12 | logger(app: Application) {
13 | return new Logger(app);
14 | }
15 |
16 | @Provide('logger')
17 | loggerAlias(app: Application) {
18 | return app.get(Logger);
19 | }
20 |
21 | launch() {
22 | const logger = app().get(Logger);
23 | if (app().isAgent) {
24 | Logger.Cluster.bindListener(logger);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/mailer.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Provider, AppendAgent } from '../../../decorators';
2 | import { Mailer } from '../../../supports/mailer';
3 | import { Application } from '../../../foundation/application';
4 |
5 |
6 | @Provider()
7 | @AppendAgent()
8 | export class MailerProvider{
9 | @Provide(Mailer)
10 | mailer() {
11 | return new Mailer();
12 | }
13 |
14 | @Provide('mail')
15 | mailerAlias(app: Application) {
16 | return app.get(Mailer);
17 | }
18 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/messenger.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Provider, AppendAgent, AppendMaster } from '../../../decorators';
2 | import { ProviderInterface } from '../../../interfaces';
3 | import { Messenger } from '../../../messenger';
4 | import { app } from '../../../helpers';
5 |
6 |
7 | @Provider()
8 | @AppendAgent()
9 | @AppendMaster()
10 | export class MessengerProvider implements ProviderInterface {
11 | @Provide(Messenger)
12 | messenger() {
13 | return new Messenger();
14 | }
15 |
16 | @Provide('messenger')
17 | loggerAlias() {
18 | return app().get(Messenger);
19 | }
20 |
21 | launch() {
22 | app().make(Messenger);
23 | }
24 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/proxy.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provider } from '../../../decorators';
2 | import { app, config } from '../../../helpers';
3 | import { ProxyMiddleware } from '../../buildin-app/middlewares/proxy';
4 | import { Str } from '../../../utils';
5 | import path from 'path';
6 |
7 | @Provider()
8 | export class ProxyProvider{
9 |
10 | private fixContext(context: string) {
11 | return path.join(Str.formatPrefix(config().get('app.baseUrl', '')), context)
12 | .replace(/^\*$/, "**")
13 | .replace(/\/\*$/, "");
14 | }
15 |
16 | launch() {
17 | let proxyConfig = config().get('proxy', {});
18 | // For backwards compatibility reasons.
19 | proxyConfig = Object.keys(proxyConfig).map(context => {
20 | const correctedContext = this.fixContext(context);
21 | if (typeof (proxyConfig[context]) === "string") {
22 | return {
23 | context: correctedContext,
24 | target: proxyConfig[context],
25 | originContext: context
26 | };
27 | } else {
28 | return {
29 | ...proxyConfig[context],
30 | context: correctedContext,
31 | originContext: context,
32 | only: Array.isArray(proxyConfig[context]?.only) ?
33 | proxyConfig[context]?.only.map((uri: string) => this.fixContext(uri)) :
34 | undefined,
35 | except: Array.isArray(proxyConfig[context]?.except) ?
36 | proxyConfig[context]?.except.map((uri: string) => this.fixContext(uri)) :
37 | undefined,
38 | };
39 | }
40 | });
41 | for (const context of Object.keys(proxyConfig)) {
42 | const conf = proxyConfig[context];
43 | app().use(ProxyMiddleware, [conf]);
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/redis.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Provider, AppendAgent } from '../../../decorators';
2 | import { Redis } from '../../../supports/redis';
3 | import { app } from '../../../helpers';
4 |
5 |
6 | @Provider()
7 | @AppendAgent()
8 | export class RedisProvider{
9 | @Provide(Redis)
10 | _database() {
11 | return new Redis();
12 | }
13 |
14 | @Provide('redis')
15 | _databaseAlias() {
16 | return app().get(Redis);
17 | }
18 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/router.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Provider, AppendAgent } from '../../../decorators';
2 | import { ProviderInterface } from '../../../interfaces';
3 | import { Router } from '../../../http/router';
4 | import { app } from '../../../helpers';
5 |
6 | @Provider()
7 | @AppendAgent()
8 | export class RouterProvider implements ProviderInterface {
9 | @Provide(Router)
10 | router() {
11 | return new Router();
12 | }
13 |
14 | @Provide('router')
15 | _routerAlias() {
16 | return app().get(Router);
17 | }
18 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/schedule.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Provider, AppendAgent } from '../../../decorators';
2 | import { ProviderInterface } from '../../../interfaces';
3 | import { Application } from '../../../foundation/application';
4 | import { Container } from '../../../container';
5 | import { ScheduleService } from '../../../supports/schedule';
6 |
7 | @Provider()
8 | @AppendAgent()
9 | export class ScheduleProvider implements ProviderInterface {
10 | app: Application = Container.get('app');
11 |
12 | @Provide(ScheduleService)
13 | schedule() {
14 | return new ScheduleService(this.app);
15 | }
16 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/server.provider.ts:
--------------------------------------------------------------------------------
1 | import { Provide, Provider } from '../../../decorators';
2 | import { AppServer } from '../../../http/server';
3 | import { ProviderInterface } from '../../../interfaces';
4 | import { app } from '../../../helpers';
5 |
6 | @Provider()
7 | export class AppServerProvider implements ProviderInterface {
8 | @Provide('appServer')
9 | httpServer() {
10 | return new AppServer();
11 | }
12 |
13 | launch() {
14 | app().get('appServer').createServer();
15 | }
16 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/depends/template-engine.provider.ts:
--------------------------------------------------------------------------------
1 | import { Application } from '../../application';
2 | import * as nunjucks from 'nunjucks';
3 | import * as path from 'path';
4 | import { Provide, Provider } from '../../../decorators';
5 | import { ProviderInterface } from '../../../interfaces';
6 | import { Str } from '../../../utils';
7 |
8 | import { app } from '../../../helpers';
9 |
10 | @Provider()
11 | export class TemplateEngineProvider implements ProviderInterface {
12 | @Provide('template')
13 | _tmp(app: Application) {
14 | const templateEnv = new nunjucks.Environment([new nunjucks.FileSystemLoader(app.viewPath, {
15 | // noCache: app.isDebug,
16 | // watch: app.isDebug,
17 | noCache: false,
18 | watch: false
19 | }), new nunjucks.FileSystemLoader(path.resolve(__dirname, '../../../errors/views'), {
20 | // noCache: app.isDebug,
21 | // watch: app.isDebug,
22 | noCache: false,
23 | watch: false
24 | })], {
25 | autoescape: false,
26 | });
27 | const config = app.get('config');
28 | templateEnv.addGlobal('app', app);
29 | templateEnv.addGlobal('config', config);
30 | templateEnv.addGlobal('__public__', Str.formatPrefix(config.get('app.baseUrl', '')) + Str.formatPrefix(config.get('app.publicPrefix', '')));
31 | return templateEnv;
32 | }
33 |
34 | launch() {
35 | app().make('template');
36 | }
37 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './common.provider';
2 | export * from './worker.provider';
3 |
4 |
5 |
--------------------------------------------------------------------------------
/packages/framework/src/foundation/auto-providers/worker.provider.ts:
--------------------------------------------------------------------------------
1 | // import Tokens from 'csrf';
2 | import Tokens from 'csrf';
3 | import { Depends, Provide, Disable, Provider } from '../../decorators';
4 | import { Request } from '../../http/request';
5 | // import { Response } from '../../http/response';
6 | import * as symbols from '../../symbol';
7 | import { request } from '../../helpers';
8 | import * as providers from './depends';
9 | import { AsyncLocalStorage } from 'async_hooks';
10 |
11 | @Depends([
12 | providers.TemplateEngineProvider,
13 | providers.AppServerProvider,
14 | ])
15 | @Provider()
16 | export class WorkerProvider {
17 | @Provide(symbols.ASYNC_LOCAL_STORAGE)
18 | @Disable
19 | asyncLocalStorage() {
20 | return new AsyncLocalStorage();
21 | }
22 |
23 | @Provide('csrf')
24 | _csrf() {
25 | return new Tokens();
26 | }
27 |
28 | @Provide(Request, false)
29 | @Disable
30 | _requestInstance() {
31 | return request();
32 | }
33 |
34 | @Provide(symbols.INJECTORS.QUERY, false)
35 | @Disable
36 | _query() {
37 | return request().query;
38 | }
39 |
40 | @Provide(symbols.INJECTORS.BODY, false)
41 | @Disable
42 | _body() {
43 | return request().body;
44 | }
45 | }
--------------------------------------------------------------------------------
/packages/framework/src/foundation/buildin-app/agents/schedule.ts:
--------------------------------------------------------------------------------
1 | import { Agent } from '../../../decorators';
2 | import { Application } from '../../application';
3 | import { Container } from '../../../container';
4 | import { ScheduleService } from '../../../supports/schedule';
5 |
6 | /**
7 | * 在 Agent 进程处理定时任务
8 | */
9 | @Agent()
10 | export class ScheduleAgent {
11 | app: Application = Container.get('app');
12 |
13 | resolve() {
14 | this.app.get(ScheduleService).start();
15 | }
16 | }
--------------------------------------------------------------------------------
/packages/framework/src/http/middleware/index.ts:
--------------------------------------------------------------------------------
1 | export * from './middleware-service';
--------------------------------------------------------------------------------
/packages/framework/src/http/proxy/index.ts:
--------------------------------------------------------------------------------
1 | export * from './proxy';
--------------------------------------------------------------------------------
/packages/framework/src/http/request/utils/parse-body.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import buddy from 'co-body';
8 | import formidable from 'formidable';
9 | import { Request } from '../index';
10 |
11 | function parseForm(req: any) {
12 | return new Promise(((resolve, reject) => {
13 | const fields: any = {};
14 | const files: any = {};
15 | const form = new formidable.IncomingForm();
16 | form.on('end', () => resolve({
17 | fields,
18 | files,
19 | })).on('error', (err: any) => reject(err)).on('field', (field: string, value: any) => {
20 | if (fields[field]) {
21 | if (Array.isArray(fields[field])) {
22 | fields[field].push(value);
23 | } else {
24 | fields[field] = [fields[field], value];
25 | }
26 | } else {
27 | fields[field] = value;
28 | }
29 | }).on('file', (field: string, file: any) => {
30 | if (files[field]) {
31 | if (Array.isArray(files[field])) {
32 | files[field].push(file);
33 | } else {
34 | files[field] = [files[field], file];
35 | }
36 | } else {
37 | files[field] = file;
38 | }
39 | });
40 | form.parse(req);
41 | }));
42 | }
43 |
44 | export async function parseBody(request: Request) {
45 | let body: any = {};
46 | if (request.is('json')) {
47 | body.fields = await buddy.json(request.req);
48 | } else if (request.is('urlencoded')) {
49 | body.fields = await buddy.form(request.req);
50 | } else if (request.is('text')) {
51 | body.fields = await buddy.text(request.req);
52 | } else if (request.is('multipart')) {
53 | body = await parseForm(request.req);
54 | } else {
55 | body.fields = await buddy.text(request.req);
56 | }
57 | return body;
58 | }
59 |
--------------------------------------------------------------------------------
/packages/framework/src/http/response/manager.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019 zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { Response } from '.';
8 |
9 | export class ResponseManager {
10 | response: any;
11 | constructor(data: any = null, code = 200, headers = {}) {
12 | if (data instanceof Response) {
13 | this.response = data;
14 | } else {
15 | this.response = new Response(data, code, headers);
16 | }
17 | }
18 |
19 | output(request: any) {
20 | if (!this.response) return undefined;
21 | this.response.send(request);
22 | return this.response;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/framework/src/http/router/helpers.ts:
--------------------------------------------------------------------------------
1 | import { Node } from './node';
2 |
3 |
4 | /**
5 | * match trie node with type
6 | */
7 | export function isMatchNodeWithType(node: Node, key: string) {
8 | if (node.key && node.type === 'all') {
9 | return true;
10 | }
11 | if (node.key && node.type === 'static') {
12 | return node.key === key;
13 | }
14 | if (node.key && node.type === 'reg') {
15 | return (new RegExp(node.key).test(key));
16 | }
17 | return false;
18 | };
19 |
20 | /**
21 | * parse pattern to array
22 | */
23 | export function parsePattern(pattern: string) {
24 | return pattern.split('/').filter(p => p !== '');
25 | };
26 |
--------------------------------------------------------------------------------
/packages/framework/src/http/router/trie.ts:
--------------------------------------------------------------------------------
1 | import { Request } from '../request';
2 | import { parsePattern } from './helpers';
3 | import { Node } from './node';
4 | import { Route } from './route';
5 |
6 | export class Trie {
7 | /**
8 | * route trie cache map
9 | */
10 | routes: Map = new Map();
11 |
12 | /**
13 | * add a route
14 | * @param route
15 | */
16 | add(route: Route) {
17 | for (const method of route.methods) {
18 | if (!this.routes.has(method)) {
19 | this.routes.set(method, new Node());
20 | }
21 | this.register(this.routes.get(method), route);
22 | }
23 | }
24 |
25 | /**
26 | * register route node
27 | * @param rootNode
28 | * @param route
29 | */
30 | register(rootNode: Node, route: Route) {
31 | rootNode.insert(route, route.pieces, 0);
32 | }
33 |
34 | /**
35 | * match route by request
36 | * @param request
37 | */
38 | match(request: Request) {
39 | const _method = request.getMethod() || '';
40 | const _path = request.getPath();
41 | const rootNode = this.routes.get(_method);
42 | if (!rootNode) return null;
43 | const keys = parsePattern(_path);
44 | const result = rootNode.search(keys, 0);
45 | if (result) return result.route || null;
46 | return null;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/packages/framework/src/http/server/index.ts:
--------------------------------------------------------------------------------
1 | export * from './server';
--------------------------------------------------------------------------------
/packages/framework/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import 'reflect-metadata';
9 |
10 | export * from './base';
11 | export * from './container';
12 | export * from './http/cookie';
13 | export * from './config';
14 | export * from './supports/database';
15 | export * from './decorators';
16 | export * from './foundation/application';
17 | export * from './loader';
18 | export * from './supports/logger';
19 | export * from './messenger';
20 | export * from './http/middleware';
21 | export * from './http/request';
22 | export * from './resource';
23 | export * from './http/response';
24 | export * from './http/response/redirect';
25 | export * from './view';
26 | export * from './interfaces';
27 | export * from './utils';
28 | export * from './pagination';
29 | export * from './helpers';
30 |
31 |
--------------------------------------------------------------------------------
/packages/framework/src/interfaces/agent.interface.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export interface AgentInterface {
4 | resolve(): Promise | any;
5 | }
--------------------------------------------------------------------------------
/packages/framework/src/interfaces/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | export * from './middleware.interface';
9 | export * from './resource.interface';
10 | export * from './provider.interface';
11 | export * from './agent.interface';
--------------------------------------------------------------------------------
/packages/framework/src/interfaces/middleware.interface.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | import { Request } from '../http/request';
9 | import { Next } from '../http/middleware';
10 |
11 | export interface MiddlewareInterface {
12 | resolve(request: Request, next: Next): any;
13 | }
--------------------------------------------------------------------------------
/packages/framework/src/interfaces/provider.interface.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export interface ProviderInterface {
4 | register?(): void | Promise;
5 | launch?(): void | Promise;
6 | [key: string]: any;
7 | }
--------------------------------------------------------------------------------
/packages/framework/src/interfaces/resource.interface.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2020 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https: //opensource.org/licenses/MIT
6 | */
7 |
8 | export interface ResourceInterface {
9 | resolve(...args: any[]): any;
10 | }
--------------------------------------------------------------------------------
/packages/framework/src/loader/index.ts:
--------------------------------------------------------------------------------
1 | export * from './loader';
--------------------------------------------------------------------------------
/packages/framework/src/messenger/index.ts:
--------------------------------------------------------------------------------
1 | export * from './messenger';
--------------------------------------------------------------------------------
/packages/framework/src/pagination/index.ts:
--------------------------------------------------------------------------------
1 | export * from './paginator';
--------------------------------------------------------------------------------
/packages/framework/src/pipeline/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | type TStage = (...args: any[]) => any
9 |
10 | type TProcesser = (...args: any[]) => any
11 |
12 | export class Pipeline {
13 |
14 | stages: TStage[]
15 |
16 | payload: any;
17 |
18 | /**
19 | * Create Pipeline Instance
20 | */
21 | constructor(...stages: TStage[]) {
22 | /**
23 | * @type stages pipe stages
24 | */
25 | this.stages = stages;
26 | }
27 |
28 | /**
29 | * add pipe stage
30 | */
31 | pipe(...stages: TStage[]) {
32 | for (const stage of stages) {
33 | // assert(is.isFunction(stage), new IllegalArgumentError('pipe stage must be function'));
34 | this.stages.push(stage);
35 | }
36 | return this;
37 | }
38 |
39 | /**
40 | * send payloads
41 | */
42 | send(...payload: any[]) {
43 | this.payload = payload;
44 | return this;
45 | }
46 |
47 | /**
48 | * run pipeline
49 | */
50 | async process(processor: TProcesser) {
51 | if (this.stages.length > 0) {
52 | const callback = this.stages
53 | .reduceRight(
54 | (next, pipe) => async (...data: any[]) => pipe(...data, next.bind(null, ...data)),
55 | async (...params: any[]) => processor(...params),
56 | );
57 | return callback(...this.payload);
58 | }
59 | return processor(...this.payload);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/packages/framework/src/provider/index.ts:
--------------------------------------------------------------------------------
1 | export * from './provider';
--------------------------------------------------------------------------------
/packages/framework/src/resource/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019 zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | export * from './resource';
--------------------------------------------------------------------------------
/packages/framework/src/supports/cache/config.interface.ts:
--------------------------------------------------------------------------------
1 | export interface CacheConfigInterface {
2 | store: 'memory' | 'redis' | 'fs';
3 | connection: string;
4 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/cache/index.ts:
--------------------------------------------------------------------------------
1 | export * from './cache';
2 | export * from './config.interface';
--------------------------------------------------------------------------------
/packages/framework/src/supports/cache/store/index.ts:
--------------------------------------------------------------------------------
1 | export * from './store';
2 | export * from './memory';
3 | export * from './redis';
4 | export * from './fs';
--------------------------------------------------------------------------------
/packages/framework/src/supports/cache/store/store.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | export interface StorageItemInterface {
4 | value: any;
5 | expiresAt: number;
6 | }
7 |
8 | /**
9 | * 缓存的抽象方法
10 | */
11 | export abstract class CacheStore {
12 | /**
13 | * 获取单个缓存
14 | * @param key
15 | */
16 | abstract get(key: string): Promise;
17 |
18 | /**
19 | * 获取多个缓存
20 | * @param keys
21 | */
22 | // abstract many(...keys: string[]): Promise;
23 | /**
24 | * 设置一个缓存
25 | * @param key
26 | * @param value
27 | * @param seconds
28 | */
29 | abstract set(key: string, value: any, seconds?: number): Promise;
30 | abstract add(key: string, value: any, seconds: number): Promise;
31 |
32 | /**
33 | * 设置多个缓存
34 | * @param data
35 | */
36 | // abstract setMany(data: Record): Promise;
37 | /**
38 | * 使缓存的值增加
39 | * @param key
40 | * @param value
41 | */
42 | abstract increment(key: string, value: number): Promise;
43 |
44 | /**
45 | * 使缓存的值减少
46 | * @param key
47 | * @param value
48 | */
49 | abstract decrement(key: string, value: number): Promise;
50 |
51 | /**
52 | * 设置一个不会过期的缓存
53 | * @param key
54 | * @param value
55 | */
56 | abstract forever(key: string, value: any): Promise;
57 |
58 | /**
59 | * 删除一个缓存
60 | * @param key
61 | */
62 | abstract remove(key: string): Promise;
63 |
64 | /**
65 | * 删除所有缓存
66 | */
67 | abstract flush(): Promise;
68 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/actuator/actuator.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 执行器抽象类
3 | */
4 | export abstract class Actuator {
5 | abstract query(sql: string, bindings?: any): Promise
6 | abstract select(query: string, bindings?: any[]): Promise
7 | abstract insert(query: string, bindings?: any[]): Promise
8 | abstract update(query: string, bindings?: any[]): Promise
9 | abstract delete(query: string, bindings?: any[]): Promise
10 | abstract commit(): Promise
11 | abstract rollback(): Promise
12 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/actuator/index.ts:
--------------------------------------------------------------------------------
1 | export * from './actuator';
2 | export * from './mysql-tansaction-actuator';
3 | export * from './mysql-actuator';
4 |
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/builder/index.ts:
--------------------------------------------------------------------------------
1 | export * from './builder';
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/builder/join.ts:
--------------------------------------------------------------------------------
1 | import { Builder, TJoinType, TSymlink } from './builder';
2 |
3 | export class NJoin {
4 | /**
5 | * sql builder instance
6 | */
7 | builder: Builder;
8 |
9 | /**
10 | * join type
11 | * 'inner' | 'left' | 'right' | 'cross'
12 | */
13 | type: TJoinType;
14 |
15 | /**
16 | * Create Join Builder
17 | * @param builder
18 | * @param type
19 | */
20 | constructor(builder: Builder, type: TJoinType) {
21 | this.builder = builder;
22 | this.type = type;
23 |
24 | return new Proxy(this, this.proxy);
25 | }
26 |
27 | /**
28 | * get Join proxy
29 | */
30 | get proxy(): ProxyHandler {
31 | return {
32 | get(target, p, receiver) {
33 | if (typeof p !== 'string') return Reflect.get(target, p, receiver);
34 | if (Reflect.has(target, p)) {
35 | return Reflect.get(target, p, receiver);
36 | }
37 | return target.builder[p as keyof Builder];
38 | }
39 | };
40 | }
41 | /**
42 | * set join table
43 | * @param table
44 | * @param as
45 | */
46 | table(table: string, as?: string) {
47 | this.builder.table(table, as);
48 | return this;
49 | }
50 |
51 | /**
52 | * set on sql
53 | * @param column
54 | * @param operator
55 | * @param seed
56 | * @param symlink
57 | */
58 | on(column: string, operator: string, seed?: string, symlink: TSymlink = 'and') {
59 | this.builder.whereColumn(column, operator, seed, symlink);
60 | return this;
61 | }
62 |
63 | /**
64 | * set or on sql
65 | * @param column
66 | * @param operator
67 | * @param seed
68 | */
69 | orOn(column: string, operator: string, seed?: string) {
70 | return this.on(column, operator, seed, 'or');
71 | }
72 | }
73 |
74 | export type Join = NJoin & Builder;
75 | export const Join: new (builder: Builder, type: TJoinType) => Join = NJoin as any;
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/connector/connector.ts:
--------------------------------------------------------------------------------
1 | export abstract class Connector {
2 | abstract connect(options: any): any;
3 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/connector/mysql-connector.ts:
--------------------------------------------------------------------------------
1 | import { PoolOptions, createPool } from 'mysql2';
2 | import { Connector } from './connector';
3 |
4 | export class MysqlConnector extends Connector {
5 | /**
6 | * connect to mysql use pool
7 | * @param options
8 | */
9 | connect(options: PoolOptions) {
10 | const pool = createPool(options);
11 | return pool;
12 | }
13 |
14 | // /**
15 | // * connect to mysql
16 | // */
17 | // connect(options: string | ConnectionConfig) {
18 | // const connection = createConnection(options);
19 | // connection.connect();
20 | // connection.on('error', (err: MysqlError) => {
21 | // this.handleConnectionLost(err, options);
22 | // });
23 | // return connection;
24 | // }
25 |
26 | // /**
27 | // * handle error when connection lost
28 | // * @param err
29 | // * @param options
30 | // */
31 | // handleConnectionLost(err: MysqlError, options: string | ConnectionConfig) {
32 | // if (err) {
33 | // if (err.fatal) {
34 | // this.connect(options);
35 | // } else {
36 | // throw err;
37 | // }
38 | // }
39 | // }
40 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/index.ts:
--------------------------------------------------------------------------------
1 | export * from './database';
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/manager/index.ts:
--------------------------------------------------------------------------------
1 | export * from './manager';
2 | export * from './mysql-manager';
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/manager/manager.ts:
--------------------------------------------------------------------------------
1 | import { Actuator } from '../actuator/actuator';
2 | import { Builder } from '../builder';
3 | import { Parser } from '../parser/parser';
4 |
5 | export abstract class Manager {
6 | /**
7 | * sql parser
8 | */
9 | parser: Parser;
10 |
11 | /**
12 | * sql actuator
13 | */
14 | actuator: Actuator;
15 |
16 | /**
17 | * close connection close
18 | */
19 | abstract close(): void
20 |
21 | /**
22 | * set table
23 | * @param table
24 | * @param as
25 | */
26 | abstract table(table: string, as?: string): Builder
27 | abstract beginTransaction(): Promise
28 | abstract transaction(callback: (conn: Builder) => Promise | void): Promise
29 | abstract query(sql: string, bindings?: any): Promise
30 | abstract select(query: string, bindings?: any[]): Promise
31 | abstract insert(query: string, bindings?: any[]): Promise
32 | abstract update(query: string, bindings?: any[]): Promise
33 | abstract delete(query: string, bindings?: any[]): Promise
34 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/parser/index.ts:
--------------------------------------------------------------------------------
1 | export * from './parser';
2 | export * from './mysql-parser';
--------------------------------------------------------------------------------
/packages/framework/src/supports/database/parser/mysql-parser.ts:
--------------------------------------------------------------------------------
1 | import { Builder } from '../builder';
2 | import { Parser } from './parser';
3 |
4 | export class MysqlParser extends Parser {
5 | parseLock(builder: Builder) {
6 | if (typeof builder._lock === 'string') return builder._lock;
7 | if (typeof builder._lock === 'boolean') return builder._lock ? 'for update' : 'lock in share mode';
8 | return '';
9 | }
10 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/logger/consts.ts:
--------------------------------------------------------------------------------
1 | export const LOGGER_PROCESS_MESSAGE = 'tiger:process_logger_message';
--------------------------------------------------------------------------------
/packages/framework/src/supports/logger/index.ts:
--------------------------------------------------------------------------------
1 | export * from './logger';
--------------------------------------------------------------------------------
/packages/framework/src/supports/mailer/connector.ts:
--------------------------------------------------------------------------------
1 | import nodemailer from 'nodemailer';
2 |
3 | /**
4 | * 邮件服务连接器
5 | */
6 | export class MailConnector {
7 | /**
8 | * 连接邮件服务器
9 | * @param options
10 | * @returns
11 | */
12 | connect(options: any) {
13 | return nodemailer.createTransport(options);
14 | }
15 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/mailer/index.ts:
--------------------------------------------------------------------------------
1 | export * from './mailer';
--------------------------------------------------------------------------------
/packages/framework/src/supports/mailer/mailer.ts:
--------------------------------------------------------------------------------
1 |
2 | import { config } from '../../helpers';
3 | import { MailManager } from './manager';
4 | import { MailConnector } from './connector';
5 | /**
6 | * 邮件服务
7 | */
8 | export class Mailer {
9 | /**
10 | * mail 管理器
11 | */
12 | managers: Map = new Map();
13 |
14 | /**
15 | * 获取已经连接的 mail 服务
16 | * @param name
17 | * @returns
18 | */
19 | transporter(name = 'default') {
20 | if (!this.managers.has(name)) {
21 | const mailConfig = this.getTransporterConfigure(name);
22 | this.managers.set(name, this.createTransporterManager(mailConfig));
23 | }
24 | return this.managers.get(name) as MailManager;
25 | }
26 |
27 | createTransporterManager(options: any) {
28 | const transporter = (new MailConnector()).connect(options);
29 | return new MailManager(transporter);
30 | }
31 |
32 | /**
33 | * 根据名称获取对应邮箱配置
34 | * @param name
35 | * @returns
36 | */
37 | private getTransporterConfigure(name: string) {
38 | return config().get(`mail.${name}`);
39 | }
40 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/mailer/manager.ts:
--------------------------------------------------------------------------------
1 | import nodemailer from 'nodemailer';
2 | import { MailBuilder } from './builder';
3 |
4 | /**
5 | * 邮件管理器
6 | */
7 | export class MailManager {
8 | private transporter: nodemailer.Transporter;
9 |
10 | constructor(transporter: nodemailer.Transporter) {
11 | this.transporter = transporter;
12 | }
13 |
14 | create() {
15 | return new MailBuilder(this);
16 | }
17 |
18 | send(message: nodemailer.SendMailOptions) {
19 | return this.transporter.sendMail(message);
20 | }
21 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/orm/index.ts:
--------------------------------------------------------------------------------
1 | export * from './base-model';
2 | export * from './pivot-model';
3 | export * from './repository';
4 | export * from './model';
--------------------------------------------------------------------------------
/packages/framework/src/supports/orm/pivot-model.ts:
--------------------------------------------------------------------------------
1 | import { BaseEntity } from './base-model';
2 |
3 | export class PivotEntity extends BaseEntity {
4 | //
5 | }
6 |
--------------------------------------------------------------------------------
/packages/framework/src/supports/orm/relations/has-relations.abstract.ts:
--------------------------------------------------------------------------------
1 | import { Builder } from '../../database/builder';
2 | import { Application } from '../../../foundation/application';
3 | import { Container } from '../../../container';
4 | import { ModelBuilder } from '../builder';
5 | import { Model } from '../model';
6 | import { Repository } from '../repository';
7 |
8 | export abstract class HasRelations {
9 | /**
10 | * application
11 | */
12 | protected app: Application = Container.get('app');
13 |
14 | /**
15 | * 父模型
16 | */
17 | protected parent: Model;
18 |
19 | /**
20 | * 当前关联模型
21 | */
22 | protected model: Model;
23 |
24 | /**
25 | * 外键
26 | */
27 | protected foreignKey: string;
28 |
29 | /**
30 | * 关联主键
31 | */
32 | protected localKey: string;
33 |
34 | /**
35 | * 渴求式加载单个模型关联数据
36 | * @param result
37 | * @param relation
38 | */
39 | abstract eagerly(result: Repository, relation: string, queryCallback?: (query: ModelBuilder & Builder) => void): Promise
40 | /**
41 | * 渴求式加载多个模型关联数据
42 | * @param results
43 | * @param relation
44 | */
45 | abstract eagerlyMap(results: Repository[], relation: string, queryCallback?: (query: ModelBuilder & Builder) => void): Promise
46 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/orm/relations/index.ts:
--------------------------------------------------------------------------------
1 | export * from './has-one';
2 | export * from './belongs-to';
3 | export * from './has-many';
4 | export * from './belongs-to-many';
5 | export * from './has-relations.abstract';
--------------------------------------------------------------------------------
/packages/framework/src/supports/redis/config.interface.ts:
--------------------------------------------------------------------------------
1 | import { RedisOptions, ClusterNode, ClusterOptions } from 'ioredis';
2 |
3 | type clusterConfig = {
4 | cluster: boolean,
5 | nodes: ClusterNode[],
6 | } & ClusterOptions
7 |
8 | export interface RedisConfigInterface {
9 | default: RedisOptions | clusterConfig,
10 | schedule: RedisOptions | clusterConfig,
11 | cache: RedisOptions | clusterConfig,
12 | [key: string]: RedisOptions | clusterConfig,
13 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/redis/connector.ts:
--------------------------------------------------------------------------------
1 |
2 | import IORedis from 'ioredis';
3 |
4 |
5 | export class Connector {
6 | connect(options: any) {
7 | if (options.cluster === true) {
8 | const nodes = options.nodes || [];
9 | if (!nodes || !nodes.length) return;
10 | return new IORedis.Cluster(nodes, options);
11 | } else if (options.sentinels) {
12 | if (!options.sentinels || !options.sentinels.length) return;
13 | return new IORedis(options);
14 | } else {
15 | return new IORedis(options);
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/redis/index.ts:
--------------------------------------------------------------------------------
1 | export * from './redis';
2 | export * from './config.interface';
--------------------------------------------------------------------------------
/packages/framework/src/supports/redis/redis.ts:
--------------------------------------------------------------------------------
1 | import { config } from '../../helpers';
2 | import { Connector } from './connector';
3 | import { Redis as IORedis, Cluster } from 'ioredis';
4 | import { fakeBaseClass } from '../../utils/fake-base-class';
5 |
6 | export type RedisClient = IORedis | Cluster
7 |
8 | export class Redis extends fakeBaseClass() {
9 | /**
10 | * 连接实例
11 | */
12 | private instances: Map = new Map();
13 |
14 | constructor() {
15 | super();
16 | return new Proxy(this, this.proxy);
17 | }
18 |
19 | /**
20 | * 代理器
21 | */
22 | get proxy(): ProxyHandler {
23 | return {
24 | get(target: Redis, p: string | number | symbol, receiver: any) {
25 | if (typeof p === 'string') {
26 | if (Reflect.has(target, p)) {
27 | return Reflect.get(target, p, receiver);
28 | }
29 | return target.connection()[p as keyof RedisClient];
30 | }
31 | return Reflect.get(target, p, receiver);
32 | }
33 | };
34 | }
35 |
36 | /**
37 | * 获取 redis 连接
38 | * @param name
39 | * @returns
40 | */
41 | public connection(name = 'default') {
42 | if (!this.instances.has(name)) {
43 | const config = this.getConnectioncConfigure(name);
44 | const instance = this.createConnection(config);
45 | instance && this.instances.set(name, instance);
46 | }
47 | return this.instances.get(name) as RedisClient;
48 | }
49 |
50 | /**
51 | * 获取连接配置
52 | * @param name
53 | * @returns
54 | */
55 | private getConnectioncConfigure(name: string) {
56 | const options = config().get(`redis.${name}`);
57 | if (!options) throw new Error(`未找到 Redis 配置 [redis.${name}]`);
58 | return options;
59 | }
60 |
61 | /**
62 | * 创建连接
63 | * @param options
64 | * @returns
65 | */
66 | private createConnection(options: any) {
67 | const redis = (new Connector()).connect(options);
68 | return redis;
69 | }
70 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/schedule/index.ts:
--------------------------------------------------------------------------------
1 | export * from './schedule-service';
2 | export * from './scheduler';
--------------------------------------------------------------------------------
/packages/framework/src/supports/schedule/matcher.ts:
--------------------------------------------------------------------------------
1 | import mz from 'moment-timezone';
2 |
3 | /**
4 | * CORN 匹配器
5 | */
6 | export class Matcher {
7 | /**
8 | * 匹配数组
9 | * @param pattern
10 | * @param value
11 | * @returns
12 | */
13 | private matchPattern(pattern: string, value: number) {
14 | if (~pattern.indexOf(',')){
15 | const patterns = pattern.split(',');
16 | return !!~patterns.indexOf(value.toString());
17 | }
18 | return pattern === value.toString();
19 | }
20 |
21 | /**
22 | * 根据表达式和时间进行匹配
23 | * @param pattern
24 | * @param date
25 | * @param timezone
26 | * @returns
27 | */
28 | public match(pattern: string, date: Date, timezone?: string) {
29 | const _date = timezone ? mz.tz(date, timezone).toDate() : date;
30 | const expressions = pattern.split(' ');
31 | const runOnSecond = this.matchPattern(expressions[0], _date.getSeconds());
32 | const runOnMinute = this.matchPattern(expressions[1], _date.getMinutes());
33 | const runOnHour = this.matchPattern(expressions[2], _date.getHours());
34 | const runOnDay = this.matchPattern(expressions[3], _date.getDate());
35 | const runOnMonth = this.matchPattern(expressions[4], _date.getMonth() + 1);
36 | const runOnWeekDay = this.matchPattern(expressions[5], _date.getDay());
37 | return runOnSecond && runOnMinute && runOnHour && runOnDay && runOnMonth && runOnWeekDay;
38 | }
39 | }
--------------------------------------------------------------------------------
/packages/framework/src/supports/template-engine/index.ts:
--------------------------------------------------------------------------------
1 | export * from './template';
--------------------------------------------------------------------------------
/packages/framework/src/supports/template-engine/template.ts:
--------------------------------------------------------------------------------
1 | import * as nunjucks from 'nunjucks';
2 | import * as path from 'path';
3 | import { Application } from '../../foundation/application';
4 |
5 | export class Template {
6 | static create(app: Application) {
7 | const templateEnv = new nunjucks.Environment([new nunjucks.FileSystemLoader(app.viewPath, {
8 | noCache: app.isDebug,
9 | watch: app.isDebug,
10 | }), new nunjucks.FileSystemLoader(path.resolve(__dirname, '../errors/views'), {
11 | noCache: app.isDebug,
12 | watch: app.isDebug,
13 | })], {
14 | autoescape: false,
15 | });
16 | const config = app.get('config');
17 | templateEnv.addGlobal('app', app);
18 | templateEnv.addGlobal('config', config);
19 | templateEnv.addGlobal('__public__', config.get('app.publicPrefix', ''));
20 | return templateEnv;
21 | }
22 | }
--------------------------------------------------------------------------------
/packages/framework/src/utils/defered.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | export class Deferred {
9 | /**
10 | * promise
11 | */
12 | private _promise: Promise;
13 |
14 |
15 | /**
16 | * resolve func
17 | */
18 | private _resolve: (value: T | PromiseLike) => void;
19 |
20 | /**
21 | * reject func
22 | */
23 | private _reject: (reason?: any) => void;
24 |
25 | /**
26 | * Create Deferred
27 | */
28 | constructor() {
29 | this._promise = new Promise((resolve, reject) => {
30 | this._resolve = resolve;
31 | this._reject = reject;
32 | });
33 | }
34 |
35 | /**
36 | * promise getter
37 | */
38 | get promise(): Promise {
39 | return this._promise;
40 | }
41 |
42 | /**
43 | * resolve promise
44 | * @param value
45 | */
46 | resolve (value: T | PromiseLike): void {
47 | this._resolve(value);
48 | }
49 |
50 | /**
51 | * reject promise
52 | * @param reason
53 | */
54 | reject (reason?: any): void {
55 | this._reject(reason);
56 | }
57 | }
--------------------------------------------------------------------------------
/packages/framework/src/utils/encrypt.ts:
--------------------------------------------------------------------------------
1 |
2 | import { createHash, BinaryLike } from 'crypto';
3 |
4 | export const encrypt = (algorithm: string, content: BinaryLike) => {
5 | const hash = createHash(algorithm);
6 | hash.update(content);
7 | return hash.digest('hex');
8 | };
--------------------------------------------------------------------------------
/packages/framework/src/utils/fake-base-class.ts:
--------------------------------------------------------------------------------
1 | export function fakeBaseClass(): new() => Pick {
2 | return class {} as any;
3 | }
--------------------------------------------------------------------------------
/packages/framework/src/utils/index.ts:
--------------------------------------------------------------------------------
1 |
2 | export { Str } from './str';
3 | export { Tool } from './tool';
4 |
--------------------------------------------------------------------------------
/packages/framework/src/utils/tool.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2018 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | import * as A from 'fp-ts/lib/Array';
9 | import * as O from 'fp-ts/lib/Option';
10 | import { pipe } from 'fp-ts/lib/pipeable';
11 |
12 | export class Tool {
13 |
14 | /**
15 | * defer function based on promise
16 | * 基于 promise 的延迟函数
17 | */
18 | static defer() {
19 | const result: any = {};
20 | result.promise = new Promise((resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => {
21 | result.resolve = resolve;
22 | result.reject = reject;
23 | });
24 | return result;
25 | }
26 |
27 | static A = A;
28 | static O = O;
29 | static pipe = pipe;
30 | }
31 |
--------------------------------------------------------------------------------
/packages/framework/src/validate/index.ts:
--------------------------------------------------------------------------------
1 | export * from './validate';
2 |
--------------------------------------------------------------------------------
/packages/framework/src/view/factory.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2019 Chan Zewail
3 | *
4 | * This software is released under the MIT License.
5 | * https://opensource.org/licenses/MIT
6 | */
7 | import { View } from '.';
8 | import { Container } from '../container';
9 | import { Application } from '../foundation/application';
10 | import { Request } from '../http/request';
11 |
12 | export class ViewFactory {
13 | /**
14 | * application
15 | */
16 | app: Application = Container.get('app');
17 |
18 | /**
19 | * view
20 | */
21 | view: View;
22 |
23 | constructor(view: View) {
24 | this.view = view;
25 | }
26 |
27 | combineVars(request: Request) {
28 | const defaultVars = {
29 | sessionValue(key: string) {
30 | return request.session().get(key);
31 | },
32 | get __token__() {
33 | return request._csrf;
34 | },
35 | };
36 | return Object.assign({}, defaultVars, this.view.getVars());
37 | }
38 |
39 | output(request: Request) {
40 | const template = this.app.get('template');
41 | const vars = this.combineVars(request);
42 | return template.render(this.view.getTemplate(), vars);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/packages/framework/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "dist",
6 | "module": "commonjs"
7 | },
8 | "include": [
9 | "src/**/*.ts",
10 | "vendors.d.ts"
11 | ],
12 | "exclude": [
13 | "node_modules",
14 | "**/FUTURE_*",
15 | "**/DEPRECATED_*"
16 | ]
17 | }
--------------------------------------------------------------------------------
/packages/framework/vendors.d.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 | declare module 'keygrip' {
4 | const x: any;
5 | export = x;
6 | }
7 |
8 | declare module 'require-main-filename' {
9 | const x: any;
10 | export = x;
11 | }
12 |
13 | declare module 'core-util-is' {
14 | const x: any;
15 | export = x;
16 | }
17 |
18 |
19 | declare module 'cache-content-type' {
20 | const x: any;
21 | export = x;
22 | }
23 |
24 | declare module '@dazejs/trace-page' {
25 | const x: any;
26 | export = x;
27 | }
28 |
29 |
30 | declare module 'winston-mongodb' {
31 | const MongoDB: MongoDBTransportInstance;
32 | }
33 |
34 | // declare module 'winston-daily-rotate-file' {
35 | // var x: any;
36 | // export = x;
37 | // }
38 |
39 | // declare module 'winston' {
40 | // var x: any;
41 | // export = x;
42 | // }
43 |
44 |
--------------------------------------------------------------------------------
/packages/trace-page/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | __tests__
4 | __debug__
5 | .idea
6 | .vscode
7 | logs
8 |
--------------------------------------------------------------------------------
/packages/trace-page/README.md:
--------------------------------------------------------------------------------
1 | # `@dazejs/trace-page`
2 |
3 | > TODO: description
4 |
5 | ## Usage
6 |
7 | ```
8 | const tracePage = require('@dazejs/trace-page');
9 |
10 | // TODO: DEMONSTRATE API
11 | ```
12 |
--------------------------------------------------------------------------------
/packages/trace-page/__tests__/index.spec.ts:
--------------------------------------------------------------------------------
1 | // import tracePage from '..';
2 |
3 | describe('@dazejs/trace-page', () => {
4 | it('needs tests', () => {
5 | expect(true).toBeTruthy()
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/packages/trace-page/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'html-webpack-inline-source-plugin';
2 | declare module 'code-prettify';
3 | declare module 'zepto';
4 | declare module 'html-webpack-plugin';
5 |
--------------------------------------------------------------------------------
/packages/trace-page/images.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.svg'
2 | declare module '*.png'
3 | declare module '*.jpg'
4 | declare module '*.jpeg'
5 | declare module '*.gif'
6 | declare module '*.bmp'
7 | declare module '*.tiff'
--------------------------------------------------------------------------------
/packages/trace-page/template/index.ts:
--------------------------------------------------------------------------------
1 |
2 | import './less/index.less';
3 | // eslint-disable-next-line
4 | // @ts-ignore
5 | import $ from 'zepto';
6 | // eslint-disable-next-line
7 | // @ts-ignore
8 | import PR from 'code-prettify';
9 |
10 | $(function () {
11 | PR.prettyPrint();
12 | // eslint-disable-next-line
13 | // @ts-ignore
14 | $('.frame').on('click', function () {
15 | // eslint-disable-next-line
16 | // @ts-ignore
17 | const index = $(this).data('index');
18 | $('.frame.active').removeClass('active');
19 | // eslint-disable-next-line
20 | // @ts-ignore
21 | $(this).addClass('active');
22 | $('.frame-code.active').removeClass('active');
23 | $('.frame-code' + '-' + index).addClass('active');
24 | });
25 | // eslint-disable-next-line
26 | // @ts-ignore
27 | $('.frame-code').each(function () {
28 | // eslint-disable-next-line
29 | // @ts-ignore
30 | const ele = $(this);
31 | const li = ele.find('.prettyprint').find('li');
32 | const currentLineNumber = ele.data('current');
33 | const firstLineNumber = li.first().attr('value');
34 | const activeLineNumber = currentLineNumber - firstLineNumber - 1;
35 | li.eq(activeLineNumber).addClass('active', 'current');
36 | li.eq(activeLineNumber - 1).addClass('current');
37 | li.eq(activeLineNumber + 1).addClass('current');
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/packages/trace-page/template/less/code.less:
--------------------------------------------------------------------------------
1 |
2 | /*! Color themes for Google Code Prettify | MIT License | github.com/jmblog/color-themes-for-google-code-prettify */
3 | .prettyprint {
4 | background: #2f3640;
5 | font-family: Menlo, "Bitstream Vera Sans Mono", "DejaVu Sans Mono", Monaco, Consolas, monospace;
6 | border: 0 !important;
7 | }
8 |
9 | .pln {
10 | color: #e6e9ed;
11 | }
12 |
13 |
14 | /* Specify class=linenums on a pre to get line numbering */
15 | ol.linenums {
16 | margin-top: 0;
17 | margin-bottom: 0;
18 | color: #656d78;
19 | margin-left: 10px;
20 | }
21 |
22 | li.L0,
23 | li.L1,
24 | li.L2,
25 | li.L3,
26 | li.L4,
27 | li.L5,
28 | li.L6,
29 | li.L7,
30 | li.L8,
31 | li.L9 {
32 | padding-left: 1em;
33 | background-color: #2f3640;
34 | list-style-type: decimal;
35 | }
36 |
37 | @media screen {
38 |
39 | /* string content */
40 |
41 | .str {
42 | color: #ffce54;
43 | }
44 |
45 | /* keyword */
46 |
47 | .kwd {
48 | color: #4fc1e9;
49 | }
50 |
51 | /* comment */
52 |
53 | .com {
54 | color: #656d78;
55 | }
56 |
57 | /* type name */
58 |
59 | .typ {
60 | color: #4fc1e9;
61 | }
62 |
63 | /* literal value */
64 |
65 | .lit {
66 | color: #ac92ec;
67 | }
68 |
69 | /* punctuation */
70 |
71 | .pun {
72 | color: #e6e9ed;
73 | }
74 |
75 | /* lisp open bracket */
76 |
77 | .opn {
78 | color: #e6e9ed;
79 | }
80 |
81 | /* lisp close bracket */
82 |
83 | .clo {
84 | color: #e6e9ed;
85 | }
86 |
87 | /* markup tag name */
88 |
89 | .tag {
90 | color: #ed5565;
91 | }
92 |
93 | /* markup attribute name */
94 |
95 | .atn {
96 | color: #a0d468;
97 | }
98 |
99 | /* markup attribute value */
100 |
101 | .atv {
102 | color: #ffce54;
103 | }
104 |
105 | /* declaration */
106 |
107 | .dec {
108 | color: #ac92ec;
109 | }
110 |
111 | /* variable name */
112 |
113 | .var {
114 | color: #e6e9ed;
115 | }
116 |
117 | /* function name */
118 |
119 | .fun {
120 | color: #e6e9ed;
121 | }
122 | }
--------------------------------------------------------------------------------
/packages/trace-page/tsconfig-for-webpack-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es5",
5 | "esModuleInterop": true,
6 | "skipLibCheck": true,
7 | "declaration": false,
8 | "noLib": true
9 | }
10 | }
--------------------------------------------------------------------------------
/packages/trace-page/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "target": "es5",
6 | "baseUrl": "./",
7 | "outDir": "dist"
8 | },
9 | "include": [
10 | "./index.ts",
11 | "./global.d.ts",
12 | "./images.d.ts"
13 | ],
14 | "exclude": [
15 | "node_modules"
16 | ]
17 | }
--------------------------------------------------------------------------------
/scripts/build.sh:
--------------------------------------------------------------------------------
1 |
2 | #!/bin/bash
3 | set -e
4 | cp ./README.md ./packages/framework/README.md
5 | cp ./README_en.md ./packages/framework/README_en.md
6 | lerna run build --stream
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2017",
4 | "module": "commonjs",
5 | "lib": [
6 | "esnext"
7 | ],
8 | "allowJs": false,
9 | "declaration": true,
10 | "sourceMap": true,
11 | "removeComments": true,
12 | "strict": true,
13 | "noImplicitAny": true,
14 | "strictNullChecks": true,
15 | "strictFunctionTypes": true,
16 | "strictPropertyInitialization": false,
17 | "noImplicitThis": true,
18 | "alwaysStrict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noImplicitReturns": true,
22 | "moduleResolution": "node",
23 | "allowSyntheticDefaultImports": true,
24 | "esModuleInterop": true,
25 | "experimentalDecorators": true,
26 | "emitDecoratorMetadata": true,
27 | "skipLibCheck": true,
28 | "preserveSymlinks": true
29 | }
30 | }
--------------------------------------------------------------------------------