Git Product home page Git Product logo

amala's Introduction

Amala

amala2

Amala is a decorator-based API framework for KoaJS v2+ and Typescript. Amala is fast, light, self-documenting and Docker-ready; Perfect for microservices.

  • Define your REST API endpoints using ES8 classes and decorators.
  • Inject arguments into your endpoint handlers, effectively turning your controller endpoints into standalone, testable service endpoints.
  • Clean, light and FAST endpoints. Powered by Koa.
  • No further magic past decorators. Full access to underlying Koa app.
  • Project creator comes with fully configured Docker and Docker-compose settings for quick containerization.
  • In-built OpenAPI spec exporter and Swagger UI!

This leads to clean, self-documenting API endpoints and makes it so you can re-use those service endpoints elsewhere. It also makes your endpoint endpoints easier to test.

Supporting Amala

Amala is an MIT-licensed open source project with its ongoing development made possible entirely by community support. If Amala is helping you build awesome APIs, please consider Becoming a Patron.

If you would like to contribute in other ways, Pull requests are also welcome!

Getting started

You may create an Amala project with any of the following:

  • npm init amala-app <project_name>
  • npm create amala-app <project_name>
  • yarn create amala-app <project_name>

For next steps, see official docs at https://amalajs.com.

amala's People

Contributors

anonrig avatar dependabot[bot] avatar georgyfarniev avatar iyobo avatar kindlyiyobo avatar yurasmetanka avatar zrubenst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

amala's Issues

Consult, constructor has no effect

image

How does the constructor take effect when the bootstrapControllers is initialized?

For example, like this ok
export class App{
constructor(private name:string = "111"){
}
test(){
console.log(this.name)
console.log('test function')
}
}
const app = new App()
app.test()

SyntaxError: Cannot use import statement outside a module

Hi!

First of all congrats on this beautiful project. I didn't want to bother with a bug I've been facing, but here's the truth:

path /Users/yagiz/Workspace/alfred/src/**/*/controller.ts
(node:44681) UnhandledPromiseRejectionWarning: /Users/yagiz/Workspace/alfred/src/admin/account/controller.ts:1

I'm receiving this error on the following code:

  await bootstrapControllers(app, {
    router,
    basePath: '/',
    controllers: [__dirname + '/**/*/controller.ts'],
    initBodyParser: true,
    boomifyErrors: true,
    disableVersioning: true
  })

My .babelrc is:

{
  "presets": [["env", { "modules": false }], "@babel/preset-typescript"],
  "plugins": [
    "@babel/plugin-transform-modules-commonjs",
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    "@babel/proposal-class-properties",
    "@babel/proposal-object-rest-spread"
  ]
}

And my tsconfig.json is:

{
  "compileOnSave": false,
  "exclude": [
    "node_modules",
    "docs",
    "migrations",
    "seeders",
    "tests",
    "websites",
    "dist"
  ],
  "include": ["./**/*.ts"],
  "compilerOptions": {
    /* Basic Options */
    "incremental": true /* Enable incremental compilation */,
    "target": "ES5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
    "lib": [
      "ES5",
      "ES2016",
      "ES2017"
    ] /* Specify library files to be included in the compilation. */,
    "allowJs": true /* Allow javascript files to be compiled. */,
    "checkJs": true /* Report errors in .js files. */,
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    "declaration": true /* Generates corresponding '.d.ts' file. */,
    // "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
    "sourceMap": true /* Generates corresponding '.map' file. */,
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    // "outDir": "./dist" /* Redirect output structure to the directory. */,
    "rootDir": "./" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
    // "composite": true /* Enable project compilation */,
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    "removeComments": true /* Do not emit comments to output. */,
    // "noEmit": true /* Do not emit outputs. */,
    "importHelpers": true /* Import emit helpers from 'tslib'. */,
    "downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */,
    // "isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */,

    /* Strict Type-Checking Options */
    // "strict": true /* Enable all strict type-checking options. */,
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true /* Enable strict null checks. */,
    // "strictFunctionTypes": true /* Enable strict checking of function types. */,
    "strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */,
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    "noUnusedLocals": true /* Report errors on unused locals. */,
    // "noUnusedParameters": true /* Report errors on unused parameters. */,
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,

    /* Module Resolution Options */
    "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
    "baseUrl": "." /* Base directory to resolve non-absolute module names. */,
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */,
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    "sourceRoot": "." /* Specify the location where debugger should locate TypeScript files instead of source locations. */,
    "mapRoot": "." /* Specify the location where debugger should locate map files instead of generated locations. */,
    // "inlineSourceMap": true /* Emit a single file with source maps instead of having a separate file. */,
    // "inlineSources": true /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */,

    /* Experimental Options */
    "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */,
    "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */,

    /* Advanced Options */
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  }
}

Create roadmap

Hi @iyobo, I think we need some roadmap to define project scope and features. The last one is necessary to prevent us from working on same issue simultaneously. I don’t have much time but I want to help with PR’s (if you want). Also I think it’s important to keep this project simple as now, but it need better documentation and existing features support.

The problem of other frameworks such as nestjs is their complexity. Not all projects need all this features, but really most rest API needs features provided by this project, such as input validation and injection of parameters.

I think this module has bright future after some polishing and popularization.

Regards, George

Support ability to pass in Controller classes directly

Right now, we rely on providing bootstrapControllers a glut to get all controllers per bootstrap.
We should allow for the ability to provide an array of not only glut strings describing where these class files are, but actual Classes as well.

Support OpenAPI spec file generation (JSON)

This controller library gives endpoints all the self-documentation they need to generate OpenAPI spec files.
Let's make that happen.

Ideally, the openAPI spec should be generated and cached during bootstrapControllers(...), the result of which can then be manually used by users as they deem fit.

e.g to serve from an endpoint or to be outputed into a JSON file.

To keep this module simple and flexible, The specifics of how to output/use the spec file should be left to the users.

License

What is the license for the code from this repository?

Use API versioning on top level instead of controller decorator

Hi. It would be nice to have option of creating version globally, not by picking specific controllers with @Version() decorator. For example:

await bootstrapControllers(app, {
    router,
    basePath: '/api',
    initBodyParser: true,
    boomifyErrors: true,
    versions:{
        1: './version1_controllers/**/*.ts',
        2: './version2_controllers/**/*.ts'
    }
});

Or just use custom controllers structure, not just list, but object with version prefixes similar to versions...

Params type conversion

If I supply @Params('id') id: number, then it should be converted to number. A good example can be found in type-graphql library.

Support for uploaded files

I'd love to be able to inject uploaded files through @koa/multer. Just like routing-controllers does.

Would you accept a PR for this? I'd love to send you one.

class-validator not support ValidateNested

export default class FileParam {
  @ValidateNested()
  metadata: FileMetadataParam;
}

export class FileMetadataParam {
  @IsPositive()
  public size: number;
}


   // controller
  @Post("")
  async upload(@Body() fileParam: FileParam, @Ctx() ctx: Context) {
      // todo
  }

Injected arguments that should be null or undefined end up as empty object

Example:

@Controller('/test')
export class TestController {
	@Get('/whoami')
	@Flow(AuthMiddleware(false))
	async getTest(@CurrentUser() user: any): Promise<any> {
		console.log(user); // logs "{}" If ctx.state.user is null/undefined
		return user ?? "unknown"; // returns "{}" instead of "unknown" if ctx.state.user is null/undefined
	}
}

Race condition on generateEndPoints function

By default we're using lodash each function to iterate over actions of the endpoints and using async function as a callback, to run promises inside this.

When iterating through node inspect mode, I couldn't find any issue but, when running through an actual npm start I've received the following error:

By default lodash each iteraction doesn't wait for callback function async to finish and may cause inconsistencies like the following:

https://github.com/iyobo/koa-ts-controllers/blob/master/src/util/generateRoutes.ts#L94

(node:84929) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 24)
(node:84929) UnhandledPromiseRejectionWarning: TypeError: undefined is not a function
    at /Users/yagiz/Workspace/alfred/node_modules/koa-ts-controllers/dist/util/generateRoutes.js:110:32
    at /Users/yagiz/Workspace/alfred/node_modules/lodash/lodash.js:4905:15
    at baseForOwn (/Users/yagiz/Workspace/alfred/node_modules/lodash/lodash.js:2990:24)
    at /Users/yagiz/Workspace/alfred/node_modules/lodash/lodash.js:4874:18
    at Function.forEach (/Users/yagiz/Workspace/alfred/node_modules/lodash/lodash.js:9342:14)
    at _generateEndPoints (/Users/yagiz/Workspace/alfred/node_modules/koa-ts-controllers/dist/util/generateRoutes.js:80:22)
    at /Users/yagiz/Workspace/alfred/node_modules/koa-ts-controllers/dist/util/generateRoutes.js:143:19
    at /Users/yagiz/Workspace/alfred/node_modules/lodash/lodash.js:4905:15
    at baseForOwn (/Users/yagiz/Workspace/alfred/node_modules/lodash/lodash.js:2990:24)
    at /Users/yagiz/Workspace/alfred/node_modules/lodash/lodash.js:4874:18
    at Function.forEach (/Users/yagiz/Workspace/alfred/node_modules/lodash/lodash.js:9342:14)
    at Object.generateRoutes (/Users/yagiz/Workspace/alfred/node_modules/koa-ts-controllers/dist/util/generateRoutes.js:140:22)
    at Object.exports.bootstrapControllers (/Users/yagiz/Workspac

Donation

Please enable donation to this project, at least via github

multer support for amala

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads/')
  },
  filename: function (req, file, cb) {
    cb(null, `${file.fieldname}-${Date.now()}-${file.originalname}`)
  },
})
const upload = multer({ storage: storage })

@Controller('/')
class UploadController {
  @Flow([upload.single('image')])
  @Post('/upload')
  upload(@File() files: Record<string, File>) {
    console.log(files)
  }
}

this is my code that doesn't give any errors at all. I get the file in logs, but I can't upload it.

Without using amala with only koa, everything works fine. I assume that the problem is a different way of processing the request, since it is impossible to access the fields through amala

originalname
fieldname and etc...

Therefore, multer receives incorrect data, I cannot solve the problem in any way.

is there a way to make friends with amala and multer?

Current project status

Hello. First of all, thanks for creating this package! It's really sad that https://github.com/typestack/routing-controllers/ is almost dead now and I was glad to see your project. I just want to know about your plans for this project and if it's ready to use for serious application.

I want to keep things simple, that's why I want to avoid complicated things such as nest. everything I need is basic routing and decorator-based injections and validations, things that your library provides.

So, what is your plans about it? Will you continue develop it? Will you at least accept PR's?

Thanks 👍

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.