trailsjs / trails

:evergreen_tree: Modern Web Application Framework for Node.js.
http://trailsjs.io
Other
1.66k stars 70 forks source link

Make Trails TS compliant #242

Open jaumard opened 8 years ago

jaumard commented 8 years ago

In TS when we want to use external js library, we need some specific file definition used by TS to compile correctly. Those file are called "typings" definition, Have .d.ts extension. https://typescript.codeplex.com/wikipage?title=Writing%20Definition%20%28.d.ts%29%20Files

We are trying to create them with @scott-wyatt but no luck until now. So if there some TS people here that want to help let us know :)

scott-wyatt commented 8 years ago

This get's interesting because Trails is compartmentalized in different repos, so we have to write a definition file for things like: trails, trails-service, trails-controller etc. Not quite sure which is the best way to go about this right now.

scott-wyatt commented 8 years ago

We need definition files and passing tests for trails, trails-controller, trails-model, and trails-service. I'm not sure if we need them for the core trailpacks.

scott-wyatt commented 8 years ago

Here's what I got so far.

declare namespace TrailsService {
  class TrailsService {
    app: {
      config: any;
      sitemap: any;
      routes: { path: string, config: {app?: any} }[];
      services: any;
    };
    log: any;
    id: any;
    __: any;
    config: any;

    constructor(app: any);
  }
}

declare module "trails-service" {
  export = TrailsService;
}

and usage looks like

import { TrailsController as Controller } from 'trails-controller';

export class DefaultController extends Controller {
  default (req, res) {
    console.log(this.app);
  }
}
scott-wyatt commented 8 years ago

Okay, so I have "definition" files, however, they don't know that they are extending TrailsApp, still don't know how to do that part...

jaumard commented 8 years ago

What do you mean by extending TrailsApp ?

jaumard commented 8 years ago

@scott-wyatt is the file definition you put above or another one ?

scott-wyatt commented 8 years ago

That's the controller definition file above ^^. By extending, basically, a service controller etc all get an instance of this.app that they 'extend' in their constructor, with the current definition file, this causes issues in loading because they don't know they need to wait to get the app that they are extending. It might just be source ordering in trails, but I'm not really sure. However, when it's compiled you get this error:

 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
                                                                   ^
TypeError: Cannot read property 'prototype' of undefined at __extends
scott-wyatt commented 8 years ago

When done inline

import {Request, Response} from 'express';
interface TrailsControllerStatic {
    log:any;
    app:{config:any, services:any, routes: {path:any}, log:any};
}
interface TrailsController {
  new(options: any): TrailsControllerStatic
}
// declare var Controller: TrailsController;
var Controller: TrailsController = require('trails-controller');

export class DefaultController extends Controller {
  /**
   * Return some info about this application
   */
  info(req: Request, res: Response ) {
    res.status(200).json(this.app.services.DefaultService.getApplicationInfo())
  }
}

we now get the error:

 TypeError: Class constructors cannot be invoked without 'new'
jaumard commented 8 years ago

I was able to run a project without problem if we transpile server side into es6 not es5, but by using a module that export all Trails classes. The module does :

module.exports = {
  Controller: require('trails-controller'),
  Policy: require('trails-policy'),
  Model: require('trails-model'),
  Service: require('trails-service'),
  TrailsApp: require('trails')
}

Witch allow the following definition :

declare module "trails-api" {
  export class Controller {
    app: TrailsApp;
    log: any;
    id: any;
    __: any;
    config: any;
    new(app: TrailsApp): Controller
  }

  export class Service {
    app: TrailsApp;
    log: any;
    id: any;
    __: any;
    config: any;
    new(app: TrailsApp): Service
  }

  export class Policy {
    app: TrailsApp;
    log: any;
    id: any;
    __: any;
    config: any;
    new(app: TrailsApp): Policy
  }

  export class Model {
    app: TrailsApp;
    new(app: TrailsApp): Model
  }

  export class TrailsApp {
    routes: { path: string, config: {app?: any} }[];
    services: any;
    sitemap: any;

    pkg: any;
    config: any;
    api: any;
    env: any;
    versions: any;
    _trails: any;
    packs: any;
    loadedPacks: any;
    loadedModules: any;
    bound: any;
    started: any;
    stopped: any;
    timers: any;
    constructor(app: any);

    start(app?): any;
    stop(err?): any;
    emit(event?): any;
    onceAny(events, handler?): any;
    after(events): any;
  }
}

With both no more problem when transpile (in es6). And we can use it like this :

import 'trails';
import {Request, Response} from 'express';
import { Controller } from 'trails-api';

/**
 * @module DefaultController
 *
 * @description Default Controller included with a new Trails app
 * @see {@link http://trailsjs.io/doc/api/controllers}
 * @this TrailsApp
 */
export class DefaultController extends Controller {
  /**
   * Return some info about this application
   */
  info(req: Request, res: Response ) {
    res.status(200).json(this.app.services.DefaultService.getApplicationInfo())
  }
}
jaumard commented 8 years ago

So until a better solution here is a working solution:

Instead of using trails-controller, trails-model .... use trails-api

scott-wyatt commented 8 years ago

This fix does require node 6+ if also used with webpack.

scott-wyatt commented 8 years ago

Okay so @jaumard fix is the only relevant way to get this to work for now. Typescript simply does not like the way Trails loads in classes.
The only real way to get Trails compliant with typescript is to upgrade trails completely to es6 and make trails compatible only with node 6.7 and higher and Typescript needs to progress some as well http://kangax.github.io/compat-table/es6/#typescript. Why I do see that as where things are heading, that's a lot of work it seems.

scott-wyatt commented 7 years ago

module.exports = {Controller: class DefaultController extends Controller{...} } will allow TS 1.8 to transpile. Thanks @jaumard! If we put node 6+ and es6 in the roadmap for trails 3.0 then we should move this bounty to that.

jaumard commented 7 years ago

What about merging controller/policy/service and model class into one module ? Don't really see the point of having them all separate. I'll even merge them with Trails main repo like trails-core as they are mandatory to create a project.

What do you think @trailsjs/maintainers ?

scott-wyatt commented 7 years ago

I think it's best they are separate actually :-( The reason why is because them separated means I can use my own trails-controller or whatever.

jaumard commented 7 years ago

In that case why not just put them all together like I did on trails-api? Because generally you use all of them during a project and even if you don't it's only one classes ^^ that will not make your project heavier :)

scott-wyatt commented 7 years ago

Whatever is clever :-p

tjwebb commented 7 years ago

@jaumard @scott-wyatt what's the status on this?

scott-wyatt commented 7 years ago

So, it can be done, and it works, trails-api has the necessary d.ts files. I'd like to publish them to typings, but it's a little tricky to get right.

AnthoniG commented 7 years ago

Is there an example application that uses Typescript please ? Something that I can clone and extend etc ?

I am wanting to write a new NodeJS application and really would like to use Trails to do so, but only if it supports Typescript.

Regards Anthoni

scott-wyatt commented 7 years ago

@AnthoniG this is a little outdated, but yes, here's an example of trails in typescript

scott-wyatt commented 7 years ago

I hope to post trails to @types by the end of this month

AnthoniG commented 7 years ago

@scott-wyatt Cheers. Will take a look at it :)

clayrisser commented 7 years ago

Here is an example of Trails using full es6. I'm assuming it wouldn't be too hard to get typescript to work with this.

https://github.com/jamrizzi/trailblazer

AnthoniG commented 7 years ago

@jamrizzi Cloning REPO to have a look later. Thanks. Typescript and now ES6 are very closely matched, so I should be able to convert it easily enough :smile:

scott-wyatt commented 7 years ago

Still haven't had a chance to post to @types for this. If anyone has a chance, there is $$$ in a bounty :-)

rayhaanq commented 6 years ago

Hi, what's the latest with this? When we use the generator will it generate typescript files?