All Projects → rbuckton → Reflect Metadata

rbuckton / Reflect Metadata

Licence: apache-2.0
Prototype for a Metadata Reflection API for ECMAScript

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects
HTML
75241 projects

Projects that are alternatives of or similar to Reflect Metadata

Laravel Meta
Metadata for Eloquent model
Stars: ✭ 124 (-94.73%)
Mutual labels:  metadata
Ytdlrc
☁️ Downloads videos and metadata with youtube-dl and moves each file on completion to an rclone remote
Stars: ✭ 140 (-94.06%)
Mutual labels:  metadata
Amundsen
Amundsen is a metadata driven application for improving the productivity of data analysts, data scientists and engineers when interacting with data.
Stars: ✭ 2,901 (+23.18%)
Mutual labels:  metadata
Owmeta
Unified, simple data access python library for data & facts about C. elegans anatomy
Stars: ✭ 134 (-94.31%)
Mutual labels:  metadata
Rcrossref
R client for various CrossRef APIs
Stars: ✭ 137 (-94.18%)
Mutual labels:  metadata
Codestar Framework
A Simple and Lightweight WordPress Option Framework for Themes and Plugins
Stars: ✭ 147 (-93.76%)
Mutual labels:  metadata
Isbntools
python app/framework for 'all things ISBN' including metadata, descriptions, covers...
Stars: ✭ 122 (-94.82%)
Mutual labels:  metadata
Metadata.js
Library for building offline-first browser-based applications :: платформа автономных веб-приложений
Stars: ✭ 165 (-92.99%)
Mutual labels:  metadata
Dataspice
🌶 Create lightweight schema.org descriptions of your datasets
Stars: ✭ 137 (-94.18%)
Mutual labels:  metadata
Timber Ruby
🌲 Great Ruby logging made easy.
Stars: ✭ 154 (-93.46%)
Mutual labels:  metadata
Reflection
Lightweight (3K) ES Module implementation of reflect-metadata
Stars: ✭ 136 (-94.23%)
Mutual labels:  metadata
Widoco
Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template.
Stars: ✭ 136 (-94.23%)
Mutual labels:  metadata
Metadata Extractor
Extracts Exif, IPTC, XMP, ICC and other metadata from image, video and audio files
Stars: ✭ 1,972 (-16.26%)
Mutual labels:  metadata
Coregpx
A library for parsing and creation of GPX location files. Purely Swift.
Stars: ✭ 132 (-94.39%)
Mutual labels:  metadata
Beanknife
An annotation processor library to automatically generate the data transfer objects (DTO).
Stars: ✭ 163 (-93.08%)
Mutual labels:  metadata
Metastore
Store and restore metadata from a filesystem.
Stars: ✭ 122 (-94.82%)
Mutual labels:  metadata
Pycsw
pycsw is an OGC CSW server implementation written in Python. pycsw fully implements the OpenGIS Catalogue Service Implementation Specification [Catalogue Service for the Web]. Initial development started in 2010 (more formally announced in 2011). The project is certified OGC Compliant, and is an OGC Reference Implementation. pycsw allows for the publishing and discovery of geospatial metadata via numerous APIs (CSW 2/CSW 3, OpenSearch, OAI-PMH, SRU). Existing repositories of geospatial metadata can also be exposed, providing a standards-based metadata and catalogue component of spatial data infrastructures. pycsw is Open Source, released under an MIT license, and runs on all major platforms (Windows, Linux, Mac OS X). Please read the docs at https://pycsw.org/docs for more information.
Stars: ✭ 141 (-94.01%)
Mutual labels:  metadata
Dynamicswebapi
DynamicsWebApi is a Microsoft Dynamics 365 / Microsoft Dataverse (formerly known as Common Data Service) Web API helper library for JavaScript
Stars: ✭ 165 (-92.99%)
Mutual labels:  metadata
Evolutility Ui Jquery
Model-driven Web UI for CRUD using REST or localStorage.
Stars: ✭ 164 (-93.04%)
Mutual labels:  metadata
Awesome Forensicstools
Awesome list of digital forensic tools
Stars: ✭ 120 (-94.9%)
Mutual labels:  metadata

Metadata Reflection API

Installation

npm install reflect-metadata

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
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].