Open jaumard opened 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.
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.
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);
}
}
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...
What do you mean by extending TrailsApp ?
@scott-wyatt is the file definition you put above or another one ?
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
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'
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())
}
}
So until a better solution here is a working solution:
Instead of using trails-controller, trails-model .... use trails-api
This fix does require node 6+ if also used with webpack.
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.
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.
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 ?
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.
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 :)
Whatever is clever :-p
@jaumard @scott-wyatt what's the status on this?
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.
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
@AnthoniG this is a little outdated, but yes, here's an example of trails in typescript
I hope to post trails to @types by the end of this month
@scott-wyatt Cheers. Will take a look at it :)
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.
@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:
Still haven't had a chance to post to @types for this. If anyone has a chance, there is $$$ in a bounty :-)
Hi, what's the latest with this? When we use the generator will it generate typescript files?
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%20FilesWe 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 :)