Export type declaration outside of the function - google-closure-compiler

I'm trying to use google closure compiler (I'll call it compiler for short) to validate JavaScript codebase like that:
java -jar compiler.jar --js='**.js' --jscomp_error newCheckTypes > NUL 2> gcc.log
The thing is we already have a lot of code in AMD and type annotations written for core modules like that:
define(function () {
/** #constructor */
MyClass () {}
/** #param {string} s */
MyClass.prototype.myMethod = function (s) {
alert(s);
}
return MyClass;
});
I'd like to reference the type /** #type {MyClass} */ in other modules, so if I call some method with wrong arguments, it will complaint.
Unfortunately, when I use such type annotations, compiler outputs:
Bad type annotation. Unknown type MyClass
/** #type {MyClass} */
If I strip out module-delcaring function, compiler "understands" my declaration, but I don't feel like rewriting our code in that way.
Is there a way to make compiler see my type declarations and apply in other modules?

The compiler has a --transform_amd_modules which will rewrite an AMD module to CommonJS. It only supports a limited number of define signatures and is not widely used or actively maintained.
With CommonJS modules, you can use the --process_common_js_modules flag to rewrite and rescope the code to a global type which can be checked by the compiler. The CommonJS modules functionality is actively maintained.

Related

Where is the http.get() function in Angular2 defined?

I'm new to Typescript and Angular 2.
I wanted to look at the exact implementation of http.get(), so I opened the file in ./node_modules/angular2/src/http/http.d.ts and scrolled to the get function. This is what I found:
/**
* Performs a request with `get` http method.
*/
get(url: string, options?: RequestOptionsArgs): Observable<Response>;
/**
* Performs a request with `post` http method.
*/
post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response>;
/**
....
Basically, there is no function definition. It seems like an abstract method (in Java lingo). I looked through the other http files, used VSCode intellisense, and couldn't find the code for the body of the function.
Where is it and how can I find it?
It is defined here: https://github.com/angular/angular/blob/master/modules/angular2/src/http/http.ts
What you are seeing is the TypeScript typings file. It contains the definitions, but not the implementation.

Override a symfony service tag with a compiler pass

I'm trying to override a tag in a symfony service definition with a compiler pass. The service as an example would be data_collector.translation.
The goal is to deactivate the data collector service to disable the element in the symfony web developer toolbar. To do this, I have to set the priority of the data_collector tag to 0.
I could also override it in my own service definition:
services:
data_collector.translation:
class: 'Symfony\Component\Translation\DataCollector\TranslationDataCollector'
tags:
- {name: 'data_collector', priority: '0'}
arguments: [#translator.data_collector]
But as I want to do this for a few of the data collectors, I would need to know the mandatory arguments for the data collector definition. The priority works the same for all collectors and therefore I would only need the name of the collector to disable it.
So I wrote the following compiler pass:
class DataCollectorCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('data_collector.translation')) {
return;
}
$definition = $container->getDefinition('data_collector.translation');
$tags = $definition->getTags();
$tags['data_collector'][0]['priority'] = 0;
$definition->setTags($tags);
$container->setDefinition('data_collector.translation', $definition);
}
}
To make things more wired: When I run this command:
$ php app/console container:debug --show-private --tag='data_collector'
I get the following output:
data_collector.translation #WebProfiler/Collector/translation.html.twig translation 0 Symfony\Component\Translation\DataCollector\TranslationDataCollector
So the priority even in the debugger is set to 0.
But for which reason ever the element is still shown in the toolbar.
What did I do wrong here? Is there another mechanism for overwriting a tag within a compiler pass?
The compiler pass does run (tested it with printing out stuff)
I'm using Symfony 2.7.1
Turns out the code does work, the only problem is, that the CompilerPass is run after the ProfilerPass which is part of the FrameworkBundle. Putting my bundle with the CompilerPass before the FrameworkBundle in the AppKernel solves the problem (more information here). For not even initiating the data collectors it's better to remove all tags instead of just setting the priority to 0.
That's what the final solution looks like:
class DataCollectorCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$collectorsToRemove = [
'data_collector.form',
'data_collector.translation',
'data_collector.logger',
'data_collector.ajax',
'data_collector.twig'
];
foreach($collectorsToRemove as $dataCollector) {
if (!$container->hasDefinition($dataCollector)) {
continue;
}
$definition = $container->getDefinition($dataCollector);
$definition->clearTags();
}
}
}
Can you try this?
if (!$container->hasDefinition('data_collector.form')) {
return;
}
$definition = $container->getDefinition('data_collector.form');
$definition->clearTags();
$container->setDefinition('data_collector.form', $definition);
Why not use your compiler pass to manipulate directly the service Definition of the service holding all these collectors ?
If I look at the compiler pass responsible for loading the data collector, it seems that they are all injected using a method call injection.
You could use your compiler pass to rewrite the method call array using methods like setMethodCalls, removeMethodCall, ... of the Definition entity.
The method call manipulation documentation : link

Symfony2 docs on Routing component?

I was looking for Routing Component's documentation, explicitly which types of parameters it accepts.
For example, the type: annotations in my just created app's routing.yml made me want to look what other types are out there, but there is no docs on it. I can only find the documentation in the Book and a little bit in Components.
Loader types
Main types of routing loaders are described in the component's docs. It mentions quite a few loaders:
YamlFileLoader
XmlFileLoader
PhpFileLoader
ClosureLoader
AnnotationFileLoader, AnnotationClassLoader & AnnotationDirectoryLoader
You'll find all the core loaders in the Symfony\Component\Routing\Loader namespace
It's all based on Config's component loaders, so it's worth if you also read about the Config component.
Each loader's supports() method will tell you in which circumstances the loader is actually used. For example, for the YamlFileLoader it's:
public function supports($resource, $type = null)
{
return is_string($resource)
&& 'yml' === pathinfo($resource, PATHINFO_EXTENSION)
&& (!$type || 'yaml' === $type);
}
You can see it looks at resource's extension and type.
Custom loaders
You can implement your own loaders by implementing the Symfony\Component\Config\Loader\LoaderInterface.
Read more about it in the How to Create a custom Route Loader cookbook. It actually explains quite a lot on how routing loaders work. Have a look at some 3rd party loaders too, such as the FOSRestBundle's one.
How to wire it all together
Have a look at the generated container in the Symfony Standard Edition to see how the full stack framework wires it all together. It should look similar to:
/**
* Gets the 'routing.loader' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* #return \Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader A Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader instance.
*/
protected function getRouting_LoaderService()
{
$a = $this->get('file_locator');
$b = $this->get('annotation_reader');
$c = new \Sensio\Bundle\FrameworkExtraBundle\Routing\AnnotatedRouteControllerLoader($b);
$d = new \Symfony\Component\Config\Loader\LoaderResolver();
$d->addLoader(new \Symfony\Component\Routing\Loader\XmlFileLoader($a));
$d->addLoader(new \Symfony\Component\Routing\Loader\YamlFileLoader($a));
$d->addLoader(new \Symfony\Component\Routing\Loader\PhpFileLoader($a));
$d->addLoader(new \Symfony\Component\Routing\Loader\AnnotationDirectoryLoader($a, $c));
$d->addLoader(new \Symfony\Component\Routing\Loader\AnnotationFileLoader($a, $c));
$d->addLoader($c);
return $this->services['routing.loader'] = new \Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader($this->get('controller_name_converter'), $this->get('monolog.logger.router', ContainerInterface::NULL_ON_INVALID_REFERENCE), $d);
}
The key here is the LoaderResolver which takes care of finding an appropriate loader for a type of configuration.

Using modules in Meteor.js with Typescript

Folks, I'm trying to do something that I thought ought to be simple, but I must be doing something wrong. I'm trying to simply have a clear structure in my meteor application which uses Typescript.
Here are my requirements:
All interfaces are available in both client and server
Some class implementations are only available on the server
I don't want to rely on file load order for my application to work properly
I need my own module to not clash with global objects (such as the Position class for example)
I need to have one monolithic include file for server, one for both client and server and one for client (don't want to have 10s of includes on top of my files)
The setup that I have right now is this
server
server-book.ts
client
shared
collections.ts
definitions
server
include.d.ts (includes all .d.ts files in this folder)
server-book.d.ts (server specific implementation of book)
client
shared
include.d.ts (includes all .d.ts files here)
book.d.ts (book interface definition)
collections.d.ts
In each .d.ts file I have
module MyModule {
interface Bla {}
};
In each .ts file that defines a class I have:
module MyModule {
export class MyBla implements Bla {};
}
All .d.ts files generated for classes are generated by tsc -d.
No .ts files are being included via ///<reference> rather only .d.ts files.
Now, when I run this, I get an error that MyModule is undefined:
/// <reference path="shared/include.d.ts"/>
/// <reference path="server/include.d.ts"/>
Meteor.startup(() => {
var temp = new MyModule.ServerBook();
});
The error occurs right on MyModule.
What am I doing wrong? What should be the proper setup here?
Thanks!
I have dealt with this issue on my blog. I decided to use the evil eval command, since it gave me the easiest possibility of using modules till something more sophisticated appears.
File /lib/foo.ts is position in the subdirectory since it has to be loaded before Bar.
eval('var Hugo = (this.Hugo || (this.Hugo = {})'); // this will override the automatically emitted var Hugo and assigns it with globally defined Hugo module
module Hugo {
export class Foo {
foo():string {
return 'foo'
}
}
}
File /bar.ts
/// <reference path="lib/foo.ts"/>
eval('var Hugo = (this.Hugo || (this.Hugo = {})'); // this will override the automatically emitted var Hugo and assigns it with globally defined Hugo module
module Hugo {
export class Bar extends Foo {
bar () : string {
return 'bar';
}
}
}
File /test.ts
/// <reference path="lib/foo.ts"/>
/// <reference path="bar.ts"/>
var m = new Hugo.Bar();
console.log(m.bar());
console.log(m.foo());
As mentioned here, for classes, the solution is even simpler:
class ExportedClass {
variable : int;
}
this.ExportedClass = ExportedClass;
Definition files should use the declare keyword. You would normally get an error if you didn't use this keyword.
declare module MyModule {
export interface Bla {}
}
And
declare module MyModule {
export class MyBla implements Bla {
}
}
It is also worth checking that the ServerBook class has the export keyword (just like MyBla in your examples).
After lot of trial and errors, here are my findings so far :
Using typescript "module" keyword doesn't get well with Meteor. I think at the moment you cannot use it (or the workarounds are too complicated for me).
However, here is what you can do :
Let say that you have package A where you want to define a class ClassToExport which you want to make public.
class ClassToExport {
getFoo(){
return "foo";
}
}
Please note that you can't write this.ClassToExport = ClassToExport and
api.export('ClassToExport') or else ClassToExport won't be available in the global scope of package A, hence the need for a module/namespace for exporting your class, which we will see next.
Now, for the class to be available for the consumers of your package, you have to create a namespace, which will be the equivalent of the "module" typescript keyword for internal module.
So let's write :
declare var packageA; //so that the compiler doesn't complain about undeclared var
packageA = packageA || {}; //so that this namespace can be reused for the entire package
packageA.ClassToExport = ClassToExport; //the actual export
Now, don't forget to write
api.export('packageA') in the package.js of package A
If you have a package B where you want to use ClassToExport, you write in package B:
var cte = new packageA.ClassToExport();
without forgetting to api.use package A in package B's package.js
If you don't want to write the namespace each time you use the class, you can also write var ClassToExport = packageA.ClassToExport; at the top of your using file.
If you need a global class for you package only, without exporting it, then you can do instead just :
this.ClassToExport = ClassToExport
and again don't write api.export('ClassToExport'), or it won't be available in the package anymore.
This way, i think the features (export/ import) of internal typescript modules are there.
If you are not afraid of gulp build, I have prepared a typescript boilerplate project which allows you to comfortably use typescript from within your app, not depending on packages.
https://github.com/tomitrescak/meteor-boilerplate-typescript
Random idea, what about extend Meteor instead of Window.
Meteor.yournamespace = Meteor.yournamespace || {};
Meteor.yournamespace.myclass = new MyClass();
or
Meteor.yournamespace.MyClass = MyClass();
I think this is less invasive than go directly to the window object IMHO. my two cents.
now you can do Meteor.yournamespace.MyClass :P
--EDIT
Then you could create a meteor-extend.d.ts file and do something like:
/// <reference path="main.d.ts" />
declare module Meteor {
var yournamespace: any;
}
Now you can remove the <any> before Meteor and Typescript will not complaint.

Doctrine PHPCR-ODM under Symfony not detecting mapped Document class

I am attempting to integrate PHPCR-ODM with an existing Symfony project, and am having trouble getting it to (presumably) detect my mapped Document class. Specifically, I get an error like this when attempting to persist a Document of my class MyDocument:
[Doctrine\Common\Persistence\Mapping\MappingException]
The class 'Example\Common\ORM\Document\MyDocument' was not found in the chain configured namespaces Doctrine\ODM\PHPCR\Document
My class is in a potentially strange namespace because this project uses Doctrine ORM as well, and thus far I've just added a new space for mapped Documents off of that, but I can't imagine the choice of namespace name affects the functionality.
Per the docs, I have added to my app/autoload.php:
AnnotationRegistry::registerFile(__DIR__.'/../vendor/doctrine/phpcr-odm/lib/Doctrine/ODM/PHPCR/Mapping/Annotations/DoctrineAnnotations.php');
My app/config/config.yml includes the following (with parameters set in parameters.yml):
doctrine_phpcr:
session:
backend:
type: jackrabbit
url: %jackrabbit_url%
workspace: %jackrabbit_workspace%
username: %jackrabbit_user%
password: %jackrabbit_password%
odm:
auto_mapping: true
My document class lives in src/Example/Common/ORM/Document/MyDocument.php and looks like:
<?php
namespace Example\Common\ORM\Document;
use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCRODM;
/**
* #PHPCRODM\Document
*/
class MyDocument
{
/**
* #PHPCRODM\Id
*/
private $id;
/**
* #PHPCRODM\ParentDocument
*/
private $parent;
/**
* #PHPCRODM\Nodename
*/
private $name;
// .. etc
Finally, the code I am using to test the integration is inside a simple console command, and looks like:
use Example\Common\ORM\Document\MyDocument;
// ...
$documentManager = $this->container->get('doctrine_phpcr.odm.default_document_manager');
$document = new MyDocument();
$document->setParent($documentManager->find(null, '/'));
$document->setName('ExampleName');
$documentManager->persist($document);
$documentManager->flush();
I have verified that my MyDocument class is being correctly loaded, but it seems that the annotations are not being processed in a way that is making the DocumentManager aware that it is a mapped Document class.
My guess is that I have overlooked some simple configuration step, but from looking repeatedly and thoroughly at the docs for PHPCR, PHPCR-ODM, and even Symfony CMF, I can't seem to find anything. Most of the examples out there involve using PHPCR via Symfony CMF, and I wasn't able to find many (any?) real world examples of PHPCR-ODM being integrated in a regular Symfony project.
edit: The Eventual Solution
I followed the advice that #WouterJ gave below and it fixed my problem, and I further followed his suggestion of adding a compiler pass to my Symfony bundle to make this work with a non-standard namespace (i.e., something other than YourBundle\Document). In my case, this is going into a library that will be re-used elsewhere rather than a bundle, so it was appropriate.
To do this, I added a method to the src/Example/Bundle/ExampleBundle/ExampleBundle.php file like so:
<?php
namespace Example\Bundle\ExampleBundle;
use Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class ExampleBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$mappedDirectories = array(
realpath(__DIR__ . '/../../Common/ODM/Document')
);
$mappedNamespaces = array(
'Example\Common\ODM\Document'
);
$phpcrCompilerClass = 'Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass';
if (class_exists($phpcrCompilerClass)) {
$container->addCompilerPass(
DoctrinePhpcrMappingsPass::createAnnotationMappingDriver(
$mappedNamespaces,
$mappedDirectories
));
}
}
}
That code allows any mapped document classes to be placed in the Example\Common\ODM\Document namespace and it will pick them up. This example uses annotations but the same pattern can be used for XML or YAML mappings (see the Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass class for method signatures).
I found that I also needed to define the doctrine_phpcr.odm.metadata.annotation_reader service for this to work, which I did in app/config.yml:
services:
doctrine_phpcr.odm.metadata.annotation_reader:
class: Doctrine\Common\Annotations\AnnotationReader
There may be a better way to do that, but that was enough to make it work for me.
The document should be placed in the Document namespace of the bundle, not the ORM\Document namespace.
If you really want to put it in the ORM\Document namespace (which is very strange, because we are talking about an ODM not an ORM), you can use the doctrine mapping compiler pass: http://symfony.com/doc/current/cookbook/doctrine/mapping_model_classes.html

Resources