Giter VIP home page Giter VIP logo

reflect-metadata's Introduction

Metadata Reflection API

NOTE: Now that both Decorators and Decorator Metadata have achieved Stage 3 within TC39, the API proposed below is no longer being considered for standardization. However, this package will continue to support projects that leverage TypeScript's legacy --experimentalDecorators option as some projects may not be able to migrate to use standard decorators.

Installation

npm install reflect-metadata

Usage

ES Modules in NodeJS/Browser, TypeScript/Babel, Bundlers

// - Modifies global `Reflect` object (or defines one in ES5 runtimes).
// - Supports ESM and CommonJS.
// - Contains internal polyfills for `Map`, `Set`, and `WeakMap` for older runtimes.
import "reflect-metadata";

// - Modifies global `Reflect` object (or defines one in ES5 runtimes).
// - Supports ESM and CommonJS.
// - Requires runtime support for `"exports"` in `package.json`.
// - Does not include internal polyfills.
import "reflect-metadata/lite";

CommonJS

// - Modifies global `Reflect` object (or defines one in ES5 runtimes).
// - Contains internal polyfills for `Map`, `Set`, and `WeakMap` for older runtimes.
require("reflect-metadata");

// - Modifies global `Reflect` object (or defines one in ES5 runtimes).
// - Requires runtime support for `"exports"` in `package.json`.
// - Does not include internal polyfills.
require("reflect-metadata/lite");

In the Browser via <script>

HTML

<!-- Modifies global `Reflect` object (or defines one in ES5 runtimes). -->
<!-- Contains internal polyfills for `Map`, `Set`, and `WeakMap` for older runtimes. -->
<script src="path/to/reflect-metadata/Reflect.js"></script>

<!-- Modifies global `Reflect` object (or defines one in ES5 runtimes). -->
<!-- Does not include internal polyfills. -->
<script src="path/to/reflect-metadata/ReflectLite.js"></script>

Script

// - Makes types available in your editor.
/// <reference path="path/to/reflect-metadata/standalone.d.ts" />

Background

  • Decorators add the ability to augment a class and its members as the class is defined, through a declarative syntax.
  • Traceur attaches annotations to a static property on the class.
  • Languages like C# (.NET), and Java support attributes or annotations that add metadata to types, along with a reflective API for reading metadata.

Goals

  • A number of use cases (Composition/Dependency Injection, Runtime Type Assertions, Reflection/Mirroring, Testing) want the ability to add additional metadata to a class in a consistent manner.
  • A consistent approach is needed for various tools and libraries to be able to reason over metadata.
  • Metadata-producing decorators (nee. "Annotations") need to be generally composable with mutating decorators.
  • Metadata should be available not only on an object but also through a Proxy, with related traps.
  • Defining new metadata-producing decorators should not be arduous or over-complex for a developer.
  • Metadata should be consistent with other language and runtime features of ECMAScript.

Syntax

  • Declarative definition of metadata:
class C {
  @Reflect.metadata(metadataKey, metadataValue)
  method() {
  }
}
  • Imperative definition of metadata:
Reflect.defineMetadata(metadataKey, metadataValue, C.prototype, "method");
  • Imperative introspection of metadata:
let obj = new C();
let metadataValue = Reflect.getMetadata(metadataKey, obj, "method");

Semantics

  • Object has a new [[Metadata]] internal property that will contain a Map whose keys are property keys (or undefined) and whose values are Maps of metadata keys to metadata values.
  • Object will have a number of new internal methods for [[DefineOwnMetadata]], [[GetOwnMetadata]], [[HasOwnMetadata]], etc.
    • These internal methods can be overridden by a Proxy to support additional traps.
    • These internal methods will by default call a set of abstract operations to define and read metadata.
  • The Reflect object will expose the MOP operations to allow imperative access to metadata.
  • Metadata defined on class declaration C is stored in C.[[Metadata]], with undefined as the key.
  • Metadata defined on static members of class declaration C are stored in C.[[Metadata]], with the property key as the key.
  • Metadata defined on instance members of class declaration C are stored in C.prototype.[[Metadata]], with the property key as the key.

API

// define metadata on an object or property
Reflect.defineMetadata(metadataKey, metadataValue, target);
Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);

// check for presence of a metadata key on the prototype chain of an object or property
let result = Reflect.hasMetadata(metadataKey, target);
let result = Reflect.hasMetadata(metadataKey, target, propertyKey);

// check for presence of an own metadata key of an object or property
let result = Reflect.hasOwnMetadata(metadataKey, target);
let result = Reflect.hasOwnMetadata(metadataKey, target, propertyKey);

// get metadata value of a metadata key on the prototype chain of an object or property
let result = Reflect.getMetadata(metadataKey, target);
let result = Reflect.getMetadata(metadataKey, target, propertyKey);

// get metadata value of an own metadata key of an object or property
let result = Reflect.getOwnMetadata(metadataKey, target);
let result = Reflect.getOwnMetadata(metadataKey, target, propertyKey);

// get all metadata keys on the prototype chain of an object or property
let result = Reflect.getMetadataKeys(target);
let result = Reflect.getMetadataKeys(target, propertyKey);

// get all own metadata keys of an object or property
let result = Reflect.getOwnMetadataKeys(target);
let result = Reflect.getOwnMetadataKeys(target, propertyKey);

// delete metadata from an object or property
let result = Reflect.deleteMetadata(metadataKey, target);
let result = Reflect.deleteMetadata(metadataKey, target, propertyKey);

// apply metadata via a decorator to a constructor
@Reflect.metadata(metadataKey, metadataValue)
class C {
  // apply metadata via a decorator to a method (property)
  @Reflect.metadata(metadataKey, metadataValue)
  method() {
  }
}

Alternatives

  • Use properties rather than a separate API.
    • Obvious downside is that this can be a lot of code:
function ParamTypes(...types) {
  return (target, propertyKey) => {
    const symParamTypes = Symbol.for("design:paramtypes");
    if (propertyKey === undefined) {
      target[symParamTypes] = types;
    }
    else {
      const symProperties = Symbol.for("design:properties");
      let properties, property;
      if (Object.prototype.hasOwnProperty.call(target, symProperties)) {
        properties = target[symProperties];
      }
      else {
        properties = target[symProperties] = {};
      }
      if (Object.prototype.hasOwnProperty.call(properties, propertyKey)) {
        property = properties[propertyKey];
      }
      else {
        property = properties[propertyKey] = {};
      }
      property[symParamTypes] = types;
    }
  };
}

Notes

  • Though it may seem counterintuitive, the methods on Reflect place the parameters for the metadata key and metadata value before the target or property key. This is due to the fact that the property key is the only optional parameter in the argument list. This also makes the methods easier to curry with Function#bind. This also helps reduce the overall footprint and complexity of a metadata-producing decorator that could target both a class or a property:
function ParamTypes(...types) {
  // as propertyKey is effectively optional, its easier to use here
  return (target, propertyKey) => { Reflect.defineMetadata("design:paramtypes", types, target, propertyKey); }

  // vs. having multiple overloads with the target and key in the front:
  //
  // return (target, propertyKey) => {
  //    if (propertyKey === undefined) {
  //      Reflect.defineMetadata(target, "design:paramtypes", types);
  //    }
  //    else {
  //      Reflect.defineMetadata(target, propertyKey, "design:paramtypes", types);
  //    }
  // }
  //
  // vs. having a different methods for the class or a property:
  //
  // return (target, propertyKey) => {
  //    if (propertyKey === undefined) {
  //      Reflect.defineMetadata(target, "design:paramtypes", types);
  //    }
  //    else {
  //      Reflect.definePropertyMetadata(target, propertyKey, "design:paramtypes", types);
  //    }
  // }
}
  • To enable experimental support for metadata decorators in your TypeScript project, you must add "experimentalDecorators": true to your tsconfig.json file.
  • To enable experimental support for auto-generated type metadata in your TypeScript project, you must add "emitDecoratorMetadata": true to your tsconfig.json file.
    • Please note that auto-generated type metadata may have issues with circular or forward references for types.

Issues

  • A poorly written mutating decorator for a class constructor could cause metadata to become lost if the prototype chain is not maintained. Though, not maintaining the prototype chain in a mutating decorator for a class constructor would have other negative side effects as well. @rbuckton
    • This is mitigated if the mutating decorator returns a class expression that extends from the target, or returns a proxy for the decorator. @rbuckton
  • Metadata for a method is attached to the class (or prototype) via the property key. It would not then be available if trying to read metadata on the function of the method (e.g. "tearing-off" the method from the class). @rbuckton

reflect-metadata's People

Contributors

amatiasq avatar cncolder avatar hasezoey avatar knutkj avatar olegdokuka avatar rbuckton avatar wbuchwalter 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  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  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

reflect-metadata's Issues

Move "use strict" inside scope

When bundling Reflect.js with other libraries for deployment purposes, the global "use strict" seems to cause problems because it automatically applies to all later libraries in the bundle. Would it be possible to nest the "use strict" inside all outermost global functions inside Reflect.js?

minification - copyright

As of now, I'm forced to include a huge amount of unnecessary comments like this:

result = Reflect.getOwnMetadataKeys(C);

The regex parses the (C) as a copyright and keeps the comment.

Is there any way, to swap out class C with e.g. class F ?

Build failing when applied to class

I'm trying to apply metadata to an exported class and I'm getting the following build error in Visual Studio 2013, I can apply metadata to method fine.

require("../libs/reflect-metadata/Reflect");

@Reflect.metadata("ExampleKey", "ExampleValue")
export class ExampleClass {
}

Gives the following build error, any ideas what I'm doing wrong?

Error 1 Type '((target: TFunction) => void | TFunction) | ((target: Object, prop...' is not assignable to type '(target: typeof ExampleClass) => void | typeof ExampleClass'.
Type '(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => void...' is not assignable to type '(target: typeof ExampleClass) => void | typeof ExampleClass'. C:\XXXX.ts 5 1 XXXX.Server

Using a Decorator to get list of implemented interfaces

Hi,

Do you know if it is possible to get the array of interfaces implemented by a class using a decorator:

interface IWarrior {
  // ...
}

interface INinja {
  // ...
}

So If I do something like:

@somedecorator
class Ninja implements INinja, IWarrior {
   // ...
}

At run-time Ninja will have an annotation which contains ["INinja", "IWarrior"] ?

I have asked on stack overflow

Thanks

Does not work in Ie8

It seems like getters and setters are used for Map and Set classes , so it does not work in ie8

Loading Reflect through karma-systemjs fails to load crypto

I'm trying to run my angular2 unit tests with karma-systemjs and I'm running into a weird issue where Reflect tries to load an undefined library called "crypto". From what I understood, Reflect makes some test to check if crypto is availlable in a node environement.

This is the line that breaks :
var nodeCrypto = isNode && require("crypto");

I managed to find a quick workaround by defining a fake module in my systemjs.config, but I'm still wondering if I'm doing something wrong. Maybe there's a better way to deal with this issue. What do you think?

Here's the code for the workaround :
exports.crypto = false;

Reflection cannot determine design:type on poperties with class types that are "defined after current class"

This code:

import 'reflect-metadata';

function Relation() {
    return function (object, propertyName) {
        let type = Reflect.getMetadata('design:type', object, propertyName);
        console.log(type);
    }
}

class Person {
    name: string;
    @Relation()
    info: PersonInfo;
}

class PersonInfo {
    info: Person;
}

produces me:

undefined

however the Person class output looks good:

var Person = (function () {
    function Person() {
    }
    __decorate([
        Relation(), 
        __metadata('design:type', PersonInfo)
    ], Person.prototype, "info");
    return Person;
})();

License Details

I noticed that the license is missing the copyright year...

Reflect.getMetadata return undefined only in IE11

I am learning Decorators and found issue running in IE11, but no problem in chrome and Edge....

only in IE11, Relect.getMetadata() will return undefined.... but in Chrome and edge.. there is no problem.. I only post related part here

function validate<T>(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<T>) {
    let set = descriptor.set;
    descriptor.set = function (value: T) {
        let type = Reflect.getMetadata("design:type", target, propertyKey);   // return undefined.

Enum types being reflected as Number

I'm receiving Number when I retrieve design:type on properties typed as enumerations.
Pardon my ignorance, but it shouldn't be decorated with the actual generated type like in this example?
https://gist.github.com/rbuckton/4b8df4908aad49aac212#metadata-example

The compiler (1.9.0-dev.20160220) is indeed decorating the property with:
__metadata('design:type', Number)

Also all those compiler flags are set to true, but nothing changed:

"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"preserveConstEnums": true

Is that feature yet to come? I'm missing something here?!

I was unable to find any discussion about this on the main repo, can you provide me any heads up in this regard? ๐Ÿ˜•

Thank you!

Provide the ability to enumerate metadata on all property keys

The current proposed metadata API provides no ways of enumerating all the decorated property keys. This information should be available "statically" without a fully instantiated object.

For example, say I have a decorator that sets default values for each decorated property during construction. As the properties would otherwise have never been assigned to, Object.keys returns nothing but the Reflect object clearly knows which properties have decorators.

Get all target keys, given a metadata key and a target object?

After decorating properties of a class with a decorator that uses Reflect.defineMetadata(metadataKey, metadataValue, target, targetKey), is there not a way to ask an instance of that class for all its targetKeys that have a certain metadataKey? I want to enumerate all properties of a possibly non-initialized instance of a decorated class, that have a certain decorator / metadata key.

Suggestion:

Reflect.getTargetKeys(metadataKey, target)

Is there a workaround? Can I access the whole metadata map for now, to get the required information, and how?

Illustration:

class A {
    @ComplexField(B)
    public theB: B;
    @ComplexField(C)
    public theC: C;
}

function ComplexField(type: any) : PropertyDecorator {
    return function (target: any, property: string) : void {
        Reflect.defineMetadata("complexField", type, target, property);
    };
}
..

let a: A = new A();
// Now: how to get all the properties of a that are decorated with the @ComplexField decorator? 
// Suggestion was:
let complexFields: string[] = Reflect.getTargetKeys("complexField", a); // returns ["theB", "theC"] 

Can't Install reflect-metadata

I am writing a NODE stack application, which uses Angular2, passportJS and a number of other dependencies which seem to have peer dependencies on either [email protected] or [email protected]. However, whenever I install or update these, I get warnings that this dependency is not met. If I run

npm i reflect-metadata

then I get the following output:

npm i reflect-metadata --save

> [email protected] install /Users/georgeedwards/Desktop/Gen-App/node_modules/bcrypt
> node-gyp rebuild

  CXX(target) Release/obj.target/bcrypt_lib/src/blowfish.o
  CXX(target) Release/obj.target/bcrypt_lib/src/bcrypt.o
  CXX(target) Release/obj.target/bcrypt_lib/src/bcrypt_node.o
  SOLINK_MODULE(target) Release/bcrypt_lib.node
[email protected] /Users/georgeedwards/Desktop/Gen-App
โ”œโ”€โ”€ [email protected]  extraneous
โ””โ”€โ”€ UNMET PEER DEPENDENCY [email protected]

npm WARN [email protected] requires a peer of [email protected] but none was installed.

however many times I run that command, it doesn't seem to install, or throw any errors...

I am using a mac, running OSX 10.

npm list reflect-metadata
[email protected] /Users/georgeedwards/Desktop/Gen-App
โ””โ”€โ”€ UNMET PEER DEPENDENCY [email protected]

npm ERR! peer dep missing: [email protected], required by [email protected]
npm ERR! code 1

`GetPrototypeOf` fails for arrow functions

Arrow functions do not have a prototype so this will fail when they are reflected upon.

//GetPrototypeOf
// When O = () => 'abc' this fails
let prototype = O.prototype; //undefined
let prototypeProto = Object.getPrototypeOf(prototype); // throws Uncaught TypeError: Cannot convert undefined or null to object(โ€ฆ)
if (prototypeProto == null || prototypeProto === Object.prototype) {
    return proto;
}

Found when attempting to use an arrow function in and angular2 project with: provide(SomeToken, { useFactory: () => 'abc' })
I'd send a PR but I can't seem to get the tests running.

metadataMap.get with valid key is returning undefined

In my code I am trying to access the metadata value for "design:paramtypes" on my class constructor. I have traced the code to the spot where the value gets dropped or things don't look right anymore.

Background

  • I am using Typescript 1.5.0-beta with --emitDecoratorMetadata
  • Calling Reflect.getMetadataKeys(myObject) returns an array of 3 keys that do in fact include the key I am looking for.
  • The metadata is on the object itself, not a parent or ancestor.

While stepping though the code I have discovered the following:

On line 605 of Reflect.js in OrdinaryGetMetadata the correct MetadataKey is being passed in, and the OrdinaryHasOwnMetadata method returns true.

The code path then enters OrdinaryGetOwnMetadata on line 617 of Reflect.js still with the correct MetadataKey.

GetOrCreateMetadataMap returns a valid object with the value that I am looking for as can be seen here:

image

However the very next bit of executable code is line 622 return metadataMap.get(MetadataKey); and this returns an array with a single value of undefined seen here:

image

This appears to be a native function that cannot be debugged and I am curious as to why it is not returning the correct value.

Do you have any insight or advice about how to get this piece of metadata back?

Initial Release

We've got our own metadata system in Aurelia, but this would work fine for us. Since we are working towards a standard, I would like to convert Aurelia over to use this library internally. To feel good about doing that, I would need at least a 0.1.0 release so that I can properly import it via jspm and/or bower. Any chance you could do this? If you can follow semver, then we can manage Aurelia's use of this library well and would be happy with it. This would also enable us to automatically enable our DI to work with TS type info.

Would it be possible to preserve generic metadata?

Would it be possible to preserve parameterized metadata like this:

@mygetter
getUsers(..args): Promise<Users>

@widget
getWidget(id:number):Promise<Widget>

Right now design:returntype preserves return type as Promise object. It would be very helpful if somehow it preserved the type of Promise as well.

Is this something that may be implemented in the future? This would be very helpful for libraries that auto-generate documentation and also to generate schema from class definition.

reflect-metadata causes a http://localhost:3000/crypto Failed to load resource: the server responded with a status of 404 (Not Found)

hi Ron

I have a problem when I try to use reflect-metadata with angular2

I took the angular2 quickstart like https://angular.io/docs/ts/latest/quickstart.html#!#config-files.
I included code that uses Reflect.metadata and Reflect.getMetadata.
I have a Person and json that represents that person.
I deserialize that json into that Person with this code.
The json is displayed on screen and the deserialized Person is printed to the console.

I started from the quickstart angular2 example and I followed the two options:
to use its plunker
to clone it
Option 1: from the angular2 quickstart plunker
Starting from the angular2 quickstart plunker I forked it with your code and added a Person to deserialize and it works like a charm. !!!
You can see the forked plunker here:
http://plnkr.co/edit/GY0k2XqurtfXDjHkAPYV?p=preview

From this example its important to note that:
the transpilation happens in the browser.
there is no need to import 'reflect-metadata'; to use Reflect.metadata or the Reflect.metadata, for some reason Reflect is found I guess because 'reflect-metadata' is a transistive dependency used by angular2.
Option 2: from the clone

I added the same code as in the plunker and imported it into intellij.
I did an npm install and npm start.

After npm start The first error came up and the server could not start. The error is TS2339: Property 'metadata' does not exist on type 'typeof Reflect' on the terminal console and in my intellij.
To try to solve this problem I added:

npm install reflect-metadata --save to have it in my node_modules
in the main.ts I added import 'reflect-metadata';
After doing this, the error in the intellij disappeared and now it seems to find the Reflect.

when I do npm start the server starts but when I access the page it throws an error in the console with the message
http://localhost:3000/reflect-metadata Failed to load resource: the server responded with a status of 404 (Not Found)

To bypass this error I modified the systemjs.config.js with the following lines:

var map = {
    'app':                        'app', // 'dist',

    '@angular':                   'node_modules/@angular',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    'rxjs':                       'node_modules/rxjs',
    'reflect-metadata':           'node_modules/reflect-metadata'
  };

  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
    'reflect-metadata':{ main: 'Reflect.js', defaultExtension: 'js' }
  };

Then I did the npm start again and now I have the error in the chrome console

Error: patchProperty/desc.set/wrapFn@http://localhost:3000/node_modules/zone.js/dist/zone.js:769:27
    Zone</ZoneDelegate</ZoneDelegate.prototype.invokeTask@http://localhost:3000/node_modules/zone.js/dist/zone.js:356:24
    Zone</Zone</Zone.prototype.runTask@http://localhost:3000/node_modules/zone.js/dist/zone.js:256:29
    ZoneTask/this.invoke@http://localhost:3000/node_modules/zone.js/dist/zone.js:423:29

    Error loading http://localhost:3000/crypto as "crypto" from http://localhost:3000/node_modules/reflect-metadata/Reflect.js

And here I'm stuck :(
Maybe I should include the reflect-metadata in a different way or maybe I'm configuring the systemjs.config.js in the wrong way when I had 'reflect-metadata'.

thanks
Ovidio

NPM package includes unnecessary files

Hi @rbuckton ,

Going by the .npmignore file, it seems that the NPM package once installed shouldn't include typings/test folder as well as Reflect.ts and other files which makes sense, however when installing from NPM it does include these files.

image

The only reason I bring this up is due to what I believe to be an issue with TypeScript extension for Visual Studio 2015 when performing a clean/rebuild of a project with TypeScript, it deletes the Reflect.js.

I am using JSPM trying to build a simple Angular 2 demo and whenever I build the project, Reflect.js is deleted from the jspm_packages folder even though tsconfig.json is excluding the jspm_packages folder. I think this is because of the matching Reflect.ts/Reflect.js names where the exclude is being ignored/not working for clean but successfully being ignored for build. This leaves my JSPM project unable to resolve the Reflect.js file as it's been deleted. I can confirm this by renaming Reflect.ts to Reflect_.ts and a clean/rebuild leaves the Reflect.js untouched.

Below is my tsconfig.json for completeness.

{
  "compileOnSave":  true,
  "compilerOptions": {
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "module": "commonjs",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": "node"
  },
  "exclude": [
    "jspm_packages",
    "typings",
    "node_modules",
    "wwwroot"
  ]
}

Reflect.js is untouched by a clean/rebuild if in the node_modules directory, but not so for the jspm_packages directory.

Provided you do want the files ignored, could the .npmignore be updated to remove these files from the npm package? I think the file contents should be:

node_modules
test
typings
Reflect.ts
tsconfig.json

Thanks for the package either way ๐Ÿ‘

Error: decorator is not a function

I'm unable to make a custom annotation attribute that takes parameters, the setup is an Angular 2 app written in TypeScript.

TypeScript code:


export function myAttribute(target: any, keyName: string): any {
    if (!target || !keyName) return;

    console.log('inside attribute!');
}

export class Organization {
    public id: string;
    public name: string;
    @myAttribute(null, 'test') public url: string;
}

JavaScript outout:

System.register([], function(exports_1, context_1) {
    "use strict";
    var __moduleName = context_1 && context_1.id;
    var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
        else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    };
    var __metadata = (this && this.__metadata) || function (k, v) {
        if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
    };
    var Organization;
    function myAttribute(target, keyName) {
        if (!target || !keyName)
            return;
        console.log('inside attribute!');
    }
    exports_1("myAttribute", myAttribute);
    return {
        setters:[],
        execute: function() {
            Organization = (function () {
                function Organization() {
                }
                __decorate([
                    myAttribute(null, 'test'), 
                    __metadata('design:type', String)
                ], Organization.prototype, "url", void 0);
                return Organization;
            }());
            exports_1("Organization", Organization);
        }
    }
});

//# sourceMappingURL=OrganizationStore.js.map

The library is imported in my boot.ts, like this:

import 'reflect-metadata';

The exception:

startup.js:485 Error: TypeError: decorator is not a function
        at DecoratePropertyWithoutDescriptor (http://localhost:3000/jspm_packages/npm/[email protected]/Reflect.js:564:13)
        at Object.decorate (http://localhost:3000/jspm_packages/npm/[email protected]/Reflect.js:91:20)
        at __decorate (http://localhost:3000/app/state/OrganizationStore.js:6:96)
        at eval (http://localhost:3000/app/state/OrganizationStore.js:26:17)
        at execute (http://localhost:3000/app/state/OrganizationStore.js:31:14)

As you see I'm on release 0.1.3, using latest TypeScript (1.8.10) and this is my tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "preserveConstEnums": true,
    "jsx": "react"
  },
  "exclude": [
    "node_modules",
    "platforms",
    "www"
  ]
}

Any suggestions for what I can try to fix the issue?

Updating meta of proto object wrongly

When we have a mutable value on proto object and update the same to save on self. It is updating the metadata value on proto object as well.

I do understand that I should clone the value before updating but still when we get values from proto ( not self) it should be cloned and passed to avoid accidental fail. I could have done thsi but this was @angular/ compiler code that was causing an issue.

I have froked the repo here https://github.com/arpit-agarwal/reflect-metadata and added a test-case which fails on your repo and works after my fix for cloning. If desired i may create a pull request.
MutableKeyValueDefinedOnPrototype

    it("MutableKeyValueDefinedOnPrototype", () => {
        let prototype = {};
        let obj = Object.create(prototype);
        Reflect.defineMetadata("key", ["value_proto"], prototype, undefined);
        let result = Reflect.getMetadata("key", obj, undefined);
        assert.equal(result[0], "value_proto");
        result.push("value_self");
        Reflect.defineMetadata("key", result , obj, undefined);
        let result_proto = Reflect.getMetadata("key", prototype, undefined);
        let result_self = Reflect.getMetadata("key", obj, undefined);
        assert.equal(result_proto.length, 1);
        assert.equal(result_self.length, 2);

    });

compiler error in TS 1.8

error TS2339: Property 'getMetadata' does not exist on type 'typeof Reflect'.

Reflect.getMetadata("design:type", target, key);

build error with typescript 2.0.2 RC

With the changes described in microsoft/TypeScript#9646 now there are build errors in projects using reflect-metadata.

We are using angular, webpack and awesome-typescript-loader and experiencing now:
"File '.../node_modules/reflect-metadata/Reflect.d.ts' not found" error during the build.

Changing import "./reflect-metadata"; to import "./reflect-metadata.d.ts"; in typings.d.ts fixes the problem.

Reflect.getMetadata is not a function

So i have update to the latest RC7 of angular2 and now im getting this error :

Reflect.getMetadata is not a function

What can I do to fix this issue, I'm using the 0.1.2 version. (Also tried with the latest 0.1.8)

Thanks in advance!

Add typescript.definition entry in package.json for tsd

Tsd supports definition files in external modules, but it needs to be in the "typescript" section of the package.json file.

Currently, this information is in the typings entry, and does not work out of the box with tsd.

Errors

When i try to bundle reflect-metadata with webpack i'm getting a lot of warnings along with the following errors. should i ignore these warnings for my production build ?
errors

reflect 0.1.4 giving a lot of errors

Hello, with this new update and using Typescript 1.8.10 I am getting a lot of this errors:

ERROR in /Users/jesus/Programming/Work/angular.io/public/docs/_examples/~/reflect-metadata/Reflect.ts
(255,21): error TS2384: Overload signatures must all be ambient or non-ambient.

Hundreds perhaps.

My best guess is that your Typescript version used here is old or you are using old syntax.

I report this because at angular.io we have a webpack cookbook and on build it gives dozen of warnings (Due the crypto require changes made recently that could be a webpack issue perhaps) and hundreds of this errors.

More info at angular/angular.io#2042

0.1.4 drives webpack crazy

WARNING in .//reflect-metadata/Reflect.js
Critical dependencies:
841:28-35 require function is used in a way in which dependencies cannot be statically extracted
@ ./
/reflect-metadata/Reflect.js 841:28-35

and many thigns like that after this happens.

However if I comment out the following line (841):

return (void 0, require)("crypto");

everything is fixed.

Currently forced to roll back :(

Set metadata to parent class

Hey @rbuckton

I'm currently trying to use metadata in my typescript api concept. Previously I used my own hidden field to store the information. Now since I use reflection, I want to set metadata on the base controller.

Now it seems, I'm missing something ๐Ÿ˜„

I've got the following setup:

@Controller()
export class TestController {

    @Route()
    public search(request: Request, response: Response): void {
        console.log(1234);
        response.json({foo: 'bar'});
    }
}

Now the Route decorator does register itself to the controller. Later when the controller decorater is called, all routes are console.logged.

Previously, I added my own __routes property to the controller to get those routes. It would be cool to use reflect for that.

My approach is:

let routes: RouteRegistration[] = Reflect.getOwnMetadata(routesMetadataKey, target) || [];
routes.push(new RouteRegistration(route || '', httpMethod, descriptor.value));
Reflect.defineMetadata(routesMetadataKey, routes, target, propertyKey);

the target is the Class (TestController), the property key is the name of the function (search in this case). The goal is to get a list of routes into the TestControllers metadata.

Cheers

Make it an official proposal for ES (?)

This is half question, half suggestion: Are there plans for adding Reflect.metadata to the list of ECMA262 proposals? It seems like there is progress in the TypeScript integration but no trace of adding it to JS proper. I think it would be valuable having it exposed early in that list because it could help direct the conversation about the decorator proposal (e.g. an official way of implementing annotations using decorators instead of just "random code patching/obfuscation").

Losing metadata

Hello,

I've been trying to use this module using typescript for the decorators. I seem to keep losing my data and it's confusing me a little bit. Upon creating a small test, I found some odd behavior I wasn't expecting (I assume the problem here is me).

Whenever I put a decorator on a property, the decorator doesn't get the class as target. I have to use target.constructor to get it. But when I put the decorator on the class itself, it does seem to get the class.

Code speaks a thousand words, so:

export function field() {
  return (target:Object, property:string) => {
    console.log(target, target.constructor);
  };
}

@field() // Log above: [Function: Field]  [Function: Function]
export class Field {
  @field() // Log above: {}  [Function: Field]
  public property:any;
}

This confuses me. How can I always get the metadata of a class (including properties) if I always get a different target? Am I missing something on how this should be used?

Thank you for your time.

reflect-metadata with an angular rc5 app error localhost/:24 Error: TypeError: Cannot read property 'type' of null(โ€ฆ)

hello Ron,

I was using reflect-metadata 0.1.3 in an angular rc4 app in a project.
Now I use reflect-metadata 0.1.8 and angular rc5.

The way I was using it was the following.

  • systemjs.config.js
    map['reflect-metadata'] = 'node_modules/reflect-metadata/Reflect.js';
  • main.ts
    import "reflect-metadata";

-In my application
`export class MapUtils {

static getClazz(target:any, propertyKey:string):any {
    return Reflect.getMetadata("design:type", target, propertyKey)
}

static getJsonProperty<T>(target:any, propertyKey:string):IJsonMetaData<T> {
    return Reflect.getMetadata(jsonMetadataKey, target, propertyKey);
}`

But now I have the error:
Error: TypeError: Cannot read property 'type' of null(โ€ฆ)

I suspect I'm not mapping properly in the systemjs.config.js but with rc4 and angular rc4 that worked.

If you could guide me into the right direction that would be great

thanks

IE8 expected identifier error

When I try to open my website in a internet explorer ie8, doesn't work. While in IE11 I have no problems.

When I debug the error is: "Expected identifier" Reflect.js, line 516 character 26. It seems like don't recognize the "delete" on "if(!metadataMap.delete(metadataKey)) return false".

What can I do?
Thanks.

[email protected] may be not compatible with 0.1.3

Hi,

I have [email protected] installed on my machine, and

  "dependencies": {
      "reflect-metadata": "^0.1.3",
  }

in the my packages.json's dependency list.

Yesterday when i restore the all the node modules, npm picked up [email protected] for me, which results an compiling error:

Build:Cannot find name 'Record'. ...\reflect-metadata\Reflect.ts 20

I am not 100% if that is compatibility issue, but thank you for taking a look.

Correct way to create mutating decorator for a class constructor

According to readme.md:

A poorly written mutating decorator for a class constructor could cause metadata to become lost if the prototype chain is not maintained. Though, not maintaining the prototype chain in a mutating decorator for a class constructor would have other negative side effects as well. @rbuckton

Could you please provide an example? I've encountered this while creating decorator for Angular 2.

Is metadata stored in external map using class/function as key?

Bower package?

I see that this is on npm already, but could we get this on Bower as well?

Add support for generic type such as Array<T> when introspecting metadata

Considering the following function declaration with a decorator added to extract metadata from a method in a typescript class.

@logMetadata
public getFoos(): Array<Foo> {return new Array<Foo>()};

function logMetadata(target: any, key: string) {

    var returnvalue = Reflect.getMetadata("design:returntype", target, key);
    console.log(`${key} return value: ${returnvalue.name}`);
  }

the statement: console.log(${key} return value: ${returnvalue.name}) writes:

'getFoos return value: Array'

whereas the expected output should have been:

'getFoos return value: Array'

Cheers

using this on ionic 2 / angular 2

Incorrect environment detection in WeakMapPolyfill

In CreateWeakMapPolyfill(), to detect if we are running under node, this code is used:

const isNode = typeof global !== "undefined" &&
  typeof module === "object" &&
  typeof module.exports === "object" &&
  typeof require === "function";

But when using tools which implement CommonJS API in the browser such as Webpack or Browserify, isNode will be incorrectly set to true.

We could replace the check by this one:

 const isNode = Object.prototype.toString.call(global.process) === '[object process]';

Related PR: #7

Thanks!

When installed redundantly, Metadata could be erased

If multiple node modules have dependencies on 'reflect-metadata' and modules are installed redundantly, metadata is erased after later require('reflect-metadata') is invoked.

Assume that using module Foo and Bar, they're using reflect-metadata
npm package tree looks like below
|โ”€ Foo
| โ”” [email protected]
|โ”€ Bar
โ”” [email protected]

One of my own decorators save something by invoking Reflect.defineMetadata() and another module imports Bar module, so another reflect-metadata module is initialized.
On initialization, reflect-metadata patches its own functions to global Reflect object.
On second initialization, it may overwrite functions, but internal Metadata object will be lost.

I've avoided this problem by specifying same semver version in package.json. latest npm (ver>=3) does not install redundantly.
|โ”€ Foo
| โ”” [email protected]
|โ”€ Bar

But for the case modules should use different versions or one of them is maintained by others,
it would be great to copy internal Metadata values

Status

We have people asking us what is going on with this spec. Is the TS team behind it? Is it still planned to be submitted as a proposal? Some clarification would be very welcome.

No valid 'elements' option was specified for xxx

@JsonObject({ knownTypes: [EinheitentabellenEintrag, NachschlagetabellenEintrag]})
export class Nachschlagetabelle {
    public static get NACHSCHLAGETABELLE_TYPE(): string {
        return "Nachschlagetabelle";
    }

    @JsonMember
    tabellenname: string = "";

    @JsonMember({ elements: EinheitentabellenEintrag})
    test: EinheitentabellenEintrag[];

    @JsonMember({ elementType: NachschlagetabellenEintrag })
    ntEintraege: NachschlagetabellenEintrag[] = [];
}

Error:
No valid 'elements' option was specified for 'Nachschlagetabelle.test'.(โ€ฆ)

Why do I get the error message eventhough I specified a the elements option?

edit: code block formatting - @rbuckton

Minified version

Now that there is a major framework (Angular 2) using reflect-metadata as a production dependency that needs to be loaded by the browser, would it be possible to have a minified JavaScript version included in the package, like other librairies do, to avoid extra build steps ?

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.