{"id":21872404,"url":"https://github.com/zerkalica/babel-plugin-transform-metadata","last_synced_at":"2025-04-15T00:06:47.051Z","repository":{"id":66328213,"uuid":"58222265","full_name":"zerkalica/babel-plugin-transform-metadata","owner":"zerkalica","description":"Reflection metadata support for classes and functions with flowtype type aliases support","archived":false,"fork":false,"pushed_at":"2017-11-16T10:17:27.000Z","size":159,"stargazers_count":10,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-02T06:36:14.429Z","etag":null,"topics":["babel-plugin","flowtype","metadata","reflection"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zerkalica.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-06T17:03:23.000Z","updated_at":"2020-04-11T10:47:59.000Z","dependencies_parsed_at":"2023-07-25T22:01:04.405Z","dependency_job_id":null,"html_url":"https://github.com/zerkalica/babel-plugin-transform-metadata","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerkalica%2Fbabel-plugin-transform-metadata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerkalica%2Fbabel-plugin-transform-metadata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerkalica%2Fbabel-plugin-transform-metadata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerkalica%2Fbabel-plugin-transform-metadata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zerkalica","download_url":"https://codeload.github.com/zerkalica/babel-plugin-transform-metadata/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654096,"owners_count":21140236,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["babel-plugin","flowtype","metadata","reflection"],"created_at":"2024-11-28T06:20:32.650Z","updated_at":"2025-04-15T00:06:47.014Z","avatar_url":"https://github.com/zerkalica.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# babel-plugin-transform-metadata\n\nStrict, optimized and smart reflection metadata generator for classes and functions from [flowtype](https://flowtype.org) metadata.\n\n-   Supports arrows and function expressions\n-   Metadata provided for array and object-style arguments\n-   Generics and type arguments support\n\n## Examples\n\n### Interface as value\n\nFlowtype and [typescript](https://www.typescriptlang.org/) reflection does not support type annotations as value keys, so we use some trick with typecast.\n\nIn:\n\n```js\n// @flow\n\nimport _ from 'babel-plugin-transform-metadata/_'\n\nclass A {}\n\nexport interface C {\n    a: A;\n}\nclass MyClass {\n    constructor(c: C) {}\n}\n\nconst id = (_: C)\n```\n\nOut:\n\n```js\n'use strict';\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar A = function A() {\n    _classCallCheck(this, A);\n};\n\nvar MyClass = function MyClass(c) {\n    _classCallCheck(this, MyClass);\n};\n\nMyClass.displayName = 'MyClass';\nMyClass._r = [0, ['C']];\n\n\nvar id = 'C';\n```\n\n### Mark function\n\nIn:\n\n```js\n// @flow\n\nfunction fn(a: A) {\n    function fn2(a: A) {\n\n    }\n}\n```\n\nOut:\n\n```js\n\"use strict\";\n\nfunction fn(a) {\n    function fn2(a) {}\n}\nfn.displayName = \"fn\";\nfn._r = [1, [A]];\n```\n\n### Components metadata\n\nIn:\n\n```js\n// @flow\nclass A {}\ninterface State {s: A}\nfunction ComponentD(rec: {p: number}, state: State) {\n    return \u003cdiv\u003eAA\u003c/div\u003e\n}\n```\n\nOut:\n\n```js\n\nfunction A() {}\n\nfunction ComponentD(rec, state, createVNode) {\n    return createVNode(2, 'div', null, 'AA');\n}\n\nComponentD.displayName = 'ComponentD';\nComponentD._r1 = [{\n    s: A\n}];\n```\n\n### Type parameters\nIn example below, ISource and IStatus to ids mappings are configured in .babelrc.\nOnly first type parameter used.\n\nIn:\n\n```js\n// @flow\ntype ResultOf\u003cF\u003e = _ResultOf\u003c*, F\u003e\ntype _ResultOf\u003cV, F: (...x: any[]) =\u003e V\u003e = V\n\nfunction fn(a: A, b: Class\u003cB\u003e, f: ResultOf\u003ctypeof factory\u003e, sA: ISource\u003cA\u003e, saf: IStatus\u003cA | B\u003e) {\n    function fn2(a: A) {\n    }\n}\n```\n\nOut:\n\n```js\n'use strict';\n\nfunction fn(a, b, f, sA, saf) {\n    function fn2(a) {}\n}\n\nfn.displayName = 'fn';\nfn._r3 = 'babel-plugin-transform-metadata/src/__tests__/data/AllFeatures.js';\nfn._r2 = 2;\nfn._r1 = [A, B, factory, {\n    _r4: 1,\n    v: [A]\n}, {\n    _r4: 2,\n    v: [A, B]\n}];\n```\n\nFor more examples see ``` ./src/__tests__/data ```\n\n\n## Metadata\n\nTo each function plugin adds following metadata:\n\n```js\n\n  /**\n   * Class constructor or function argument\n   */\n  type IArg = IFunction | {\n\n    /**\n     * User defined interface id, see markGenerics\n     */\n    _r4: number;\n    /**\n     * Type arguments\n     */\n    v: IFunction[];\n  }\n\n  /**\n   * Each function or class constructor\n   */\n  interface IFunction {\n    (...args: any[]): any;\n    /**\n     * constructor/function arguments list\n     */\n    _r1?: IArg[];\n\n    /**\n     * bit flags: 1 - jsx, 2 - fn\n     */\n    _r2?: number;\n\n    /**\n     * relative filePath for hmr and debugging\n     */\n    _r3?: string;\n  }\n```\n\n## .babelrc options\n\nAdd before babel-plugin-transform-decorators-legacy and other transformation plugins.\n\n```js\ninterface IOptions {\n   /**\n    * if true - add metadata only to exported function/classes\n    */\n    onlyExports?: boolean;\n\n    /**\n     * if true - add file path to each exported class or function for hot reloading\n     */\n    addFileName?: boolean;\n\n    /**\n     * if true - add function/class name to each exported class or function\n     */\n    addDisplayName?: boolean;\n\n    /**\n     * how to generate interface name tokens:\n     * fullPath - type name + crc(file with type path), typeName - type name only\n     */\n    typeNameStrategy?: 'typeName' | 'fullPath';\n\n    /**\n     * createElement/createVNode factory name, used for [reactive-di](https://github.com/zerkalica/reactive-di) components\n     */\n    jsxPragma?: string;\n\n    /**\n     * Interface to ids mappings: {'ISource': 1, 'IStatus': 2}\n     */\n    markGenerics?: {[id: string]: number};\n}\n```\n\nExample .babelrc:\n\n```json\n{\n    \"plugins\": [\n        \"syntax-flow\",\n        \"transform-decorators-legacy\",\n        [\"transform-metadata\", {\n            \"addFilename\": true,\n            \"onlyExports\": false,\n            \"markGenerics\": {\"ISource\": 1, \"IStatus\": 2},\n            \"typeNameStrategy\": \"typeName\",\n            \"jsxPragma\": \"createVNode\"\n        }]\n    ]\n}\n```\n\n## Restrictions\n\nFor interface-based metadata we need to convert types to unique string tokens, something like this:\n\n```js\nimport type {T} from './types'\n\nfunction test(t: T) {}\nReflection.defineMetadata(['T.types'], T)\n```\n\nJS module import subsystem is poor and nothing is doing in ES standarts for improving it. It's no clean way to identify imported interface in babel plugin, if import path is relative:\n\nTypes are same, but import paths is different:\n\n```js\nimport type {T} from './types'\nimport type {T} from '../data/types'\n```\n\nIdeally, set \"typeNameStrategy\": \"fullPath\" and always use absolute path for types via name_mapper in .flowconfig:\n\n```ini\nmodule.name_mapper='^babel-plugin-transform-metadata/i/\\(.*\\)' -\u003e '\u003cPROJECT_ROOT\u003e/i/\\1'\n```\n\n```js\nimport type {T} from 'babel-plugin-transform-metadata/i/types'\nimport type {R} from './internalTypes'\n\nfunction test(t: T, r: R) {}\nReflection.defineMetadata(['T.crc1', 'R.crc2'], test)\n// where crc1 is crc32('babel-plugin-transform-metadata/i/types')\n// where crc2 is crc32('internalTypes')\n```\n\nRelative paths supported, but some collisions possible, if types with equal names are defined in different files with equal names:\n\n```js\nimport type {T} from '../t2/internalTypes'\nimport type {T} from '../t1/internalTypes'\n```\n\nIf \"typeNameStrategy\" is \"fullPath\", types always will be placed in separate files to avoid collisions like this:\n\n```js\n// t1.js\nexport type T = {\n    some: string;\n}\n\nfunction test(t: T) {}\nReflection.defineMetadata(['T'], test)\n```\n\n```js\n// t2.js\nimport type {T} from './t2'\n\nfunction test2(t: T) {}\nReflection.defineMetadata(['T.t2'], test2)\n```\n\nIf \"typeNameStrategy\" is \"typeName\", import paths will be ignored. But possible collisions with equal type names in different files.\n\n## Credits\n\n[babel-plugin-angular2-annotations](https://github.com/shuhei/babel-plugin-angular2-annotations)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerkalica%2Fbabel-plugin-transform-metadata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzerkalica%2Fbabel-plugin-transform-metadata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerkalica%2Fbabel-plugin-transform-metadata/lists"}