├── .gitignore ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── README.md ├── _config.yml ├── demo ├── index-es6.js ├── index.js └── inject.js ├── eslint.config.mjs ├── lib ├── facade │ ├── errors.ts │ ├── lang.ts │ └── type.ts ├── forward_ref.ts ├── index.ts ├── injection_token.ts ├── injector.ts ├── injector_compatibility.ts ├── metadata.ts ├── provider.ts ├── reflection │ ├── platform_reflection_capabilities.ts │ ├── reflection.ts │ ├── reflection_capabilities.ts │ ├── reflector.ts │ ├── reflector_reader.ts │ └── types.ts ├── reflective_errors.ts ├── reflective_injector.ts ├── reflective_key.ts ├── reflective_provider.ts └── util │ ├── decorators.ts │ └── resolve_dependencies.ts ├── package.json ├── rollup.config.js ├── spec └── support │ └── jasmine.json ├── test ├── forward_ref_spec.ts ├── injector_spec.ts ├── reflective_injector_spec.ts ├── reflective_key_spec.ts └── resolve_dependencies_spec.ts ├── tools ├── copy.js └── tsconfig.json ├── tsconfig-es2015.test.json ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | typings 30 | dist 31 | .vscode 32 | 33 | demo/dist 34 | demo/vendor 35 | .idea 36 | dist-test 37 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | dist-test 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "printWidth": 140, 4 | "trailingComma": "es5", 5 | "singleQuote": true, 6 | "useTabs": false, 7 | "bracketSpacing": true 8 | } 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: stable 3 | 4 | sudo: false 5 | 6 | install: true 7 | 8 | os: 9 | - linux 10 | 11 | before_script: 12 | - npm install 13 | 14 | script: 15 | - npm run build 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Downloads](https://img.shields.io/npm/dm/injection-js.svg) 2 | 3 | # Dependency Injection 4 | 5 | Dependency injection library for JavaScript and TypeScript in **5.2K**. It is an extraction of the Angular's dependency injection which means that it's feature complete, fast, reliable and well tested. 6 | 7 | # Why not Angular version 5 and above? 8 | 9 | Angular version 5 deprecated the `ReflectiveInjector` API and introduced `StaticInjector`. In short, the dependency injection in the newest versions of Angular will happen entirely compile-time so reflection will not be necessary. 10 | 11 | However, if you want to use dependency injection in your Node.js, Vue, React, Vanilla JS, TypeScript, etc. application you won't be able to take advantage of `StaticInjector` the way that Angular will because your application won't be compatible with Angular compiler. 12 | 13 | This means that **if you need dependency injection outside of Angular `@angular/core` is not an option. In such case, use `injection-js` for fast, small, reliable, high-quality, well designed and well tested solution.** 14 | 15 | # How to use? 16 | 17 | ```sh 18 | $ npm i injection-js 19 | # OR 20 | $ yarn add injection-js 21 | ``` 22 | 23 | > **Note:** 24 | > 25 | > For ES5 `Class` syntax and TypeScript you need a polyfill for the [Reflect API](http://www.ecma-international.org/ecma-262/6.0/#sec-reflection). 26 | > You can use: 27 | > 28 | > - [reflection](https://www.npmjs.com/package/@abraham/reflection) (only 3kb 🔥) 29 | > - [reflect-metadata](https://www.npmjs.com/package/reflect-metadata) 30 | > - [core-js (`core-js/es7/reflect`)](https://www.npmjs.com/package/core-js) 31 | > 32 | > Also for TypeScript you will need to enable `experimentalDecorators` and `emitDecoratorMetadata` flags within your `tsconfig.json` 33 | 34 | ## TypeScript 35 | 36 | Using the latest `inject` function: 37 | 38 | ```ts 39 | import { inject, ReflectiveInjector } from 'injection-js'; 40 | 41 | class Http {} 42 | 43 | class Service { 44 | http = inject(Http); 45 | } 46 | 47 | const injector = ReflectiveInjector.resolveAndCreate([Http, Service]); 48 | 49 | console.log(injector.get(Service) instanceof Service); 50 | console.log(injector.get(Service).http instanceof Http); 51 | ``` 52 | 53 | Using `@Injectable` and `reflect-metadata`: 54 | 55 | ```ts 56 | import 'reflect-metadata'; 57 | import { ReflectiveInjector, Injectable, Injector } from 'injection-js'; 58 | 59 | class Http {} 60 | 61 | @Injectable() 62 | class Service { 63 | constructor(private http: Http) {} 64 | } 65 | 66 | @Injectable() 67 | class Service2 { 68 | constructor(private injector: Injector) {} 69 | 70 | getService(): void { 71 | console.log(this.injector.get(Service) instanceof Service); 72 | } 73 | 74 | createChildInjector(): void { 75 | const childInjector = ReflectiveInjector.resolveAndCreate([Service], this.injector); 76 | } 77 | } 78 | 79 | const injector = ReflectiveInjector.resolveAndCreate([Service, Http]); 80 | 81 | console.log(injector.get(Service) instanceof Service); 82 | ``` 83 | 84 | ## ES6 85 | 86 | ```js 87 | const { Inject, ReflectiveInjector } = require('injection-js'); 88 | 89 | class Http {} 90 | 91 | class Service { 92 | static get parameters() { 93 | return [new Inject(Http)]; 94 | } 95 | 96 | constructor(http) { 97 | this.http = http; 98 | } 99 | } 100 | 101 | const injector = ReflectiveInjector.resolveAndCreate([Http, Service]); 102 | 103 | console.log(injector.get(Service) instanceof Service); 104 | ``` 105 | 106 | ## ES5 107 | 108 | ```js 109 | require('reflect-metadata'); 110 | var di = require('injection-js'); 111 | 112 | var Http = di.Class({ 113 | constructor: function() {}, 114 | }); 115 | 116 | var Service = di.Class({ 117 | constructor: [ 118 | Http, 119 | function(http) { 120 | this.http = http; 121 | }, 122 | ], 123 | }); 124 | 125 | var injector = di.ReflectiveInjector.resolveAndCreate([Http, Service]); 126 | 127 | console.log(injector.get(Service) instanceof Service); 128 | ``` 129 | 130 | # API 131 | 132 | For full documentation check Angular DI docs: 133 | 134 | - [Dependency Injection](https://v4.angular.io/guide/dependency-injection) 135 | - [Dependency Injection in action](https://v4.angular.io/guide/dependency-injection-in-action) 136 | - [Dependency Injection without Typescript](https://v2.angular.io/docs/ts/latest/cookbook/ts-to-js.html#!#dependency-injection) 137 | 138 | # Ecosystem 139 | 140 | This is a list of libraries that are using injection-js. If you have a suggestion on what to add, please don't hesitate to submit a PR. 141 | 142 | ## Libraries 143 | 144 | - [ng-packagr](https://github.com/ng-packagr/ng-packagr) Transpile your libraries to Angular Package Format. Part of the official Angular CLI. 145 | - [@martin_hotell/axios-http](https://github.com/Hotell/axios-http) Injectable axios HttpClient wrapper for browser and node 146 | - [@martin_hotell/rea-di](https://github.com/Hotell/rea-di) Dependency injection for React done right. Hierarchical injection on both component and service layer powered by injection-js (Angular DI framework) 🖖 147 | - [rxstack](https://github.com/rxstack/rxstack) RxStack is a realtime object-oriented framework which helps you build a micro service web applications on top of other frameworks like express and socketio by adding an abstraction layer. 148 | - [ServeRX-ts](https://github.com/mflorence99/serverx-ts) Experimental [Node.js](https://nodejs.org) HTTP framework using [RxJS](https://rxjs.dev), built with [TypeScript](https://www.typescriptlang.org/) and optimized for serverless deployments. Features declarative routes and dependency injection powered by injection-js. 149 | 150 | # License 151 | 152 | MIT 153 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /demo/index-es6.js: -------------------------------------------------------------------------------- 1 | const { Inject, ReflectiveInjector } = require('../dist'); 2 | 3 | class Http {} 4 | 5 | class Service { 6 | static get parameters() { 7 | return [[new Inject(Http)]]; 8 | } 9 | 10 | constructor(http) { 11 | this.http = http; 12 | } 13 | } 14 | 15 | const injector = ReflectiveInjector.resolveAndCreate([Http, Service]); 16 | 17 | console.log(injector.get(Service) instanceof Service); 18 | -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | require('reflect-metadata'); 2 | var di = require('../dist/injection.bundle'); 3 | 4 | var Http = di.Class({ 5 | constructor: function() {}, 6 | }); 7 | 8 | var Service = di.Class({ 9 | constructor: [ 10 | Http, 11 | function(http) { 12 | this.http = http; 13 | }, 14 | ], 15 | }); 16 | 17 | var injector = di.ReflectiveInjector.resolveAndCreate([Http, Service]); 18 | 19 | console.log(injector.get(Service) instanceof Service); 20 | -------------------------------------------------------------------------------- /demo/inject.js: -------------------------------------------------------------------------------- 1 | const { inject, ReflectiveInjector } = require('../dist'); 2 | 3 | class Http {} 4 | 5 | class Service { 6 | http = inject(Http); 7 | } 8 | 9 | const injector = ReflectiveInjector.resolveAndCreate([Http, Service]); 10 | 11 | console.log(injector.get(Service) instanceof Service); 12 | console.log(injector.get(Service).http instanceof Http); 13 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'eslint/config'; 2 | import typescriptEslint from '@typescript-eslint/eslint-plugin'; 3 | import globals from 'globals'; 4 | import tsParser from '@typescript-eslint/parser'; 5 | import path from 'node:path'; 6 | import { fileURLToPath } from 'node:url'; 7 | import js from '@eslint/js'; 8 | import { FlatCompat } from '@eslint/eslintrc'; 9 | 10 | const __filename = fileURLToPath(import.meta.url); 11 | const __dirname = path.dirname(__filename); 12 | const compat = new FlatCompat({ 13 | baseDirectory: __dirname, 14 | recommendedConfig: js.configs.recommended, 15 | allConfig: js.configs.all, 16 | }); 17 | 18 | export default defineConfig([ 19 | { 20 | extends: compat.extends('prettier', 'plugin:prettier/recommended', 'eslint:recommended', 'plugin:@typescript-eslint/recommended'), 21 | 22 | plugins: { 23 | '@typescript-eslint': typescriptEslint, 24 | }, 25 | 26 | languageOptions: { 27 | globals: { 28 | ...globals.browser, 29 | ...globals.node, 30 | }, 31 | 32 | parser: tsParser, 33 | ecmaVersion: 5, 34 | sourceType: 'module', 35 | 36 | parserOptions: { 37 | project: 'tsconfig-es2015.test.json', 38 | createDefaultProgram: true, 39 | }, 40 | }, 41 | 42 | rules: { 43 | 'no-prototype-builtins': 'off', 44 | '@typescript-eslint/ban-types': 'off', 45 | '@typescript-eslint/no-this-alias': 'off', 46 | '@typescript-eslint/no-explicit-any': 'off', 47 | '@typescript-eslint/no-empty-interface': 'off', 48 | '@typescript-eslint/no-non-null-assertion': 'off', 49 | '@typescript-eslint/no-unused-vars': 'off', 50 | '@typescript-eslint/no-unsafe-function-type': 'off', 51 | }, 52 | }, 53 | { 54 | files: ['test/**/*.ts'], 55 | 56 | rules: { 57 | '@typescript-eslint/no-empty-function': 'off', 58 | }, 59 | }, 60 | ]); 61 | -------------------------------------------------------------------------------- /lib/facade/errors.ts: -------------------------------------------------------------------------------- 1 | import { DebugContext } from './lang'; 2 | 3 | /** 4 | * @license 5 | * Copyright Google Inc. All Rights Reserved. 6 | * 7 | * Use of this source code is governed by an MIT-style license that can be 8 | * found in the LICENSE file at https://angular.io/license 9 | */ 10 | 11 | export const ERROR_TYPE = 'ngType'; 12 | export const ERROR_COMPONENT_TYPE = 'ngComponentType'; 13 | export const ERROR_DEBUG_CONTEXT = 'ngDebugContext'; 14 | export const ERROR_ORIGINAL_ERROR = 'ngOriginalError'; 15 | export const ERROR_LOGGER = 'ngErrorLogger'; 16 | 17 | export function getType(error: Error): Function { 18 | return (error as any)[ERROR_TYPE]; 19 | } 20 | 21 | export function getDebugContext(error: Error): DebugContext { 22 | return (error as any)[ERROR_DEBUG_CONTEXT]; 23 | } 24 | 25 | export function getOriginalError(error: Error): Error { 26 | return (error as any)[ERROR_ORIGINAL_ERROR]; 27 | } 28 | 29 | function defaultErrorLogger(console: Console, ...values: any[]) { 30 | (console.error)(...values); 31 | } 32 | 33 | export function getErrorLogger(error: Error): (console: Console, ...values: any[]) => void { 34 | return (error as any)[ERROR_LOGGER] || defaultErrorLogger; 35 | } 36 | 37 | export function wrappedError(message: string, originalError: any): Error { 38 | const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`; 39 | const error = Error(msg); 40 | (error as any)[ERROR_ORIGINAL_ERROR] = originalError; 41 | return error; 42 | } 43 | -------------------------------------------------------------------------------- /lib/facade/lang.ts: -------------------------------------------------------------------------------- 1 | import { Injector } from '../injector'; 2 | /** 3 | * @license 4 | * Copyright Google Inc. All Rights Reserved. 5 | * 6 | * Use of this source code is governed by an MIT-style license that can be 7 | * found in the LICENSE file at https://angular.io/license 8 | */ 9 | 10 | export interface BrowserNodeGlobal { 11 | Object: typeof Object; 12 | Array: typeof Array; 13 | Map: typeof Map; 14 | Set: typeof Set; 15 | Date: DateConstructor; 16 | RegExp: RegExpConstructor; 17 | JSON: typeof JSON; 18 | Math: any; // typeof Math; 19 | assert(condition: any): void; 20 | Reflect: any; 21 | getAngularTestability: Function; 22 | getAllAngularTestabilities: Function; 23 | getAllAngularRootElements: Function; 24 | frameworkStabilizers: Array; 25 | setTimeout: Function; 26 | clearTimeout: Function; 27 | setInterval: Function; 28 | clearInterval: Function; 29 | encodeURI: Function; 30 | } 31 | 32 | // TODO(jteplitz602): Load WorkerGlobalScope from lib.webworker.d.ts file #3492 33 | declare let WorkerGlobalScope: any /** TODO #9100 */; 34 | // CommonJS / Node have global context exposed as "global" variable. 35 | // We don't want to include the whole node.d.ts this this compilation unit so we'll just fake 36 | // the global "global" var for now. 37 | declare let global: any /** TODO #9100 */; 38 | 39 | let globalScope: BrowserNodeGlobal; 40 | if (typeof window === 'undefined') { 41 | if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) { 42 | // TODO: Replace any with WorkerGlobalScope from lib.webworker.d.ts #3492 43 | globalScope = self; 44 | } else { 45 | globalScope = global; 46 | } 47 | } else { 48 | globalScope = window; 49 | } 50 | 51 | // Need to declare a new variable for global here since TypeScript 52 | // exports the original value of the symbol. 53 | const _global: BrowserNodeGlobal = globalScope; 54 | 55 | export { _global as global }; 56 | 57 | export function isPresent(obj: T): obj is NonNullable { 58 | return obj != null; 59 | } 60 | 61 | export function stringify(token: any): string { 62 | if (typeof token === 'string') { 63 | return token; 64 | } 65 | 66 | if (token == null) { 67 | return '' + token; 68 | } 69 | 70 | if (token.overriddenName) { 71 | return `${token.overriddenName}`; 72 | } 73 | 74 | if (token.name) { 75 | return `${token.name}`; 76 | } 77 | 78 | const res = token.toString(); 79 | const newLineIndex = res.indexOf('\n'); 80 | return newLineIndex === -1 ? res : res.substring(0, newLineIndex); 81 | } 82 | 83 | export abstract class DebugContext { 84 | // We don't really need this 85 | // abstract get view(): ViewData; 86 | abstract get nodeIndex(): number | null; 87 | abstract get injector(): Injector; 88 | abstract get component(): any; 89 | abstract get providerTokens(): any[]; 90 | abstract get references(): { [key: string]: any }; 91 | abstract get context(): any; 92 | abstract get componentRenderElement(): any; 93 | abstract get renderNode(): any; 94 | abstract logError(console: Console, ...values: any[]): void; 95 | } 96 | -------------------------------------------------------------------------------- /lib/facade/type.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | /** 10 | * @whatItDoes Represents a type that a Component or other object is instances of. 11 | * 12 | * @description 13 | * 14 | * An example of a `Type` is `MyCustomComponent` class, which in JavaScript is be represented by 15 | * the `MyCustomComponent` constructor function. 16 | * 17 | * @stable 18 | */ 19 | export const Type = Function; 20 | 21 | export function isType(v: any): v is Type { 22 | return typeof v === 'function'; 23 | } 24 | 25 | export interface Type extends Function { 26 | new (...args: any[]): T; 27 | } 28 | -------------------------------------------------------------------------------- /lib/forward_ref.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { stringify } from './facade/lang'; 10 | import { Type } from './facade/type'; 11 | 12 | /** 13 | * An interface that a function passed into {@link forwardRef} has to implement. 14 | * 15 | * ### Example 16 | * 17 | * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='forward_ref_fn'} 18 | * @experimental 19 | */ 20 | export interface ForwardRefFn { 21 | (): any; 22 | } 23 | 24 | /** 25 | * Allows to refer to references which are not yet defined. 26 | * 27 | * For instance, `forwardRef` is used when the `token` which we need to refer to for the purposes of 28 | * DI is declared, 29 | * but not yet defined. It is also used when the `token` which we use when creating a query is not 30 | * yet defined. 31 | * 32 | * ### Example 33 | * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='forward_ref'} 34 | * @experimental 35 | */ 36 | export function forwardRef(forwardRefFn: ForwardRefFn): Type { 37 | (forwardRefFn).__forward_ref__ = forwardRef; 38 | (forwardRefFn).toString = function () { 39 | return stringify(this()); 40 | }; 41 | return >(forwardRefFn); 42 | } 43 | 44 | /** 45 | * Lazily retrieves the reference value from a forwardRef. 46 | * 47 | * Acts as the identity function when given a non-forward-ref value. 48 | * 49 | * ### Example ([live demo](http://plnkr.co/edit/GU72mJrk1fiodChcmiDR?p=preview)) 50 | * 51 | * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='resolve_forward_ref'} 52 | * 53 | * See: {@link forwardRef} 54 | * @experimental 55 | */ 56 | export function resolveForwardRef(type: any): any { 57 | if (typeof type === 'function' && type.hasOwnProperty('__forward_ref__') && type.__forward_ref__ === forwardRef) { 58 | return (type as ForwardRefFn)(); 59 | } else { 60 | return type; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | /** 10 | * @module 11 | * @description 12 | * The `di` module provides dependency injection container services. 13 | */ 14 | 15 | export * from './metadata'; 16 | 17 | export { forwardRef, resolveForwardRef, ForwardRefFn } from './forward_ref'; 18 | 19 | export { Injector } from './injector'; 20 | export { ReflectiveInjector } from './reflective_injector'; 21 | export { Provider, TypeProvider, ValueProvider, ClassProvider, ExistingProvider, FactoryProvider } from './provider'; 22 | export { ResolvedReflectiveFactory, ResolvedReflectiveProvider } from './reflective_provider'; 23 | export { ReflectiveKey } from './reflective_key'; 24 | export { InjectionToken, OpaqueToken } from './injection_token'; 25 | export { Class, TypeDecorator, makeDecorator, makeParamDecorator, makePropDecorator } from './util/decorators'; 26 | export { resolveDependencies } from './util/resolve_dependencies'; 27 | export { Type, isType } from './facade/type'; 28 | export { inject } from './injector_compatibility'; 29 | -------------------------------------------------------------------------------- /lib/injection_token.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | /** 10 | * Creates a token that can be used in a DI Provider. 11 | * 12 | * ### Example ([live demo](http://plnkr.co/edit/Ys9ezXpj2Mnoy3Uc8KBp?p=preview)) 13 | * 14 | * ```typescript 15 | * var t = new OpaqueToken("value"); 16 | * 17 | * var injector = Injector.resolveAndCreate([ 18 | * {provide: t, useValue: "bindingValue"} 19 | * ]); 20 | * 21 | * expect(injector.get(t)).toEqual("bindingValue"); 22 | * ``` 23 | * 24 | * Using an `OpaqueToken` is preferable to using strings as tokens because of possible collisions 25 | * caused by multiple providers using the same string as two different tokens. 26 | * 27 | * Using an `OpaqueToken` is preferable to using an `Object` as tokens because it provides better 28 | * error messages. 29 | * @deprecated since v4.0.0 because it does not support type information, use `InjectionToken` 30 | * instead. 31 | */ 32 | export class OpaqueToken { 33 | constructor(protected _desc: string) {} 34 | 35 | toString(): string { 36 | return `Token ${this._desc}`; 37 | } 38 | } 39 | 40 | /** 41 | * Creates a token that can be used in a DI Provider. 42 | * 43 | * Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a 44 | * runtime representation) such as when injecting an interface, callable type, array or 45 | * parametrized type. 46 | * 47 | * `InjectionToken` is parameterized on `T` which is the type of object which will be returned by 48 | * the `Injector`. This provides additional level of type safety. 49 | * 50 | * ``` 51 | * interface MyInterface {...} 52 | * var myInterface = injector.get(new InjectionToken('SomeToken')); 53 | * // myInterface is inferred to be MyInterface. 54 | * ``` 55 | * 56 | * ### Example 57 | * 58 | * {@example core/di/ts/injector_spec.ts region='InjectionToken'} 59 | * 60 | * @stable 61 | */ 62 | export class InjectionToken extends OpaqueToken { 63 | // This unused property is needed here so that TS can differentiate InjectionToken from 64 | // OpaqueToken since otherwise they would have the same shape and be treated as equivalent. 65 | private _differentiate_from_OpaqueToken_structurally: any; 66 | constructor(desc: string) { 67 | super(desc); 68 | } 69 | 70 | toString(): string { 71 | return `InjectionToken ${this._desc}`; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/injector.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { stringify } from './facade/lang'; 10 | import { Type } from './facade/type'; 11 | 12 | import { InjectionToken } from './injection_token'; 13 | 14 | const _THROW_IF_NOT_FOUND = new Object(); 15 | export const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND; 16 | 17 | // tslint:disable-next-line:class-name no-use-before-declare 18 | class _NullInjector implements Injector { 19 | get(token: any, notFoundValue: any = _THROW_IF_NOT_FOUND): any { 20 | if (notFoundValue === _THROW_IF_NOT_FOUND) { 21 | throw new Error(`No provider for ${stringify(token)}!`); 22 | } 23 | return notFoundValue; 24 | } 25 | } 26 | 27 | /** 28 | * @whatItDoes Injector interface 29 | * @howToUse 30 | * ``` 31 | * const injector: Injector = ...; 32 | * injector.get(...); 33 | * ``` 34 | * 35 | * @description 36 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 37 | * 38 | * ### Example 39 | * 40 | * {@example core/di/ts/injector_spec.ts region='Injector'} 41 | * 42 | * `Injector` returns itself when given `Injector` as a token: 43 | * {@example core/di/ts/injector_spec.ts region='injectInjector'} 44 | * 45 | * @stable 46 | */ 47 | export abstract class Injector { 48 | static THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND; 49 | static NULL: Injector = new _NullInjector(); 50 | 51 | /** 52 | * Retrieves an instance from the injector based on the provided token. 53 | * If not found: 54 | * - Throws {@link NoProviderError} if no `notFoundValue` that is not equal to 55 | * Injector.THROW_IF_NOT_FOUND is given 56 | * - Returns the `notFoundValue` otherwise 57 | */ 58 | abstract get(token: Type | InjectionToken, notFoundValue?: T): T; 59 | /** 60 | * @deprecated from v4.0.0 use Type or InjectionToken 61 | * @suppress {duplicate} 62 | */ 63 | abstract get(token: any, notFoundValue?: any): any; 64 | } 65 | -------------------------------------------------------------------------------- /lib/injector_compatibility.ts: -------------------------------------------------------------------------------- 1 | import { Type } from "./facade/type"; 2 | import { InjectionToken } from "./injection_token"; 3 | import { Injector } from "./injector"; 4 | 5 | 6 | /** 7 | * Current injector value used by `inject`. 8 | * - `undefined`: it is an error to call `inject` 9 | * - Injector instance: Use the injector for resolution. 10 | */ 11 | let _currentInjector: Injector | undefined = undefined; 12 | 13 | export function getCurrentInjector(): Injector | undefined { 14 | return _currentInjector; 15 | } 16 | 17 | 18 | export function setCurrentInjector( 19 | injector: Injector | undefined, 20 | ): Injector | undefined { 21 | const former = _currentInjector; 22 | _currentInjector = injector; 23 | return former; 24 | } 25 | 26 | 27 | export function inject(token: Type | InjectionToken): T { 28 | if (_currentInjector === undefined) { 29 | throw new Error( 30 | `inject() must be called from an injection context such as a constructor, a factory function, or a field initializer`, 31 | ); 32 | } else { 33 | const value = _currentInjector.get(token); 34 | return value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/metadata.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { makeDecorator, makeParamDecorator } from './util/decorators'; 10 | 11 | /** 12 | * Type of the Inject decorator / constructor function. 13 | * 14 | * @stable 15 | */ 16 | export interface InjectDecorator { 17 | /** 18 | * @whatItDoes A parameter decorator that specifies a dependency. 19 | * @howToUse 20 | * ``` 21 | * @Injectable() 22 | * class Car { 23 | * constructor(@Inject("MyEngine") public engine:Engine) {} 24 | * } 25 | * ``` 26 | * 27 | * @description 28 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 29 | * 30 | * ### Example 31 | * 32 | * {@example core/di/ts/metadata_spec.ts region='Inject'} 33 | * 34 | * When `@Inject()` is not present, {@link Injector} will use the type annotation of the 35 | * parameter. 36 | * 37 | * ### Example 38 | * 39 | * {@example core/di/ts/metadata_spec.ts region='InjectWithoutDecorator'} 40 | * 41 | * @stable 42 | */ 43 | (token: any): any; 44 | new (token: any): Inject; 45 | } 46 | 47 | /** 48 | * Type of the Inject metadata. 49 | * 50 | * @stable 51 | */ 52 | export interface Inject { 53 | token: any; 54 | } 55 | 56 | /** 57 | * Inject decorator and metadata. 58 | * 59 | * @stable 60 | * @Annotation 61 | */ 62 | export const Inject: InjectDecorator = makeParamDecorator('Inject', [['token', undefined]]); 63 | 64 | /** 65 | * Type of the Optional decorator / constructor function. 66 | * 67 | * @stable 68 | */ 69 | export interface OptionalDecorator { 70 | /** 71 | * @whatItDoes A parameter metadata that marks a dependency as optional. 72 | * {@link Injector} provides `null` if the dependency is not found. 73 | * @howToUse 74 | * ``` 75 | * @Injectable() 76 | * class Car { 77 | * constructor(@Optional() public engine:Engine) {} 78 | * } 79 | * ``` 80 | * 81 | * @description 82 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 83 | * 84 | * ### Example 85 | * 86 | * {@example core/di/ts/metadata_spec.ts region='Optional'} 87 | * 88 | * @stable 89 | */ 90 | (): any; 91 | new (): Optional; 92 | } 93 | 94 | /** 95 | * Type of the Optional metadata. 96 | * 97 | * @stable 98 | */ 99 | export interface Optional {} 100 | 101 | /** 102 | * Optional decorator and metadata. 103 | * 104 | * @stable 105 | * @Annotation 106 | */ 107 | export const Optional: OptionalDecorator = makeParamDecorator('Optional', []); 108 | 109 | /** 110 | * Type of the Injectable decorator / constructor function. 111 | * 112 | * @stable 113 | */ 114 | export interface InjectableDecorator { 115 | /** 116 | * @whatItDoes A marker metadata that marks a class as available to {@link Injector} for creation. 117 | * @howToUse 118 | * ``` 119 | * @Injectable() 120 | * class Car {} 121 | * ``` 122 | * 123 | * @description 124 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 125 | * 126 | * ### Example 127 | * 128 | * {@example core/di/ts/metadata_spec.ts region='Injectable'} 129 | * 130 | * {@link Injector} will throw {@link NoAnnotationError} when trying to instantiate a class that 131 | * does not have `@Injectable` marker, as shown in the example below. 132 | * 133 | * {@example core/di/ts/metadata_spec.ts region='InjectableThrows'} 134 | * 135 | * @stable 136 | */ 137 | (): any; 138 | new (): Injectable; 139 | } 140 | 141 | /** 142 | * Type of the Injectable metadata. 143 | * 144 | * @stable 145 | */ 146 | export interface Injectable {} 147 | 148 | /** 149 | * Injectable decorator and metadata. 150 | * 151 | * @stable 152 | * @Annotation 153 | */ 154 | export const Injectable: InjectableDecorator = makeDecorator('Injectable', []); 155 | 156 | /** 157 | * Type of the Self decorator / constructor function. 158 | * 159 | * @stable 160 | */ 161 | export interface SelfDecorator { 162 | /** 163 | * @whatItDoes Specifies that an {@link Injector} should retrieve a dependency only from itself. 164 | * @howToUse 165 | * ``` 166 | * @Injectable() 167 | * class Car { 168 | * constructor(@Self() public engine:Engine) {} 169 | * } 170 | * ``` 171 | * 172 | * @description 173 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 174 | * 175 | * ### Example 176 | * 177 | * {@example core/di/ts/metadata_spec.ts region='Self'} 178 | * 179 | * @stable 180 | */ 181 | (): any; 182 | new (): Self; 183 | } 184 | 185 | /** 186 | * Type of the Self metadata. 187 | * 188 | * @stable 189 | */ 190 | export interface Self {} 191 | 192 | /** 193 | * Self decorator and metadata. 194 | * 195 | * @stable 196 | * @Annotation 197 | */ 198 | export const Self: SelfDecorator = makeParamDecorator('Self', []); 199 | 200 | /** 201 | * Type of the SkipSelf decorator / constructor function. 202 | * 203 | * @stable 204 | */ 205 | export interface SkipSelfDecorator { 206 | /** 207 | * @whatItDoes Specifies that the dependency resolution should start from the parent injector. 208 | * @howToUse 209 | * ``` 210 | * @Injectable() 211 | * class Car { 212 | * constructor(@SkipSelf() public engine:Engine) {} 213 | * } 214 | * ``` 215 | * 216 | * @description 217 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 218 | * 219 | * ### Example 220 | * 221 | * {@example core/di/ts/metadata_spec.ts region='SkipSelf'} 222 | * 223 | * @stable 224 | */ 225 | (): any; 226 | new (): SkipSelf; 227 | } 228 | 229 | /** 230 | * Type of the SkipSelf metadata. 231 | * 232 | * @stable 233 | */ 234 | export interface SkipSelf {} 235 | 236 | /** 237 | * SkipSelf decorator and metadata. 238 | * 239 | * @stable 240 | * @Annotation 241 | */ 242 | export const SkipSelf: SkipSelfDecorator = makeParamDecorator('SkipSelf', []); 243 | 244 | /** 245 | * Type of the Host decorator / constructor function. 246 | * 247 | * @stable 248 | */ 249 | export interface HostDecorator { 250 | /** 251 | * @whatItDoes Specifies that an injector should retrieve a dependency from any injector until 252 | * reaching the host element of the current component. 253 | * @howToUse 254 | * ``` 255 | * @Injectable() 256 | * class Car { 257 | * constructor(@Host() public engine:Engine) {} 258 | * } 259 | * ``` 260 | * 261 | * @description 262 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 263 | * 264 | * ### Example 265 | * 266 | * {@example core/di/ts/metadata_spec.ts region='Host'} 267 | * 268 | * @stable 269 | */ 270 | (): any; 271 | new (): Host; 272 | } 273 | 274 | /** 275 | * Type of the Host metadata. 276 | * 277 | * @stable 278 | */ 279 | export interface Host {} 280 | 281 | /** 282 | * Host decorator and metadata. 283 | * 284 | * @stable 285 | * @Annotation 286 | */ 287 | export const Host: HostDecorator = makeParamDecorator('Host', []); 288 | -------------------------------------------------------------------------------- /lib/provider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { Type } from './facade/type'; 10 | 11 | /** 12 | * @whatItDoes Configures the {@link Injector} to return an instance of `Type` when `Type' is used 13 | * as token. 14 | * @howToUse 15 | * ``` 16 | * @Injectable() 17 | * class MyService {} 18 | * 19 | * const provider: TypeProvider = MyService; 20 | * ``` 21 | * 22 | * @description 23 | * 24 | * Create an instance by invoking the `new` operator and supplying additional arguments. 25 | * This form is a short form of `TypeProvider`; 26 | * 27 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 28 | * 29 | * ### Example 30 | * 31 | * {@example core/di/ts/provider_spec.ts region='TypeProvider'} 32 | * 33 | * @stable 34 | */ 35 | export type TypeProvider = Type; 36 | 37 | /** 38 | * @whatItDoes Configures the {@link Injector} to return a value for a token. 39 | * @howToUse 40 | * ``` 41 | * const provider: ValueProvider = {provide: 'someToken', useValue: 'someValue'}; 42 | * ``` 43 | * 44 | * @description 45 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 46 | * 47 | * ### Example 48 | * 49 | * {@example core/di/ts/provider_spec.ts region='ValueProvider'} 50 | * 51 | * @stable 52 | */ 53 | export interface ValueProvider { 54 | /** 55 | * An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`). 56 | */ 57 | provide: any; 58 | 59 | /** 60 | * The value to inject. 61 | */ 62 | useValue: any; 63 | 64 | /** 65 | * If true, then injector returns an array of instances. This is useful to allow multiple 66 | * providers spread across many files to provide configuration information to a common token. 67 | * 68 | * ### Example 69 | * 70 | * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'} 71 | */ 72 | multi?: boolean; 73 | } 74 | 75 | /** 76 | * @whatItDoes Configures the {@link Injector} to return an instance of `useClass` for a token. 77 | * @howToUse 78 | * ``` 79 | * @Injectable() 80 | * class MyService {} 81 | * 82 | * const provider: ClassProvider = {provide: 'someToken', useClass: MyService}; 83 | * ``` 84 | * 85 | * @description 86 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 87 | * 88 | * ### Example 89 | * 90 | * {@example core/di/ts/provider_spec.ts region='ClassProvider'} 91 | * 92 | * Note that following two providers are not equal: 93 | * {@example core/di/ts/provider_spec.ts region='ClassProviderDifference'} 94 | * 95 | * @stable 96 | */ 97 | export interface ClassProvider { 98 | /** 99 | * An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`). 100 | */ 101 | provide: any; 102 | 103 | /** 104 | * Class to instantiate for the `token`. 105 | */ 106 | useClass: Type; 107 | 108 | /** 109 | * If true, then injector returns an array of instances. This is useful to allow multiple 110 | * providers spread across many files to provide configuration information to a common token. 111 | * 112 | * ### Example 113 | * 114 | * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'} 115 | */ 116 | multi?: boolean; 117 | } 118 | 119 | /** 120 | * @whatItDoes Configures the {@link Injector} to return a value of another `useExisting` token. 121 | * @howToUse 122 | * ``` 123 | * const provider: ExistingProvider = {provide: 'someToken', useExisting: 'someOtherToken'}; 124 | * ``` 125 | * 126 | * @description 127 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 128 | * 129 | * ### Example 130 | * 131 | * {@example core/di/ts/provider_spec.ts region='ExistingProvider'} 132 | * 133 | * @stable 134 | */ 135 | export interface ExistingProvider { 136 | /** 137 | * An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`). 138 | */ 139 | provide: any; 140 | 141 | /** 142 | * Existing `token` to return. (equivalent to `injector.get(useExisting)`) 143 | */ 144 | useExisting: any; 145 | 146 | /** 147 | * If true, then injector returns an array of instances. This is useful to allow multiple 148 | * providers spread across many files to provide configuration information to a common token. 149 | * 150 | * ### Example 151 | * 152 | * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'} 153 | */ 154 | multi?: boolean; 155 | } 156 | 157 | /** 158 | * @whatItDoes Configures the {@link Injector} to return a value by invoking a `useFactory` 159 | * function. 160 | * @howToUse 161 | * ``` 162 | * function serviceFactory() { ... } 163 | * 164 | * const provider: FactoryProvider = {provide: 'someToken', useFactory: serviceFactory, deps: []}; 165 | * ``` 166 | * 167 | * @description 168 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 169 | * 170 | * ### Example 171 | * 172 | * {@example core/di/ts/provider_spec.ts region='FactoryProvider'} 173 | * 174 | * Dependencies can also be marked as optional: 175 | * {@example core/di/ts/provider_spec.ts region='FactoryProviderOptionalDeps'} 176 | * 177 | * @stable 178 | */ 179 | export interface FactoryProvider { 180 | /** 181 | * An injection token. (Typically an instance of `Type` or `InjectionToken`, but can be `any`). 182 | */ 183 | provide: any; 184 | 185 | /** 186 | * A function to invoke to create a value for this `token`. The function is invoked with 187 | * resolved values of `token`s in the `deps` field. 188 | */ 189 | useFactory: Function; 190 | 191 | /** 192 | * A list of `token`s which need to be resolved by the injector. The list of values is then 193 | * used as arguments to the `useFactory` function. 194 | */ 195 | deps?: any[]; 196 | 197 | /** 198 | * If true, then injector returns an array of instances. This is useful to allow multiple 199 | * providers spread across many files to provide configuration information to a common token. 200 | * 201 | * ### Example 202 | * 203 | * {@example core/di/ts/provider_spec.ts region='MultiProviderAspect'} 204 | */ 205 | multi?: boolean; 206 | } 207 | 208 | /** 209 | * @whatItDoes Describes how the {@link Injector} should be configured. 210 | * @howToUse 211 | * See {@link TypeProvider}, {@link ValueProvider}, {@link ClassProvider}, {@link ExistingProvider}, 212 | * {@link FactoryProvider}. 213 | * 214 | * @description 215 | * For more details, see the {@linkDocs guide/dependency-injection "Dependency Injection Guide"}. 216 | * 217 | * @stable 218 | */ 219 | export type Provider = TypeProvider | ValueProvider | ClassProvider | ExistingProvider | FactoryProvider | any[]; 220 | -------------------------------------------------------------------------------- /lib/reflection/platform_reflection_capabilities.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { Type } from '../facade/type'; 10 | import { GetterFn, MethodFn, SetterFn } from './types'; 11 | 12 | export interface PlatformReflectionCapabilities { 13 | isReflectionEnabled(): boolean; 14 | factory(type: Type): Function; 15 | hasLifecycleHook(type: any, lcProperty: string): boolean; 16 | parameters(type: Type): any[][]; 17 | annotations(type: Type): any[]; 18 | propMetadata(typeOrFunc: Type): { [key: string]: any[] }; 19 | getter(name: string): GetterFn; 20 | setter(name: string): SetterFn; 21 | method(name: string): MethodFn; 22 | importUri(type: Type): string; 23 | resourceUri(type: Type): string; 24 | resolveIdentifier(name: string, moduleUrl: string, members: string[] | null, runtime: any): any; 25 | resolveEnum(enumIdentifier: any, name: string): any; 26 | } 27 | -------------------------------------------------------------------------------- /lib/reflection/reflection.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { ReflectionCapabilities } from './reflection_capabilities'; 10 | import { Reflector } from './reflector'; 11 | 12 | export { Reflector } from './reflector'; 13 | 14 | /** 15 | * The {@link Reflector} used internally in Angular to access metadata 16 | * about symbols. 17 | */ 18 | export const reflector = new Reflector(new ReflectionCapabilities()); 19 | -------------------------------------------------------------------------------- /lib/reflection/reflection_capabilities.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { global, isPresent, stringify } from '../facade/lang'; 10 | import { Type, isType } from '../facade/type'; 11 | 12 | import { PlatformReflectionCapabilities } from './platform_reflection_capabilities'; 13 | import { GetterFn, MethodFn, SetterFn } from './types'; 14 | 15 | /** 16 | * Attention: This regex has to hold even if the code is minified! 17 | */ 18 | export const DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*arguments\)/; 19 | 20 | export class ReflectionCapabilities implements PlatformReflectionCapabilities { 21 | private _reflect: any; 22 | 23 | constructor(reflect?: any) { 24 | this._reflect = reflect || global['Reflect']; 25 | } 26 | 27 | isReflectionEnabled(): boolean { 28 | return true; 29 | } 30 | 31 | factory(t: Type): (args: any[]) => T { 32 | return (...args: any[]) => new t(...args); 33 | } 34 | 35 | /** @internal */ 36 | _zipTypesAndAnnotations(paramTypes: any[], paramAnnotations: any[]): any[][] { 37 | let result: any[][]; 38 | 39 | if (typeof paramTypes === 'undefined') { 40 | result = new Array(paramAnnotations.length); 41 | } else { 42 | result = new Array(paramTypes.length); 43 | } 44 | 45 | for (let i = 0; i < result.length; i++) { 46 | // TS outputs Object for parameters without types, while Traceur omits 47 | // the annotations. For now we preserve the Traceur behavior to aid 48 | // migration, but this can be revisited. 49 | if (typeof paramTypes === 'undefined') { 50 | result[i] = []; 51 | // tslint:disable-next-line:triple-equals 52 | } else if (paramTypes[i] != Object) { 53 | result[i] = [paramTypes[i]]; 54 | } else { 55 | result[i] = []; 56 | } 57 | if (paramAnnotations && paramAnnotations[i] != null) { 58 | result[i] = result[i].concat(paramAnnotations[i]); 59 | } 60 | } 61 | return result; 62 | } 63 | 64 | private _ownParameters(type: Type, parentCtor: any): any[][] | null { 65 | // If we have no decorators, we only have function.length as metadata. 66 | // In that case, to detect whether a child class declared an own constructor or not, 67 | // we need to look inside of that constructor to check whether it is 68 | // just calling the parent. 69 | // This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439 70 | // that sets 'design:paramtypes' to [] 71 | // if a class inherits from another class but has no ctor declared itself. 72 | if (DELEGATE_CTOR.exec(type.toString())) { 73 | return null; 74 | } 75 | 76 | // Prefer the direct API. 77 | if ((type).parameters && (type).parameters !== parentCtor.parameters) { 78 | return (type).parameters; 79 | } 80 | 81 | // API of tsickle for lowering decorators to properties on the class. 82 | const tsickleCtorParams = (type).ctorParameters; 83 | if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) { 84 | // Newer tsickle uses a function closure 85 | // Retain the non-function case for compatibility with older tsickle 86 | const ctorParameters = typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams; 87 | const paramTypes = ctorParameters.map((ctorParam: any) => ctorParam && ctorParam.type); 88 | const paramAnnotations = ctorParameters.map( 89 | (ctorParam: any) => ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators) 90 | ); 91 | return this._zipTypesAndAnnotations(paramTypes, paramAnnotations); 92 | } 93 | 94 | // API for metadata created by invoking the decorators. 95 | if (this._reflect != null && this._reflect.getOwnMetadata != null) { 96 | const paramAnnotations = this._reflect.getOwnMetadata('parameters', type); 97 | const paramTypes = this._reflect.getOwnMetadata('design:paramtypes', type); 98 | if (paramTypes || paramAnnotations) { 99 | return this._zipTypesAndAnnotations(paramTypes, paramAnnotations); 100 | } 101 | } 102 | 103 | // If a class has no decorators, at least create metadata 104 | // based on function.length. 105 | // Note: We know that this is a real constructor as we checked 106 | // the content of the constructor above. 107 | return new Array(type.length).fill(undefined); 108 | } 109 | 110 | parameters(type: Type): any[][] { 111 | // Note: only report metadata if we have at least one class decorator 112 | // to stay in sync with the static reflector. 113 | if (!isType(type)) { 114 | return []; 115 | } 116 | const parentCtor = getParentCtor(type); 117 | let parameters = this._ownParameters(type, parentCtor); 118 | if (!parameters && parentCtor !== Object) { 119 | parameters = this.parameters(parentCtor); 120 | } 121 | return parameters || []; 122 | } 123 | 124 | private _ownAnnotations(typeOrFunc: Type, parentCtor: any): any[] | null { 125 | // Prefer the direct API. 126 | if ((typeOrFunc).annotations && (typeOrFunc).annotations !== parentCtor.annotations) { 127 | let annotations = (typeOrFunc).annotations; 128 | if (typeof annotations === 'function' && annotations.annotations) { 129 | annotations = annotations.annotations; 130 | } 131 | return annotations; 132 | } 133 | 134 | // API of tsickle for lowering decorators to properties on the class. 135 | if ((typeOrFunc).decorators && (typeOrFunc).decorators !== parentCtor.decorators) { 136 | return convertTsickleDecoratorIntoMetadata((typeOrFunc).decorators); 137 | } 138 | 139 | // API for metadata created by invoking the decorators. 140 | if (this._reflect && this._reflect.getOwnMetadata) { 141 | return this._reflect.getOwnMetadata('annotations', typeOrFunc); 142 | } 143 | return null; 144 | } 145 | 146 | annotations(typeOrFunc: Type): any[] { 147 | if (!isType(typeOrFunc)) { 148 | return []; 149 | } 150 | const parentCtor = getParentCtor(typeOrFunc); 151 | const ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || []; 152 | const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : []; 153 | return parentAnnotations.concat(ownAnnotations); 154 | } 155 | 156 | private _ownPropMetadata(typeOrFunc: any, parentCtor: any): { [key: string]: any[] } | null { 157 | // Prefer the direct API. 158 | if ((typeOrFunc).propMetadata && (typeOrFunc).propMetadata !== parentCtor.propMetadata) { 159 | let propMetadata = (typeOrFunc).propMetadata; 160 | if (typeof propMetadata === 'function' && propMetadata.propMetadata) { 161 | propMetadata = propMetadata.propMetadata; 162 | } 163 | return propMetadata; 164 | } 165 | 166 | // API of tsickle for lowering decorators to properties on the class. 167 | if ((typeOrFunc).propDecorators && (typeOrFunc).propDecorators !== parentCtor.propDecorators) { 168 | const propDecorators = (typeOrFunc).propDecorators; 169 | const propMetadata = <{ [key: string]: any[] }>{}; 170 | Object.keys(propDecorators).forEach((prop) => { 171 | propMetadata[prop] = convertTsickleDecoratorIntoMetadata(propDecorators[prop]); 172 | }); 173 | return propMetadata; 174 | } 175 | 176 | // API for metadata created by invoking the decorators. 177 | if (this._reflect && this._reflect.getOwnMetadata) { 178 | return this._reflect.getOwnMetadata('propMetadata', typeOrFunc); 179 | } 180 | return null; 181 | } 182 | 183 | propMetadata(typeOrFunc: any): { [key: string]: any[] } { 184 | if (!isType(typeOrFunc)) { 185 | return {}; 186 | } 187 | const parentCtor = getParentCtor(typeOrFunc); 188 | const propMetadata: { [key: string]: any[] } = {}; 189 | if (parentCtor !== Object) { 190 | const parentPropMetadata = this.propMetadata(parentCtor); 191 | Object.keys(parentPropMetadata).forEach((propName) => { 192 | propMetadata[propName] = parentPropMetadata[propName]; 193 | }); 194 | } 195 | const ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor); 196 | if (ownPropMetadata) { 197 | Object.keys(ownPropMetadata).forEach((propName) => { 198 | const decorators: any[] = []; 199 | if (propMetadata.hasOwnProperty(propName)) { 200 | decorators.push(...propMetadata[propName]); 201 | } 202 | decorators.push(...ownPropMetadata[propName]); 203 | propMetadata[propName] = decorators; 204 | }); 205 | } 206 | return propMetadata; 207 | } 208 | 209 | hasLifecycleHook(type: any, lcProperty: string): boolean { 210 | return type instanceof Type && lcProperty in type.prototype; 211 | } 212 | 213 | getter(name: string): GetterFn { 214 | return new Function('o', 'return o.' + name + ';'); 215 | } 216 | 217 | setter(name: string): SetterFn { 218 | return new Function('o', 'v', 'return o.' + name + ' = v;'); 219 | } 220 | 221 | method(name: string): MethodFn { 222 | const functionBody = `if (!o.${name}) throw new Error('"${name}" is undefined'); 223 | return o.${name}.apply(o, args);`; 224 | return new Function('o', 'args', functionBody); 225 | } 226 | 227 | // There is not a concept of import uri in Js, but this is useful in developing Dart applications. 228 | importUri(type: any): string { 229 | // StaticSymbol 230 | if (typeof type === 'object' && type['filePath']) { 231 | return type['filePath']; 232 | } 233 | // Runtime type 234 | return `./${stringify(type)}`; 235 | } 236 | 237 | resourceUri(type: any): string { 238 | return `./${stringify(type)}`; 239 | } 240 | 241 | resolveIdentifier(name: string, moduleUrl: string, members: string[], runtime: any): any { 242 | return runtime; 243 | } 244 | resolveEnum(enumIdentifier: any, name: string): any { 245 | return enumIdentifier[name]; 246 | } 247 | } 248 | 249 | function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] { 250 | if (!decoratorInvocations) { 251 | return []; 252 | } 253 | return decoratorInvocations.map((decoratorInvocation) => { 254 | const decoratorType = decoratorInvocation.type; 255 | const annotationCls = decoratorType.annotationCls; 256 | const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : []; 257 | return new annotationCls(...annotationArgs); 258 | }); 259 | } 260 | 261 | function getParentCtor(ctor: Function): Type { 262 | if (!ctor.prototype) { 263 | return Object; 264 | } 265 | const parentProto = Object.getPrototypeOf(ctor.prototype); 266 | const parentCtor = parentProto ? parentProto.constructor : null; 267 | // Note: We always use `Object` as the null value 268 | // to simplify checking later on. 269 | return parentCtor || Object; 270 | } 271 | -------------------------------------------------------------------------------- /lib/reflection/reflector.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { Type } from '../facade/type'; 10 | import { PlatformReflectionCapabilities } from './platform_reflection_capabilities'; 11 | import { ReflectorReader } from './reflector_reader'; 12 | import { GetterFn, MethodFn, SetterFn } from './types'; 13 | 14 | export { PlatformReflectionCapabilities } from './platform_reflection_capabilities'; 15 | export { GetterFn, MethodFn, SetterFn } from './types'; 16 | 17 | /** 18 | * Provides access to reflection data about symbols. Used internally by Angular 19 | * to power dependency injection and compilation. 20 | */ 21 | export class Reflector extends ReflectorReader { 22 | constructor(public reflectionCapabilities: PlatformReflectionCapabilities) { 23 | super(); 24 | } 25 | 26 | updateCapabilities(caps: PlatformReflectionCapabilities) { 27 | this.reflectionCapabilities = caps; 28 | } 29 | 30 | factory(type: Type): Function { 31 | return this.reflectionCapabilities.factory(type); 32 | } 33 | 34 | parameters(typeOrFunc: Type): any[][] { 35 | return this.reflectionCapabilities.parameters(typeOrFunc); 36 | } 37 | 38 | annotations(typeOrFunc: Type): any[] { 39 | return this.reflectionCapabilities.annotations(typeOrFunc); 40 | } 41 | 42 | propMetadata(typeOrFunc: Type): { [key: string]: any[] } { 43 | return this.reflectionCapabilities.propMetadata(typeOrFunc); 44 | } 45 | 46 | hasLifecycleHook(type: any, lcProperty: string): boolean { 47 | return this.reflectionCapabilities.hasLifecycleHook(type, lcProperty); 48 | } 49 | 50 | getter(name: string): GetterFn { 51 | return this.reflectionCapabilities.getter(name); 52 | } 53 | 54 | setter(name: string): SetterFn { 55 | return this.reflectionCapabilities.setter(name); 56 | } 57 | 58 | method(name: string): MethodFn { 59 | return this.reflectionCapabilities.method(name); 60 | } 61 | 62 | importUri(type: any): string { 63 | return this.reflectionCapabilities.importUri(type); 64 | } 65 | 66 | resourceUri(type: any): string { 67 | return this.reflectionCapabilities.resourceUri(type); 68 | } 69 | 70 | resolveIdentifier(name: string, moduleUrl: string, members: string[] | null, runtime: any): any { 71 | return this.reflectionCapabilities.resolveIdentifier(name, moduleUrl, members, runtime); 72 | } 73 | 74 | resolveEnum(identifier: any, name: string): any { 75 | return this.reflectionCapabilities.resolveEnum(identifier, name); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/reflection/reflector_reader.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | /** 10 | * Provides read-only access to reflection data about symbols. Used internally by Angular 11 | * to power dependency injection and compilation. 12 | */ 13 | export abstract class ReflectorReader { 14 | abstract parameters(typeOrFunc: /*Type*/ any): any[][]; 15 | abstract annotations(typeOrFunc: /*Type*/ any): any[]; 16 | abstract propMetadata(typeOrFunc: /*Type*/ any): { [key: string]: any[] }; 17 | abstract importUri(typeOrFunc: /*Type*/ any): string | null; 18 | abstract resourceUri(typeOrFunc: /*Type*/ any): string; 19 | abstract resolveIdentifier(name: string, moduleUrl: string, members: string[], runtime: any): any; 20 | abstract resolveEnum(identifier: any, name: string): any; 21 | } 22 | -------------------------------------------------------------------------------- /lib/reflection/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | export type SetterFn = (obj: any, value: any) => void; 10 | export type GetterFn = (obj: any) => any; 11 | export type MethodFn = (obj: any, args: any[]) => any; 12 | -------------------------------------------------------------------------------- /lib/reflective_errors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { wrappedError } from './facade/errors'; 10 | import { ERROR_ORIGINAL_ERROR, getOriginalError } from './facade/errors'; 11 | import { stringify } from './facade/lang'; 12 | import { Type } from './facade/type'; 13 | 14 | import { ReflectiveInjector } from './reflective_injector'; 15 | import { ReflectiveKey } from './reflective_key'; 16 | 17 | function findFirstClosedCycle(keys: any[]): any[] { 18 | const res: any[] = []; 19 | for (let i = 0; i < keys.length; ++i) { 20 | if (res.indexOf(keys[i]) > -1) { 21 | res.push(keys[i]); 22 | return res; 23 | } 24 | res.push(keys[i]); 25 | } 26 | return res; 27 | } 28 | 29 | function constructResolvingPath(keys: any[]): string { 30 | if (keys.length > 1) { 31 | const reversed = findFirstClosedCycle(keys.slice().reverse()); 32 | const tokenStrs = reversed.map((k) => stringify(k.token)); 33 | return ' (' + tokenStrs.join(' -> ') + ')'; 34 | } 35 | 36 | return ''; 37 | } 38 | 39 | export interface InjectionError extends Error { 40 | keys: ReflectiveKey[]; 41 | injectors: ReflectiveInjector[]; 42 | constructResolvingMessage: (this: InjectionError) => string; 43 | addKey(injector: ReflectiveInjector, key: ReflectiveKey): void; 44 | } 45 | 46 | function injectionError( 47 | injector: ReflectiveInjector, 48 | key: ReflectiveKey, 49 | constructResolvingMessage: (this: InjectionError) => string, 50 | originalError?: Error 51 | ): InjectionError { 52 | const error = (originalError ? wrappedError('', originalError) : Error()) as InjectionError; 53 | error.addKey = addKey; 54 | error.keys = [key]; 55 | error.injectors = [injector]; 56 | error.constructResolvingMessage = constructResolvingMessage; 57 | error.message = error.constructResolvingMessage(); 58 | (error as any)[ERROR_ORIGINAL_ERROR] = originalError; 59 | return error; 60 | } 61 | 62 | function addKey(this: InjectionError, injector: ReflectiveInjector, key: ReflectiveKey): void { 63 | this.injectors.push(injector); 64 | this.keys.push(key); 65 | this.message = this.constructResolvingMessage(); 66 | } 67 | 68 | /** 69 | * Thrown when trying to retrieve a dependency by key from {@link Injector}, but the 70 | * {@link Injector} does not have a {@link Provider} for the given key. 71 | * 72 | * ### Example ([live demo](http://plnkr.co/edit/vq8D3FRB9aGbnWJqtEPE?p=preview)) 73 | * 74 | * ```typescript 75 | * class A { 76 | * constructor(b:B) {} 77 | * } 78 | * 79 | * expect(() => Injector.resolveAndCreate([A])).toThrowError(); 80 | * ``` 81 | */ 82 | export function noProviderError(injector: ReflectiveInjector, key: ReflectiveKey): InjectionError { 83 | return injectionError(injector, key, function (this: InjectionError) { 84 | const first = stringify(this.keys[0].token); 85 | return `No provider for ${first}!${constructResolvingPath(this.keys)}`; 86 | }); 87 | } 88 | 89 | /** 90 | * Thrown when dependencies form a cycle. 91 | * 92 | * ### Example ([live demo](http://plnkr.co/edit/wYQdNos0Tzql3ei1EV9j?p=info)) 93 | * 94 | * ```typescript 95 | * var injector = Injector.resolveAndCreate([ 96 | * {provide: "one", useFactory: (two) => "two", deps: [[new Inject("two")]]}, 97 | * {provide: "two", useFactory: (one) => "one", deps: [[new Inject("one")]]} 98 | * ]); 99 | * 100 | * expect(() => injector.get("one")).toThrowError(); 101 | * ``` 102 | * 103 | * Retrieving `A` or `B` throws a `CyclicDependencyError` as the graph above cannot be constructed. 104 | */ 105 | export function cyclicDependencyError(injector: ReflectiveInjector, key: ReflectiveKey): InjectionError { 106 | return injectionError(injector, key, function (this: InjectionError) { 107 | return `Cannot instantiate cyclic dependency!${constructResolvingPath(this.keys)}`; 108 | }); 109 | } 110 | 111 | /** 112 | * Thrown when a constructing type returns with an Error. 113 | * 114 | * The `InstantiationError` class contains the original error plus the dependency graph which caused 115 | * this object to be instantiated. 116 | * 117 | * ### Example ([live demo](http://plnkr.co/edit/7aWYdcqTQsP0eNqEdUAf?p=preview)) 118 | * 119 | * ```typescript 120 | * class A { 121 | * constructor() { 122 | * throw new Error('message'); 123 | * } 124 | * } 125 | * 126 | * var injector = Injector.resolveAndCreate([A]); 127 | 128 | * try { 129 | * injector.get(A); 130 | * } catch (e) { 131 | * expect(e instanceof InstantiationError).toBe(true); 132 | * expect(e.originalException.message).toEqual("message"); 133 | * expect(e.originalStack).toBeDefined(); 134 | * } 135 | * ``` 136 | */ 137 | export function instantiationError( 138 | injector: ReflectiveInjector, 139 | originalException: any, 140 | originalStack: any, 141 | key: ReflectiveKey 142 | ): InjectionError { 143 | return injectionError( 144 | injector, 145 | key, 146 | function (this: InjectionError) { 147 | const first = stringify(this.keys[0].token); 148 | return `${getOriginalError(this).message}: Error during instantiation of ${first}!${constructResolvingPath(this.keys)}.`; 149 | }, 150 | originalException 151 | ); 152 | } 153 | 154 | /** 155 | * Thrown when an object other then {@link Provider} (or `Type`) is passed to {@link Injector} 156 | * creation. 157 | * 158 | * ### Example ([live demo](http://plnkr.co/edit/YatCFbPAMCL0JSSQ4mvH?p=preview)) 159 | * 160 | * ```typescript 161 | * expect(() => Injector.resolveAndCreate(["not a type"])).toThrowError(); 162 | * ``` 163 | */ 164 | export function invalidProviderError(provider: any) { 165 | return Error(`Invalid provider - only instances of Provider and Type are allowed, got: ${provider}`); 166 | } 167 | 168 | /** 169 | * Thrown when the class has no annotation information. 170 | * 171 | * Lack of annotation information prevents the {@link Injector} from determining which dependencies 172 | * need to be injected into the constructor. 173 | * 174 | * ### Example ([live demo](http://plnkr.co/edit/rHnZtlNS7vJOPQ6pcVkm?p=preview)) 175 | * 176 | * ```typescript 177 | * class A { 178 | * constructor(b) {} 179 | * } 180 | * 181 | * expect(() => Injector.resolveAndCreate([A])).toThrowError(); 182 | * ``` 183 | * 184 | * This error is also thrown when the class not marked with {@link Injectable} has parameter types. 185 | * 186 | * ```typescript 187 | * class B {} 188 | * 189 | * class A { 190 | * constructor(b:B) {} // no information about the parameter types of A is available at runtime. 191 | * } 192 | * 193 | * expect(() => Injector.resolveAndCreate([A,B])).toThrowError(); 194 | * ``` 195 | * @stable 196 | */ 197 | export function noAnnotationError(typeOrFunc: Type | Function, params: any[][]): Error { 198 | const signature: string[] = []; 199 | for (let i = 0, ii = params.length; i < ii; i++) { 200 | const parameter = params[i]; 201 | if (!parameter || parameter.length === 0) { 202 | signature.push('?'); 203 | } else { 204 | signature.push(parameter.map(stringify).join(' ')); 205 | } 206 | } 207 | return Error( 208 | "Cannot resolve all parameters for '" + 209 | stringify(typeOrFunc) + 210 | "'(" + 211 | signature.join(', ') + 212 | '). ' + 213 | "Make sure that all the parameters are decorated with Inject or have valid type annotations and that '" + 214 | stringify(typeOrFunc) + 215 | "' is decorated with Injectable." 216 | ); 217 | } 218 | 219 | /** 220 | * Thrown when getting an object by index. 221 | * 222 | * ### Example ([live demo](http://plnkr.co/edit/bRs0SX2OTQiJzqvjgl8P?p=preview)) 223 | * 224 | * ```typescript 225 | * class A {} 226 | * 227 | * var injector = Injector.resolveAndCreate([A]); 228 | * 229 | * expect(() => injector.getAt(100)).toThrowError(); 230 | * ``` 231 | * @stable 232 | */ 233 | export function outOfBoundsError(index: number) { 234 | return Error(`Index ${index} is out-of-bounds.`); 235 | } 236 | 237 | // TODO: add a working example after alpha38 is released 238 | /** 239 | * Thrown when a multi provider and a regular provider are bound to the same token. 240 | * 241 | * ### Example 242 | * 243 | * ```typescript 244 | * expect(() => Injector.resolveAndCreate([ 245 | * { provide: "Strings", useValue: "string1", multi: true}, 246 | * { provide: "Strings", useValue: "string2", multi: false} 247 | * ])).toThrowError(); 248 | * ``` 249 | */ 250 | 251 | export function mixingMultiProvidersWithRegularProvidersError(provider1: any, provider2: any): Error { 252 | return Error(`Cannot mix multi providers and regular providers, got: ${provider1} ${provider2}`); 253 | } 254 | -------------------------------------------------------------------------------- /lib/reflective_injector.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { Type } from './facade/type'; 10 | import { Injector, THROW_IF_NOT_FOUND } from './injector'; 11 | import { setCurrentInjector } from './injector_compatibility'; 12 | import { Self, SkipSelf } from './metadata'; 13 | import { Provider } from './provider'; 14 | import { cyclicDependencyError, instantiationError, noProviderError, outOfBoundsError } from './reflective_errors'; 15 | import { ReflectiveKey } from './reflective_key'; 16 | import { 17 | ReflectiveDependency, 18 | ResolvedReflectiveFactory, 19 | ResolvedReflectiveProvider, 20 | resolveReflectiveProviders, 21 | } from './reflective_provider'; 22 | 23 | // Threshold for the dynamic version 24 | const UNDEFINED = new Object(); 25 | 26 | /** 27 | * A ReflectiveDependency injection container used for instantiating objects and resolving 28 | * dependencies. 29 | * 30 | * An `Injector` is a replacement for a `new` operator, which can automatically resolve the 31 | * constructor dependencies. 32 | * 33 | * In typical use, application code asks for the dependencies in the constructor and they are 34 | * resolved by the `Injector`. 35 | * 36 | * ### Example ([live demo](http://plnkr.co/edit/jzjec0?p=preview)) 37 | * 38 | * The following example creates an `Injector` configured to create `Engine` and `Car`. 39 | * 40 | * ```typescript 41 | * @Injectable() 42 | * class Engine { 43 | * } 44 | * 45 | * @Injectable() 46 | * class Car { 47 | * constructor(public engine:Engine) {} 48 | * } 49 | * 50 | * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]); 51 | * var car = injector.get(Car); 52 | * expect(car instanceof Car).toBe(true); 53 | * expect(car.engine instanceof Engine).toBe(true); 54 | * ``` 55 | * 56 | * Notice, we don't use the `new` operator because we explicitly want to have the `Injector` 57 | * resolve all of the object's dependencies automatically. 58 | * 59 | * @stable 60 | */ 61 | export abstract class ReflectiveInjector implements Injector { 62 | /** 63 | * Turns an array of provider definitions into an array of resolved providers. 64 | * 65 | * A resolution is a process of flattening multiple nested arrays and converting individual 66 | * providers into an array of {@link ResolvedReflectiveProvider}s. 67 | * 68 | * ### Example ([live demo](http://plnkr.co/edit/AiXTHi?p=preview)) 69 | * 70 | * ```typescript 71 | * @Injectable() 72 | * class Engine { 73 | * } 74 | * 75 | * @Injectable() 76 | * class Car { 77 | * constructor(public engine:Engine) {} 78 | * } 79 | * 80 | * var providers = ReflectiveInjector.resolve([Car, [[Engine]]]); 81 | * 82 | * expect(providers.length).toEqual(2); 83 | * 84 | * expect(providers[0] instanceof ResolvedReflectiveProvider).toBe(true); 85 | * expect(providers[0].key.displayName).toBe("Car"); 86 | * expect(providers[0].dependencies.length).toEqual(1); 87 | * expect(providers[0].factory).toBeDefined(); 88 | * 89 | * expect(providers[1].key.displayName).toBe("Engine"); 90 | * }); 91 | * ``` 92 | * 93 | * See {@link ReflectiveInjector#fromResolvedProviders} for more info. 94 | */ 95 | static resolve(providers: Provider[]): ResolvedReflectiveProvider[] { 96 | return resolveReflectiveProviders(providers); 97 | } 98 | 99 | /** 100 | * Resolves an array of providers and creates an injector from those providers. 101 | * 102 | * The passed-in providers can be an array of `Type`, {@link Provider}, 103 | * or a recursive array of more providers. 104 | * 105 | * ### Example ([live demo](http://plnkr.co/edit/ePOccA?p=preview)) 106 | * 107 | * ```typescript 108 | * @Injectable() 109 | * class Engine { 110 | * } 111 | * 112 | * @Injectable() 113 | * class Car { 114 | * constructor(public engine:Engine) {} 115 | * } 116 | * 117 | * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]); 118 | * expect(injector.get(Car) instanceof Car).toBe(true); 119 | * ``` 120 | * 121 | * This function is slower than the corresponding `fromResolvedProviders` 122 | * because it needs to resolve the passed-in providers first. 123 | * See {@link Injector#resolve} and {@link Injector#fromResolvedProviders}. 124 | */ 125 | static resolveAndCreate(providers: Provider[], parent?: Injector): ReflectiveInjector { 126 | const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers); 127 | return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent); 128 | } 129 | 130 | /** 131 | * Creates an injector from previously resolved providers. 132 | * 133 | * This API is the recommended way to construct injectors in performance-sensitive parts. 134 | * 135 | * ### Example ([live demo](http://plnkr.co/edit/KrSMci?p=preview)) 136 | * 137 | * ```typescript 138 | * @Injectable() 139 | * class Engine { 140 | * } 141 | * 142 | * @Injectable() 143 | * class Car { 144 | * constructor(public engine:Engine) {} 145 | * } 146 | * 147 | * var providers = ReflectiveInjector.resolve([Car, Engine]); 148 | * var injector = ReflectiveInjector.fromResolvedProviders(providers); 149 | * expect(injector.get(Car) instanceof Car).toBe(true); 150 | * ``` 151 | * @experimental 152 | */ 153 | static fromResolvedProviders(providers: ResolvedReflectiveProvider[], parent?: Injector): ReflectiveInjector { 154 | // tslint:disable-next-line:no-use-before-declare 155 | return new ReflectiveInjector_(providers, parent); 156 | } 157 | 158 | /** 159 | * Parent of this injector. 160 | * 161 | * 163 | * 164 | * ### Example ([live demo](http://plnkr.co/edit/eosMGo?p=preview)) 165 | * 166 | * ```typescript 167 | * var parent = ReflectiveInjector.resolveAndCreate([]); 168 | * var child = parent.resolveAndCreateChild([]); 169 | * expect(child.parent).toBe(parent); 170 | * ``` 171 | */ 172 | abstract get parent(): Injector | null; 173 | 174 | /** 175 | * Resolves an array of providers and creates a child injector from those providers. 176 | * 177 | * 179 | * 180 | * The passed-in providers can be an array of `Type`, {@link Provider}, 181 | * or a recursive array of more providers. 182 | * 183 | * ### Example ([live demo](http://plnkr.co/edit/opB3T4?p=preview)) 184 | * 185 | * ```typescript 186 | * class ParentProvider {} 187 | * class ChildProvider {} 188 | * 189 | * var parent = ReflectiveInjector.resolveAndCreate([ParentProvider]); 190 | * var child = parent.resolveAndCreateChild([ChildProvider]); 191 | * 192 | * expect(child.get(ParentProvider) instanceof ParentProvider).toBe(true); 193 | * expect(child.get(ChildProvider) instanceof ChildProvider).toBe(true); 194 | * expect(child.get(ParentProvider)).toBe(parent.get(ParentProvider)); 195 | * ``` 196 | * 197 | * This function is slower than the corresponding `createChildFromResolved` 198 | * because it needs to resolve the passed-in providers first. 199 | * See {@link Injector#resolve} and {@link Injector#createChildFromResolved}. 200 | */ 201 | abstract resolveAndCreateChild(providers: Provider[]): ReflectiveInjector; 202 | 203 | /** 204 | * Creates a child injector from previously resolved providers. 205 | * 206 | * 208 | * 209 | * This API is the recommended way to construct injectors in performance-sensitive parts. 210 | * 211 | * ### Example ([live demo](http://plnkr.co/edit/VhyfjN?p=preview)) 212 | * 213 | * ```typescript 214 | * class ParentProvider {} 215 | * class ChildProvider {} 216 | * 217 | * var parentProviders = ReflectiveInjector.resolve([ParentProvider]); 218 | * var childProviders = ReflectiveInjector.resolve([ChildProvider]); 219 | * 220 | * var parent = ReflectiveInjector.fromResolvedProviders(parentProviders); 221 | * var child = parent.createChildFromResolved(childProviders); 222 | * 223 | * expect(child.get(ParentProvider) instanceof ParentProvider).toBe(true); 224 | * expect(child.get(ChildProvider) instanceof ChildProvider).toBe(true); 225 | * expect(child.get(ParentProvider)).toBe(parent.get(ParentProvider)); 226 | * ``` 227 | */ 228 | abstract createChildFromResolved(providers: ResolvedReflectiveProvider[]): ReflectiveInjector; 229 | 230 | /** 231 | * Resolves a provider and instantiates an object in the context of the injector. 232 | * 233 | * The created object does not get cached by the injector. 234 | * 235 | * ### Example ([live demo](http://plnkr.co/edit/yvVXoB?p=preview)) 236 | * 237 | * ```typescript 238 | * @Injectable() 239 | * class Engine { 240 | * } 241 | * 242 | * @Injectable() 243 | * class Car { 244 | * constructor(public engine:Engine) {} 245 | * } 246 | * 247 | * var injector = ReflectiveInjector.resolveAndCreate([Engine]); 248 | * 249 | * var car = injector.resolveAndInstantiate(Car); 250 | * expect(car.engine).toBe(injector.get(Engine)); 251 | * expect(car).not.toBe(injector.resolveAndInstantiate(Car)); 252 | * ``` 253 | */ 254 | abstract resolveAndInstantiate(provider: Provider): any; 255 | 256 | /** 257 | * Instantiates an object using a resolved provider in the context of the injector. 258 | * 259 | * The created object does not get cached by the injector. 260 | * 261 | * ### Example ([live demo](http://plnkr.co/edit/ptCImQ?p=preview)) 262 | * 263 | * ```typescript 264 | * @Injectable() 265 | * class Engine { 266 | * } 267 | * 268 | * @Injectable() 269 | * class Car { 270 | * constructor(public engine:Engine) {} 271 | * } 272 | * 273 | * var injector = ReflectiveInjector.resolveAndCreate([Engine]); 274 | * var carProvider = ReflectiveInjector.resolve([Car])[0]; 275 | * var car = injector.instantiateResolved(carProvider); 276 | * expect(car.engine).toBe(injector.get(Engine)); 277 | * expect(car).not.toBe(injector.instantiateResolved(carProvider)); 278 | * ``` 279 | */ 280 | abstract instantiateResolved(provider: ResolvedReflectiveProvider): any; 281 | 282 | abstract get(token: any, notFoundValue?: any): any; 283 | } 284 | 285 | // tslint:disable-next-line:class-name 286 | export class ReflectiveInjector_ implements ReflectiveInjector { 287 | /** @internal */ 288 | _constructionCounter = 0; 289 | /** @internal */ 290 | public _providers: ResolvedReflectiveProvider[]; 291 | /** @internal */ 292 | public _parent: Injector | null; 293 | 294 | keyIds: number[]; 295 | objs: any[]; 296 | /** 297 | * Private 298 | */ 299 | constructor(_providers: ResolvedReflectiveProvider[], _parent?: Injector) { 300 | this._providers = _providers; 301 | this._parent = _parent || null; 302 | 303 | const len = _providers.length; 304 | 305 | this.keyIds = new Array(len); 306 | this.objs = new Array(len); 307 | 308 | for (let i = 0; i < len; i++) { 309 | this.keyIds[i] = _providers[i].key.id; 310 | this.objs[i] = UNDEFINED; 311 | } 312 | } 313 | 314 | get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any { 315 | return this._getByKey(ReflectiveKey.get(token), null, notFoundValue); 316 | } 317 | 318 | get parent(): Injector | null { 319 | return this._parent; 320 | } 321 | 322 | resolveAndCreateChild(providers: Provider[]): ReflectiveInjector { 323 | const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers); 324 | return this.createChildFromResolved(ResolvedReflectiveProviders); 325 | } 326 | 327 | createChildFromResolved(providers: ResolvedReflectiveProvider[]): ReflectiveInjector { 328 | const inj = new ReflectiveInjector_(providers); 329 | inj._parent = this; 330 | return inj; 331 | } 332 | 333 | resolveAndInstantiate(provider: Provider): any { 334 | return this.instantiateResolved(ReflectiveInjector.resolve([provider])[0]); 335 | } 336 | 337 | instantiateResolved(provider: ResolvedReflectiveProvider): any { 338 | return this._instantiateProviderContext(provider); 339 | } 340 | 341 | getProviderAtIndex(index: number): ResolvedReflectiveProvider { 342 | if (index < 0 || index >= this._providers.length) { 343 | throw outOfBoundsError(index); 344 | } 345 | return this._providers[index]; 346 | } 347 | 348 | /** @internal */ 349 | _new(provider: ResolvedReflectiveProvider): any { 350 | if (this._constructionCounter++ > this._getMaxNumberOfObjects()) { 351 | throw cyclicDependencyError(this, provider.key); 352 | } 353 | return this._instantiateProviderContext(provider); 354 | } 355 | 356 | private _getMaxNumberOfObjects(): number { 357 | return this.objs.length; 358 | } 359 | 360 | private _instantiateProviderContext(provider: ResolvedReflectiveProvider): any { 361 | const previousInjector = setCurrentInjector(this); 362 | try { 363 | return this._instantiateProvider(provider); 364 | } finally { 365 | setCurrentInjector(previousInjector); 366 | } 367 | } 368 | 369 | private _instantiateProvider(provider: ResolvedReflectiveProvider): any { 370 | if (provider.multiProvider) { 371 | const res = new Array(provider.resolvedFactories.length); 372 | for (let i = 0; i < provider.resolvedFactories.length; ++i) { 373 | res[i] = this._instantiate(provider, provider.resolvedFactories[i]); 374 | } 375 | return res; 376 | } else { 377 | return this._instantiate(provider, provider.resolvedFactories[0]); 378 | } 379 | } 380 | 381 | private _instantiate(provider: ResolvedReflectiveProvider, ResolvedReflectiveFactory: ResolvedReflectiveFactory): any { 382 | const factory = ResolvedReflectiveFactory.factory; 383 | 384 | let deps: any[]; 385 | try { 386 | deps = ResolvedReflectiveFactory.dependencies.map((dep) => this._getByReflectiveDependency(dep)); 387 | } catch (e: any) { 388 | if (e.addKey) { 389 | e.addKey(this, provider.key); 390 | } 391 | throw e; 392 | } 393 | 394 | let obj: any; 395 | try { 396 | obj = factory(...deps); 397 | } catch (e: any) { 398 | throw instantiationError(this, e, e.stack, provider.key); 399 | } 400 | 401 | return obj; 402 | } 403 | 404 | private _getByReflectiveDependency(dep: ReflectiveDependency): any { 405 | return this._getByKey(dep.key, dep.visibility, dep.optional ? null : THROW_IF_NOT_FOUND); 406 | } 407 | 408 | private _getByKey(key: ReflectiveKey, visibility: Self | SkipSelf | null, notFoundValue: any): any { 409 | // tslint:disable-next-line:no-use-before-declare 410 | if (key === INJECTOR_KEY) { 411 | return this; 412 | } 413 | 414 | if (visibility instanceof Self) { 415 | return this._getByKeySelf(key, notFoundValue); 416 | } else { 417 | return this._getByKeyDefault(key, notFoundValue, visibility); 418 | } 419 | } 420 | 421 | private _getObjByKeyId(keyId: number): any { 422 | for (let i = 0; i < this.keyIds.length; i++) { 423 | if (this.keyIds[i] === keyId) { 424 | if (this.objs[i] === UNDEFINED) { 425 | this.objs[i] = this._new(this._providers[i]); 426 | } 427 | 428 | return this.objs[i]; 429 | } 430 | } 431 | 432 | return UNDEFINED; 433 | } 434 | 435 | /** @internal */ 436 | _throwOrNull(key: ReflectiveKey, notFoundValue: any): any { 437 | if (notFoundValue !== THROW_IF_NOT_FOUND) { 438 | return notFoundValue; 439 | } else { 440 | throw noProviderError(this, key); 441 | } 442 | } 443 | 444 | /** @internal */ 445 | _getByKeySelf(key: ReflectiveKey, notFoundValue: any): any { 446 | const obj = this._getObjByKeyId(key.id); 447 | return obj !== UNDEFINED ? obj : this._throwOrNull(key, notFoundValue); 448 | } 449 | 450 | /** @internal */ 451 | _getByKeyDefault(key: ReflectiveKey, notFoundValue: any, visibility: Self | SkipSelf | null): any { 452 | let inj: Injector | null; 453 | 454 | if (visibility instanceof SkipSelf) { 455 | inj = this._parent; 456 | } else { 457 | inj = this; 458 | } 459 | 460 | while (inj instanceof ReflectiveInjector_) { 461 | const inj_ = inj; 462 | const obj = inj_._getObjByKeyId(key.id); 463 | if (obj !== UNDEFINED) return obj; 464 | inj = inj_._parent; 465 | } 466 | if (inj !== null) { 467 | return inj.get(key.token, notFoundValue); 468 | } else { 469 | return this._throwOrNull(key, notFoundValue); 470 | } 471 | } 472 | 473 | get displayName(): string { 474 | const providers = _mapProviders(this, (b: ResolvedReflectiveProvider) => ' "' + b.key.displayName + '" ').join(', '); 475 | return `ReflectiveInjector(providers: [${providers}])`; 476 | } 477 | 478 | toString(): string { 479 | return this.displayName; 480 | } 481 | } 482 | 483 | const INJECTOR_KEY = ReflectiveKey.get(Injector); 484 | 485 | function _mapProviders(injector: ReflectiveInjector_, fn: Function): any[] { 486 | const res: any[] = new Array(injector._providers.length); 487 | for (let i = 0; i < injector._providers.length; ++i) { 488 | res[i] = fn(injector.getProviderAtIndex(i)); 489 | } 490 | return res; 491 | } 492 | -------------------------------------------------------------------------------- /lib/reflective_key.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { stringify } from './facade/lang'; 10 | 11 | import { resolveForwardRef } from './forward_ref'; 12 | 13 | /** 14 | * A unique object used for retrieving items from the {@link ReflectiveInjector}. 15 | * 16 | * Keys have: 17 | * - a system-wide unique `id`. 18 | * - a `token`. 19 | * 20 | * `Key` is used internally by {@link ReflectiveInjector} because its system-wide unique `id` allows 21 | * the 22 | * injector to store created objects in a more efficient way. 23 | * 24 | * `Key` should not be created directly. {@link ReflectiveInjector} creates keys automatically when 25 | * resolving 26 | * providers. 27 | * @experimental 28 | */ 29 | export class ReflectiveKey { 30 | /** 31 | * Private 32 | */ 33 | constructor(public token: Object, public id: number) { 34 | if (!token) { 35 | throw new Error('Token must be defined!'); 36 | } 37 | } 38 | 39 | /** 40 | * Returns a stringified token. 41 | */ 42 | get displayName(): string { 43 | return stringify(this.token); 44 | } 45 | 46 | /** 47 | * Retrieves a `Key` for a token. 48 | */ 49 | static get(token: Object): ReflectiveKey { 50 | // tslint:disable-next-line:no-use-before-declare 51 | return _globalKeyRegistry.get(resolveForwardRef(token)); 52 | } 53 | 54 | /** 55 | * @returns the number of keys registered in the system. 56 | */ 57 | static get numberOfKeys(): number { 58 | // tslint:disable-next-line:no-use-before-declare 59 | return _globalKeyRegistry.numberOfKeys; 60 | } 61 | } 62 | 63 | /** 64 | * @internal 65 | */ 66 | export class KeyRegistry { 67 | private _allKeys = new Map(); 68 | 69 | get(token: Object): ReflectiveKey { 70 | if (token instanceof ReflectiveKey) return token; 71 | 72 | if (this._allKeys.has(token)) { 73 | return this._allKeys.get(token)!; 74 | } 75 | 76 | const newKey = new ReflectiveKey(token, ReflectiveKey.numberOfKeys); 77 | this._allKeys.set(token, newKey); 78 | return newKey; 79 | } 80 | 81 | get numberOfKeys(): number { 82 | return this._allKeys.size; 83 | } 84 | } 85 | 86 | const _globalKeyRegistry = new KeyRegistry(); 87 | -------------------------------------------------------------------------------- /lib/reflective_provider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { reflector } from './reflection/reflection'; 10 | import { Type } from './facade/type'; 11 | 12 | import { resolveForwardRef } from './forward_ref'; 13 | import { InjectionToken } from './injection_token'; 14 | import { Inject, Optional, Self, SkipSelf } from './metadata'; 15 | import { ClassProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ValueProvider } from './provider'; 16 | import { invalidProviderError, mixingMultiProvidersWithRegularProvidersError, noAnnotationError } from './reflective_errors'; 17 | import { ReflectiveKey } from './reflective_key'; 18 | 19 | interface NormalizedProvider extends TypeProvider, ValueProvider, ClassProvider, ExistingProvider, FactoryProvider {} 20 | 21 | /** 22 | * `Dependency` is used by the framework to extend DI. 23 | * This is internal to Angular and should not be used directly. 24 | */ 25 | export class ReflectiveDependency { 26 | constructor(public key: ReflectiveKey, public optional: boolean, public visibility: Self | SkipSelf | null) {} 27 | 28 | static fromKey(key: ReflectiveKey): ReflectiveDependency { 29 | return new ReflectiveDependency(key, false, null); 30 | } 31 | } 32 | 33 | const _EMPTY_LIST: any[] = []; 34 | 35 | /** 36 | * An internal resolved representation of a {@link Provider} used by the {@link Injector}. 37 | * 38 | * It is usually created automatically by `Injector.resolveAndCreate`. 39 | * 40 | * It can be created manually, as follows: 41 | * 42 | * ### Example ([live demo](http://plnkr.co/edit/RfEnhh8kUEI0G3qsnIeT?p%3Dpreview&p=preview)) 43 | * 44 | * ```typescript 45 | * var resolvedProviders = Injector.resolve([{ provide: 'message', useValue: 'Hello' }]); 46 | * var injector = Injector.fromResolvedProviders(resolvedProviders); 47 | * 48 | * expect(injector.get('message')).toEqual('Hello'); 49 | * ``` 50 | * 51 | * @experimental 52 | */ 53 | export interface ResolvedReflectiveProvider { 54 | /** 55 | * A key, usually a `Type`. 56 | */ 57 | key: ReflectiveKey; 58 | 59 | /** 60 | * Factory function which can return an instance of an object represented by a key. 61 | */ 62 | resolvedFactories: ResolvedReflectiveFactory[]; 63 | 64 | /** 65 | * Indicates if the provider is a multi-provider or a regular provider. 66 | */ 67 | multiProvider: boolean; 68 | } 69 | 70 | // tslint:disable-next-line:class-name 71 | export class ResolvedReflectiveProvider_ implements ResolvedReflectiveProvider { 72 | constructor(public key: ReflectiveKey, public resolvedFactories: ResolvedReflectiveFactory[], public multiProvider: boolean) {} 73 | 74 | get resolvedFactory(): ResolvedReflectiveFactory { 75 | return this.resolvedFactories[0]; 76 | } 77 | } 78 | 79 | /** 80 | * An internal resolved representation of a factory function created by resolving {@link 81 | * Provider}. 82 | * @experimental 83 | */ 84 | export class ResolvedReflectiveFactory { 85 | constructor( 86 | /** 87 | * Factory function which can return an instance of an object represented by a key. 88 | */ 89 | public factory: Function, 90 | /** 91 | * Arguments (dependencies) to the `factory` function. 92 | */ 93 | public dependencies: ReflectiveDependency[] 94 | ) {} 95 | } 96 | 97 | /** 98 | * Resolve a single provider. 99 | */ 100 | function resolveReflectiveFactory(provider: NormalizedProvider): ResolvedReflectiveFactory { 101 | let factoryFn: Function; 102 | let resolvedDeps: ReflectiveDependency[]; 103 | if (provider.useClass) { 104 | const useClass = resolveForwardRef(provider.useClass); 105 | factoryFn = reflector.factory(useClass); 106 | resolvedDeps = _dependenciesFor(useClass); 107 | } else if (provider.useExisting) { 108 | factoryFn = (aliasInstance: any) => aliasInstance; 109 | resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))]; 110 | } else if (provider.useFactory) { 111 | factoryFn = provider.useFactory; 112 | resolvedDeps = constructDependencies(provider.useFactory, provider.deps); 113 | } else { 114 | factoryFn = () => provider.useValue; 115 | resolvedDeps = _EMPTY_LIST; 116 | } 117 | return new ResolvedReflectiveFactory(factoryFn, resolvedDeps); 118 | } 119 | 120 | /** 121 | * Converts the {@link Provider} into {@link ResolvedProvider}. 122 | * 123 | * {@link Injector} internally only uses {@link ResolvedProvider}, {@link Provider} contains 124 | * convenience provider syntax. 125 | */ 126 | function resolveReflectiveProvider(provider: NormalizedProvider): ResolvedReflectiveProvider { 127 | return new ResolvedReflectiveProvider_( 128 | ReflectiveKey.get(provider.provide), 129 | [resolveReflectiveFactory(provider)], 130 | provider.multi || false 131 | ); 132 | } 133 | 134 | /** 135 | * Resolve a list of Providers. 136 | */ 137 | export function resolveReflectiveProviders(providers: Provider[]): ResolvedReflectiveProvider[] { 138 | const normalized = _normalizeProviders(providers, []); 139 | const resolved = normalized.map(resolveReflectiveProvider); 140 | const resolvedProviderMap = mergeResolvedReflectiveProviders(resolved, new Map()); 141 | return Array.from(resolvedProviderMap.values()); 142 | } 143 | 144 | /** 145 | * Merges a list of ResolvedProviders into a list where 146 | * each key is contained exactly once and multi providers 147 | * have been merged. 148 | */ 149 | export function mergeResolvedReflectiveProviders( 150 | providers: ResolvedReflectiveProvider[], 151 | normalizedProvidersMap: Map 152 | ): Map { 153 | for (let i = 0; i < providers.length; i++) { 154 | const provider = providers[i]; 155 | const existing = normalizedProvidersMap.get(provider.key.id); 156 | if (existing) { 157 | if (provider.multiProvider !== existing.multiProvider) { 158 | throw mixingMultiProvidersWithRegularProvidersError(existing, provider); 159 | } 160 | if (provider.multiProvider) { 161 | for (let j = 0; j < provider.resolvedFactories.length; j++) { 162 | existing.resolvedFactories.push(provider.resolvedFactories[j]); 163 | } 164 | } else { 165 | normalizedProvidersMap.set(provider.key.id, provider); 166 | } 167 | } else { 168 | let resolvedProvider: ResolvedReflectiveProvider; 169 | if (provider.multiProvider) { 170 | resolvedProvider = new ResolvedReflectiveProvider_(provider.key, provider.resolvedFactories.slice(), provider.multiProvider); 171 | } else { 172 | resolvedProvider = provider; 173 | } 174 | normalizedProvidersMap.set(provider.key.id, resolvedProvider); 175 | } 176 | } 177 | return normalizedProvidersMap; 178 | } 179 | 180 | function _normalizeProviders(providers: Provider[], res: Provider[]): NormalizedProvider[] { 181 | providers.forEach((b) => { 182 | if (b instanceof Type) { 183 | res.push({ provide: b, useClass: b }); 184 | } else if (b && typeof b === 'object' && (b as any).provide !== undefined) { 185 | res.push(b as NormalizedProvider); 186 | } else if (b instanceof Array) { 187 | _normalizeProviders(b as Provider[], res); 188 | } else { 189 | throw invalidProviderError(b); 190 | } 191 | }); 192 | 193 | return res as NormalizedProvider[]; 194 | } 195 | 196 | export function constructDependencies(typeOrFunc: any, dependencies?: any[]): ReflectiveDependency[] { 197 | if (!dependencies) { 198 | return _dependenciesFor(typeOrFunc); 199 | } else { 200 | const params: any[][] = dependencies.map((t) => [t]); 201 | return dependencies.map((t) => _extractToken(typeOrFunc, t, params)); 202 | } 203 | } 204 | 205 | function _dependenciesFor(typeOrFunc: any): ReflectiveDependency[] { 206 | const params = reflector.parameters(typeOrFunc); 207 | 208 | if (!params) return []; 209 | if (params.some((p) => p == null)) { 210 | throw noAnnotationError(typeOrFunc, params); 211 | } 212 | return params.map((p) => _extractToken(typeOrFunc, p, params)); 213 | } 214 | 215 | function _extractToken(typeOrFunc: any, metadata: any[] | any, params: any[][]): ReflectiveDependency { 216 | let token: any = null; 217 | let optional = false; 218 | 219 | if (!Array.isArray(metadata)) { 220 | if (metadata instanceof Inject) { 221 | return _createDependency(metadata['token'], optional, null); 222 | } else { 223 | return _createDependency(metadata, optional, null); 224 | } 225 | } 226 | 227 | let visibility: Self | SkipSelf | null = null; 228 | 229 | for (let i = 0; i < metadata.length; ++i) { 230 | const paramMetadata = metadata[i]; 231 | 232 | if (paramMetadata instanceof Type) { 233 | token = paramMetadata; 234 | } else if (paramMetadata instanceof Inject) { 235 | token = paramMetadata['token']; 236 | } else if (paramMetadata instanceof Optional) { 237 | optional = true; 238 | } else if (paramMetadata instanceof Self || paramMetadata instanceof SkipSelf) { 239 | visibility = paramMetadata; 240 | } else if (paramMetadata instanceof InjectionToken) { 241 | token = paramMetadata; 242 | } 243 | } 244 | 245 | token = resolveForwardRef(token); 246 | 247 | if (token != null) { 248 | return _createDependency(token, optional, visibility); 249 | } else { 250 | throw noAnnotationError(typeOrFunc, params); 251 | } 252 | } 253 | 254 | function _createDependency(token: any, optional: boolean, visibility: Self | SkipSelf | null): ReflectiveDependency { 255 | return new ReflectiveDependency(ReflectiveKey.get(token), optional, visibility); 256 | } 257 | -------------------------------------------------------------------------------- /lib/util/decorators.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { global, stringify } from '../facade/lang'; 10 | import { Type } from '../facade/type'; 11 | 12 | let _nextClassId = 0; 13 | const Reflect = global['Reflect']; 14 | 15 | /** 16 | * Declares the interface to be used with {@link Class}. 17 | * 18 | * @stable 19 | */ 20 | export type ClassDefinition = { 21 | /** 22 | * Optional argument for specifying the superclass. 23 | */ 24 | extends?: Type; 25 | 26 | /** 27 | * Required constructor function for a class. 28 | * 29 | * The function may be optionally wrapped in an `Array`, in which case additional parameter 30 | * annotations may be specified. 31 | * The number of arguments and the number of parameter annotations must match. 32 | * 33 | * See {@link Class} for example of usage. 34 | */ 35 | constructor: Function | any[]; 36 | } & { 37 | /** 38 | * Other methods on the class. Note that values should have type 'Function' but TS requires 39 | * all properties to have a narrower type than the index signature. 40 | */ 41 | [x: string]: Type | Function | any[]; 42 | }; 43 | 44 | /** 45 | * An interface implemented by all Angular type decorators, which allows them to be used as ES7 46 | * decorators as well as 47 | * Angular DSL syntax. 48 | * 49 | * DSL syntax: 50 | * 51 | * ``` 52 | * var MyClass = ng 53 | * .Component({...}) 54 | * .Class({...}); 55 | * ``` 56 | * 57 | * ES7 syntax: 58 | * 59 | * ``` 60 | * @ng.Component({...}) 61 | * class MyClass {...} 62 | * ``` 63 | * @stable 64 | */ 65 | export interface TypeDecorator { 66 | /** 67 | * Invoke as ES7 decorator. 68 | */ 69 | >(type: T): T; 70 | 71 | // Make TypeDecorator assignable to built-in ParameterDecorator type. 72 | // ParameterDecorator is declared in lib.d.ts as a `declare type` 73 | // so we cannot declare this interface as a subtype. 74 | // see https://github.com/angular/angular/issues/3379#issuecomment-126169417 75 | (target: object, propertyKey?: string | symbol, parameterIndex?: number): void; 76 | 77 | /** 78 | * Storage for the accumulated annotations so far used by the DSL syntax. 79 | * 80 | * Used by {@link Class} to annotate the generated class. 81 | */ 82 | annotations: any[]; 83 | 84 | /** 85 | * Generate a class from the definition and annotate it with {@link TypeDecorator#annotations}. 86 | */ 87 | Class(obj: ClassDefinition): Type; 88 | } 89 | 90 | function extractAnnotation(annotation: any): any { 91 | if (typeof annotation === 'function' && annotation.hasOwnProperty('annotation')) { 92 | // it is a decorator, extract annotation 93 | annotation = annotation.annotation; 94 | } 95 | return annotation; 96 | } 97 | 98 | function applyParams(fnOrArray: Function | any[] | undefined, key: string): Function { 99 | if (fnOrArray === Object || fnOrArray === String || fnOrArray === Function || fnOrArray === Number || fnOrArray === Array) { 100 | throw new Error(`Can not use native ${stringify(fnOrArray)} as constructor`); 101 | } 102 | 103 | if (typeof fnOrArray === 'function') { 104 | return fnOrArray; 105 | } 106 | 107 | if (Array.isArray(fnOrArray)) { 108 | const annotations: any[] = fnOrArray as any[]; 109 | const annoLength = annotations.length - 1; 110 | const fn: Function = fnOrArray[annoLength]; 111 | if (typeof fn !== 'function') { 112 | throw new Error(`Last position of Class method array must be Function in key ${key} was '${stringify(fn)}'`); 113 | } 114 | if (annoLength !== fn.length) { 115 | throw new Error( 116 | `Number of annotations (${annoLength}) does not match number of arguments (${fn.length}) in the function: ${stringify(fn)}` 117 | ); 118 | } 119 | const paramsAnnotations: any[][] = []; 120 | for (let i = 0, ii = annotations.length - 1; i < ii; i++) { 121 | const paramAnnotations: any[] = []; 122 | paramsAnnotations.push(paramAnnotations); 123 | const annotation = annotations[i]; 124 | if (Array.isArray(annotation)) { 125 | for (let j = 0; j < annotation.length; j++) { 126 | paramAnnotations.push(extractAnnotation(annotation[j])); 127 | } 128 | } else if (typeof annotation === 'function') { 129 | paramAnnotations.push(extractAnnotation(annotation)); 130 | } else { 131 | paramAnnotations.push(annotation); 132 | } 133 | } 134 | Reflect.defineMetadata('parameters', paramsAnnotations, fn); 135 | return fn; 136 | } 137 | 138 | throw new Error(`Only Function or Array is supported in Class definition for key '${key}' is '${stringify(fnOrArray)}'`); 139 | } 140 | 141 | /** 142 | * Provides a way for expressing ES6 classes with parameter annotations in ES5. 143 | * 144 | * ## Basic Example 145 | * 146 | * ``` 147 | * var Greeter = ng.Class({ 148 | * constructor: function(name) { 149 | * this.name = name; 150 | * }, 151 | * 152 | * greet: function() { 153 | * alert('Hello ' + this.name + '!'); 154 | * } 155 | * }); 156 | * ``` 157 | * 158 | * is equivalent to ES6: 159 | * 160 | * ``` 161 | * class Greeter { 162 | * constructor(name) { 163 | * this.name = name; 164 | * } 165 | * 166 | * greet() { 167 | * alert('Hello ' + this.name + '!'); 168 | * } 169 | * } 170 | * ``` 171 | * 172 | * or equivalent to ES5: 173 | * 174 | * ``` 175 | * var Greeter = function (name) { 176 | * this.name = name; 177 | * } 178 | * 179 | * Greeter.prototype.greet = function () { 180 | * alert('Hello ' + this.name + '!'); 181 | * } 182 | * ``` 183 | * 184 | * ### Example with parameter annotations 185 | * 186 | * ``` 187 | * var MyService = ng.Class({ 188 | * constructor: [String, [new Optional(), Service], function(name, myService) { 189 | * ... 190 | * }] 191 | * }); 192 | * ``` 193 | * 194 | * is equivalent to ES6: 195 | * 196 | * ``` 197 | * class MyService { 198 | * constructor(name: string, @Optional() myService: Service) { 199 | * ... 200 | * } 201 | * } 202 | * ``` 203 | * 204 | * ### Example with inheritance 205 | * 206 | * ``` 207 | * var Shape = ng.Class({ 208 | * constructor: (color) { 209 | * this.color = color; 210 | * } 211 | * }); 212 | * 213 | * var Square = ng.Class({ 214 | * extends: Shape, 215 | * constructor: function(color, size) { 216 | * Shape.call(this, color); 217 | * this.size = size; 218 | * } 219 | * }); 220 | * ``` 221 | * @suppress {globalThis} 222 | * @stable 223 | */ 224 | export function Class(this: any, clsDef: ClassDefinition): Type { 225 | const constructor = applyParams(clsDef.hasOwnProperty('constructor') ? clsDef.constructor : undefined, 'constructor'); 226 | 227 | let proto = constructor.prototype; 228 | 229 | if (clsDef.hasOwnProperty('extends')) { 230 | if (typeof clsDef.extends === 'function') { 231 | (constructor).prototype = proto = Object.create((clsDef.extends).prototype); 232 | } else { 233 | throw new Error(`Class definition 'extends' property must be a constructor function was: ${stringify(clsDef.extends)}`); 234 | } 235 | } 236 | 237 | for (const key in clsDef) { 238 | if (key !== 'extends' && key !== 'prototype' && clsDef.hasOwnProperty(key)) { 239 | proto[key] = applyParams(clsDef[key], key); 240 | } 241 | } 242 | 243 | if (this && this.annotations instanceof Array) { 244 | Reflect.defineMetadata('annotations', this.annotations, constructor); 245 | } 246 | 247 | const constructorName = constructor['name']; 248 | if (!constructorName || constructorName === 'constructor') { 249 | (constructor as any)['overriddenName'] = `class${_nextClassId++}`; 250 | } 251 | 252 | return >constructor; 253 | } 254 | 255 | /** 256 | * @suppress {globalThis} 257 | */ 258 | export function makeDecorator( 259 | name: string, 260 | props: { [name: string]: any }, 261 | parentClass?: any, 262 | chainFn?: (fn: Function) => void 263 | ): (...args: any[]) => (cls: any) => any { 264 | const metaCtor = makeMetadataCtor([props]); 265 | 266 | function DecoratorFactory(this: any, objOrType: any): (cls: any) => any { 267 | if (!(Reflect && Reflect.getOwnMetadata)) { 268 | throw 'reflect-metadata shim is required when using class decorators'; 269 | } 270 | 271 | if (this instanceof DecoratorFactory) { 272 | metaCtor.call(this, objOrType); 273 | return this as typeof DecoratorFactory; 274 | } 275 | 276 | const annotationInstance = new (DecoratorFactory)(objOrType); 277 | const chainAnnotation = typeof this === 'function' && Array.isArray(this.annotations) ? this.annotations : []; 278 | chainAnnotation.push(annotationInstance); 279 | const TypeDecorator: TypeDecorator = function TypeDecorator(cls: Type) { 280 | const annotations = Reflect.getOwnMetadata('annotations', cls) || []; 281 | annotations.push(annotationInstance); 282 | Reflect.defineMetadata('annotations', annotations, cls); 283 | return cls; 284 | }; 285 | TypeDecorator.annotations = chainAnnotation; 286 | TypeDecorator.Class = Class; 287 | if (chainFn) chainFn(TypeDecorator); 288 | return TypeDecorator; 289 | } 290 | 291 | if (parentClass) { 292 | DecoratorFactory.prototype = Object.create(parentClass.prototype); 293 | } 294 | 295 | DecoratorFactory.prototype.toString = () => `@${name}`; 296 | (DecoratorFactory).annotationCls = DecoratorFactory; 297 | return DecoratorFactory; 298 | } 299 | 300 | function makeMetadataCtor(props: ([string, any] | { [key: string]: any })[]): any { 301 | return function ctor(this: any, ...args: any[]) { 302 | props.forEach((prop, i) => { 303 | const argVal = args[i]; 304 | if (Array.isArray(prop)) { 305 | // plain parameter 306 | this[prop[0]] = argVal === undefined ? prop[1] : argVal; 307 | } else { 308 | for (const propName in prop) { 309 | this[propName] = argVal && argVal.hasOwnProperty(propName) ? argVal[propName] : prop[propName]; 310 | } 311 | } 312 | }); 313 | }; 314 | } 315 | 316 | export function makeParamDecorator(name: string, props: ([string, any] | { [name: string]: any })[], parentClass?: any): any { 317 | const metaCtor = makeMetadataCtor(props); 318 | function ParamDecoratorFactory(this: unknown, ...args: any[]): any { 319 | if (this instanceof ParamDecoratorFactory) { 320 | metaCtor.apply(this, args); 321 | return this; 322 | } 323 | const annotationInstance = new (ParamDecoratorFactory)(...args); 324 | 325 | (ParamDecorator).annotation = annotationInstance; 326 | return ParamDecorator; 327 | 328 | function ParamDecorator(cls: any, unusedKey: any, index: number): any { 329 | const parameters: (any[] | null)[] = Reflect.getOwnMetadata('parameters', cls) || []; 330 | 331 | // there might be gaps if some in between parameters do not have annotations. 332 | // we pad with nulls. 333 | while (parameters.length <= index) { 334 | parameters.push(null); 335 | } 336 | 337 | parameters[index] = parameters[index] || []; 338 | parameters[index]!.push(annotationInstance); 339 | 340 | Reflect.defineMetadata('parameters', parameters, cls); 341 | return cls; 342 | } 343 | } 344 | if (parentClass) { 345 | ParamDecoratorFactory.prototype = Object.create(parentClass.prototype); 346 | } 347 | ParamDecoratorFactory.prototype.toString = () => `@${name}`; 348 | (ParamDecoratorFactory).annotationCls = ParamDecoratorFactory; 349 | return ParamDecoratorFactory; 350 | } 351 | 352 | export function makePropDecorator(name: string, props: ([string, any] | { [key: string]: any })[], parentClass?: any): any { 353 | const metaCtor = makeMetadataCtor(props); 354 | 355 | function PropDecoratorFactory(this: unknown, ...args: any[]): any { 356 | if (this instanceof PropDecoratorFactory) { 357 | metaCtor.apply(this, args); 358 | return this; 359 | } 360 | 361 | const decoratorInstance = new (PropDecoratorFactory)(...args); 362 | 363 | return function PropDecorator(target: any, name: string) { 364 | const meta = Reflect.getOwnMetadata('propMetadata', target.constructor) || {}; 365 | meta[name] = (meta.hasOwnProperty(name) && meta[name]) || []; 366 | meta[name].unshift(decoratorInstance); 367 | Reflect.defineMetadata('propMetadata', meta, target.constructor); 368 | }; 369 | } 370 | 371 | if (parentClass) { 372 | PropDecoratorFactory.prototype = Object.create(parentClass.prototype); 373 | } 374 | 375 | PropDecoratorFactory.prototype.toString = () => `@${name}`; 376 | (PropDecoratorFactory).annotationCls = PropDecoratorFactory; 377 | return PropDecoratorFactory; 378 | } 379 | -------------------------------------------------------------------------------- /lib/util/resolve_dependencies.ts: -------------------------------------------------------------------------------- 1 | import { ReflectiveInjector } from '../reflective_injector'; 2 | import { ResolvedReflectiveProvider, ResolvedReflectiveFactory, ReflectiveDependency } from '../reflective_provider'; 3 | 4 | type Constructor = new (...args: any[]) => any; 5 | 6 | /** 7 | * This utility function receives a spread of injectable classes 8 | * and returns an array of all their dependencies. Also resolves 9 | * optional dependencies. 10 | * 11 | * ### Important: 12 | * 13 | * Dynamically resolving dependencies using this function 14 | * will not play nice with static analysis tools, including tree-shaking. 15 | * From a static analysis perspective, any dependencies which are only resolved 16 | * using this function will look as though they are not used (and will be 17 | * removed by tree-shaking). This *severely* limits the usefulness of this function. 18 | * 19 | * ### Example: 20 | * 21 | * ```typescript 22 | * class HTTP {} 23 | * class Database {} 24 | * 25 | * // commenting out the decorator because the `@` symbol is spoiling 26 | * // jsDoc rendering in vscode 27 | * // @Injectable() 28 | * class PersonService { 29 | * constructor( 30 | * private http: HTTP, 31 | * private database: Database, 32 | * ) {} 33 | * } 34 | * 35 | * // @Injectable() 36 | * class OrganizationService { 37 | * constructor( 38 | * private http: HTTP, 39 | * private personService: PersonService, 40 | * ) {} 41 | * } 42 | * 43 | * const injector = ReflectiveInjector.resolveAndCreate( 44 | * resolveDependencies(OrganizationService) 45 | * ); 46 | * 47 | * const organizationService = injector.get(OrganizationService); 48 | * ``` 49 | */ 50 | export function resolveDependencies(...inputs: Constructor[]) { 51 | const deps = new Set(); 52 | 53 | function resolver(klass: Constructor) { 54 | if (deps.has(klass)) return; 55 | 56 | deps.add(klass); 57 | 58 | // resolve all dependencies of the provided class and run the `resolver()` function 59 | // on their constructor functions. 60 | ReflectiveInjector.resolve([klass]) 61 | .reduce((a, x: ResolvedReflectiveProvider) => a.concat(x.resolvedFactories), [] as ResolvedReflectiveFactory[]) 62 | .reduce((a, r: ResolvedReflectiveFactory) => a.concat(r.dependencies), [] as ReflectiveDependency[]) 63 | .forEach((d) => resolver(d.key.token as Constructor)); 64 | } 65 | 66 | for (const input of inputs) { 67 | resolver(input); 68 | } 69 | 70 | return Array.from(deps); 71 | } 72 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "injection-js", 3 | "version": "2.5.0", 4 | "description": "Dependency Injection library for JavaScript and TypeScript", 5 | "main": "injection.bundle.js", 6 | "module": "index.js", 7 | "jsnext:main": "index.js", 8 | "types": "index.d.ts", 9 | "engines": { 10 | "node": ">=8.5" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/mgechev/injection-js.git" 15 | }, 16 | "dependencies": { 17 | "tslib": "^2.0.0" 18 | }, 19 | "devDependencies": { 20 | "@eslint/eslintrc": "^3.3.1", 21 | "@eslint/js": "^9.25.1", 22 | "@types/jasmine": "^5.1.7", 23 | "@types/node": "^22.14.1", 24 | "@typescript-eslint/eslint-plugin": "^8.31.0", 25 | "@typescript-eslint/parser": "^8.31.0", 26 | "eslint": "^9.25.1", 27 | "eslint-config-prettier": "^10.1.2", 28 | "eslint-plugin-prettier": "^5.2.6", 29 | "globals": "^16.0.0", 30 | "jasmine": "^5.6.0", 31 | "prettier": "^3.5.3", 32 | "reflect-metadata": "^0.2.2", 33 | "rimraf": "^6.0.1", 34 | "rollup": "^4.40.0", 35 | "typescript": "^5.8.3" 36 | }, 37 | "scripts": { 38 | "prebuild": "npm run verify && npm t", 39 | "build": "rimraf dist && tsc && rollup -c rollup.config.js -i dist/index.js > dist/injection.bundle.js && node tools/copy.js", 40 | "pretest": "rimraf dist/test && tsc -p tsconfig-es2015.test.json", 41 | "test": "jasmine", 42 | "format": "eslint -c eslint.config.mjs lib/**/*.ts --fix && eslint -c eslint.config.mjs test/*.ts --fix", 43 | "lint": "eslint -c eslint.config.mjs lib/**/*.ts && eslint -c eslint.config.mjs test/*.ts", 44 | "verify": "tsc -p tools && npm run format && npm run lint" 45 | }, 46 | "keywords": [ 47 | "DI", 48 | "dependency", 49 | "injection", 50 | "dependency injection", 51 | "injector" 52 | ], 53 | "author": "Minko Gechev ", 54 | "license": "MIT" 55 | } 56 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | output: { 3 | format: 'umd', 4 | name: 'injection-js', 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /spec/support/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "spec_dir": "dist/test", 3 | "spec_files": [ 4 | "**/*_spec.js" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/forward_ref_spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { Type } from '../lib/facade/type'; 10 | 11 | import { forwardRef, resolveForwardRef } from '../lib'; 12 | 13 | describe('forwardRef', function () { 14 | it('should wrap and unwrap the reference', () => { 15 | const ref = forwardRef(() => String); 16 | expect(ref instanceof Type).toBe(true); 17 | expect(resolveForwardRef(ref)).toBe(String); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/injector_spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { Injector } from '../lib'; 10 | 11 | describe('Injector.NULL', () => { 12 | it('should throw if no arg is given', () => { 13 | expect(() => Injector.NULL.get('someToken')).toThrowError('No provider for someToken!'); 14 | }); 15 | 16 | it('should throw if THROW_IF_NOT_FOUND is given', () => { 17 | expect(() => Injector.NULL.get('someToken', Injector.THROW_IF_NOT_FOUND)).toThrowError('No provider for someToken!'); 18 | }); 19 | 20 | it('should return the default value', () => { 21 | expect(Injector.NULL.get('someToken', 'notFound')).toEqual('notFound'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/reflective_injector_spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import 'reflect-metadata'; 10 | 11 | import { 12 | Inject, 13 | Injectable, 14 | InjectionToken, 15 | Injector, 16 | Optional, 17 | Provider, 18 | ReflectiveInjector, 19 | ReflectiveKey, 20 | Self, 21 | forwardRef, 22 | inject, 23 | } from '../lib'; 24 | import { ReflectiveInjector_ } from '../lib/reflective_injector'; 25 | import { ResolvedReflectiveProvider_ } from '../lib/reflective_provider'; 26 | import { getOriginalError } from '../lib/facade/errors'; 27 | 28 | import { isPresent, stringify } from '../lib/facade/lang'; 29 | 30 | class Engine {} 31 | 32 | class BrokenEngine { 33 | constructor() { 34 | throw new Error('Broken Engine'); 35 | } 36 | } 37 | 38 | class DashboardSoftware {} 39 | 40 | @Injectable() 41 | class Dashboard { 42 | constructor(software: DashboardSoftware) {} 43 | } 44 | 45 | class GloveboxManual {} 46 | 47 | @Injectable() 48 | class Glovebox { 49 | manual = inject(GloveboxManual); 50 | } 51 | 52 | class TurboEngine extends Engine {} 53 | 54 | @Injectable() 55 | class Car { 56 | constructor(public engine: Engine) {} 57 | } 58 | 59 | @Injectable() 60 | class CarWithOptionalEngine { 61 | constructor(@Optional() public engine: Engine) {} 62 | } 63 | 64 | @Injectable() 65 | class CarWithDashboard { 66 | engine: Engine; 67 | dashboard: Dashboard; 68 | constructor(engine: Engine, dashboard: Dashboard) { 69 | this.engine = engine; 70 | this.dashboard = dashboard; 71 | } 72 | } 73 | 74 | @Injectable() 75 | class SportsCar extends Car {} 76 | 77 | @Injectable() 78 | class CarWithInject { 79 | constructor(@Inject(TurboEngine) public engine: Engine) {} 80 | } 81 | 82 | @Injectable() 83 | class CyclicEngine { 84 | constructor(car: Car) {} 85 | } 86 | 87 | class NoAnnotations { 88 | constructor(secretDependency: any) {} 89 | } 90 | 91 | function factoryFn(a: any) {} 92 | 93 | const dynamicProviders = [ 94 | { provide: 'provider0', useValue: 1 }, 95 | { provide: 'provider1', useValue: 1 }, 96 | { provide: 'provider2', useValue: 1 }, 97 | { provide: 'provider3', useValue: 1 }, 98 | { provide: 'provider4', useValue: 1 }, 99 | { provide: 'provider5', useValue: 1 }, 100 | { provide: 'provider6', useValue: 1 }, 101 | { provide: 'provider7', useValue: 1 }, 102 | { provide: 'provider8', useValue: 1 }, 103 | { provide: 'provider9', useValue: 1 }, 104 | { provide: 'provider10', useValue: 1 }, 105 | ]; 106 | 107 | function createInjector(providers: Provider[], parent: ReflectiveInjector | null = null): ReflectiveInjector_ { 108 | const resolvedProviders = ReflectiveInjector.resolve(providers.concat(dynamicProviders)); 109 | if (isPresent(parent)) { 110 | return parent.createChildFromResolved(resolvedProviders) as ReflectiveInjector_; 111 | } else { 112 | return ReflectiveInjector.fromResolvedProviders(resolvedProviders) as ReflectiveInjector_; 113 | } 114 | } 115 | 116 | describe(`injector`, () => { 117 | it('should instantiate a class without dependencies', () => { 118 | const injector = createInjector([Engine]); 119 | const engine = injector.get(Engine); 120 | 121 | expect(engine instanceof Engine).toBeTruthy(); 122 | }); 123 | 124 | it('should resolve dependencies based on type information', () => { 125 | const injector = createInjector([Engine, Car]); 126 | const car = injector.get(Car); 127 | 128 | expect(car instanceof Car).toBeTruthy(); 129 | expect(car.engine instanceof Engine).toBeTruthy(); 130 | }); 131 | 132 | it('should resolve dependencies based on @Inject annotation', () => { 133 | const injector = createInjector([TurboEngine, Engine, CarWithInject]); 134 | const car = injector.get(CarWithInject); 135 | 136 | expect(car instanceof CarWithInject).toBeTruthy(); 137 | expect(car.engine instanceof TurboEngine).toBeTruthy(); 138 | }); 139 | 140 | it('should throw when no type and not @Inject (class case)', () => { 141 | expect(() => createInjector([NoAnnotations])).toThrowError( 142 | "Cannot resolve all parameters for 'NoAnnotations'(?). " + 143 | 'Make sure that all the parameters are decorated with Inject or have valid type annotations ' + 144 | "and that 'NoAnnotations' is decorated with Injectable." 145 | ); 146 | }); 147 | 148 | it('should throw when no type and not @Inject (factory case)', () => { 149 | expect(() => createInjector([{ provide: 'someToken', useFactory: factoryFn }])).toThrowError( 150 | "Cannot resolve all parameters for 'factoryFn'(?). " + 151 | 'Make sure that all the parameters are decorated with Inject or have valid type annotations ' + 152 | "and that 'factoryFn' is decorated with Injectable." 153 | ); 154 | }); 155 | 156 | it('should cache instances', () => { 157 | const injector = createInjector([Engine]); 158 | 159 | const e1 = injector.get(Engine); 160 | const e2 = injector.get(Engine); 161 | 162 | expect(e1).toBe(e2); 163 | }); 164 | 165 | it('should provide to a value', () => { 166 | const injector = createInjector([{ provide: Engine, useValue: 'fake engine' }]); 167 | 168 | const engine = injector.get(Engine); 169 | expect(engine).toEqual('fake engine'); 170 | }); 171 | 172 | it('should inject dependencies instance of InjectionToken', () => { 173 | const TOKEN = new InjectionToken('token'); 174 | 175 | const injector = createInjector([ 176 | { provide: TOKEN, useValue: 'by token' }, 177 | { provide: Engine, useFactory: (v: string) => v, deps: [[TOKEN]] }, 178 | ]); 179 | 180 | const engine = injector.get(Engine); 181 | expect(engine).toEqual('by token'); 182 | }); 183 | 184 | it('should provide to a factory', () => { 185 | function sportsCarFactory(e: any) { 186 | return new SportsCar(e); 187 | } 188 | 189 | const injector = createInjector([Engine, { provide: Car, useFactory: sportsCarFactory, deps: [Engine] }]); 190 | 191 | const car = injector.get(Car); 192 | expect(car instanceof SportsCar).toBeTruthy(); 193 | expect(car.engine instanceof Engine).toBeTruthy(); 194 | }); 195 | 196 | it('should supporting provider to null', () => { 197 | const injector = createInjector([{ provide: Engine, useValue: null }]); 198 | const engine = injector.get(Engine); 199 | expect(engine).toBeNull(); 200 | }); 201 | 202 | it('should provide to an alias', () => { 203 | const injector = createInjector([Engine, { provide: SportsCar, useClass: SportsCar }, { provide: Car, useExisting: SportsCar }]); 204 | 205 | const car = injector.get(Car); 206 | const sportsCar = injector.get(SportsCar); 207 | expect(car instanceof SportsCar).toBeTruthy(); 208 | expect(car).toBe(sportsCar); 209 | }); 210 | 211 | it('should support multiProviders', () => { 212 | const injector = createInjector([ 213 | Engine, 214 | { provide: Car, useClass: SportsCar, multi: true }, 215 | { provide: Car, useClass: CarWithOptionalEngine, multi: true }, 216 | ]); 217 | 218 | const cars = injector.get(Car); 219 | expect(cars.length).toEqual(2); 220 | expect(cars[0] instanceof SportsCar).toBeTruthy(); 221 | expect(cars[1] instanceof CarWithOptionalEngine).toBeTruthy(); 222 | }); 223 | 224 | it('should support multiProviders that are created using useExisting', () => { 225 | const injector = createInjector([Engine, SportsCar, { provide: Car, useExisting: SportsCar, multi: true }]); 226 | 227 | const cars = injector.get(Car); 228 | expect(cars.length).toEqual(1); 229 | expect(cars[0]).toBe(injector.get(SportsCar)); 230 | }); 231 | 232 | it('should throw when the aliased provider does not exist', () => { 233 | const injector = createInjector([{ provide: 'car', useExisting: SportsCar }]); 234 | const e = `No provider for ${stringify(SportsCar)}! (car -> ${stringify(SportsCar)})`; 235 | expect(() => injector.get('car')).toThrowError(e); 236 | }); 237 | 238 | it('should handle forwardRef in useExisting', () => { 239 | const injector = createInjector([ 240 | { provide: 'originalEngine', useClass: forwardRef(() => Engine) }, 241 | { 242 | provide: 'aliasedEngine', 243 | useExisting: forwardRef(() => 'originalEngine'), 244 | }, 245 | ]); 246 | expect(injector.get('aliasedEngine') instanceof Engine).toBeTruthy(); 247 | }); 248 | 249 | it('should support overriding factory dependencies', () => { 250 | const injector = createInjector([ 251 | Engine, 252 | { 253 | provide: Car, 254 | useFactory: (e: Engine) => new SportsCar(e), 255 | deps: [Engine], 256 | }, 257 | ]); 258 | 259 | const car = injector.get(Car); 260 | expect(car instanceof SportsCar).toBeTruthy(); 261 | expect(car.engine instanceof Engine).toBeTruthy(); 262 | }); 263 | 264 | it('should support optional dependencies', () => { 265 | const injector = createInjector([CarWithOptionalEngine]); 266 | 267 | const car = injector.get(CarWithOptionalEngine); 268 | expect(car.engine).toEqual(null); 269 | }); 270 | 271 | it('should flatten passed-in providers', () => { 272 | const injector = createInjector([[[Engine, Car]]]); 273 | 274 | const car = injector.get(Car); 275 | expect(car instanceof Car).toBeTruthy(); 276 | }); 277 | 278 | it('should use the last provider when there are multiple providers for same token', () => { 279 | const injector = createInjector([ 280 | { provide: Engine, useClass: Engine }, 281 | { provide: Engine, useClass: TurboEngine }, 282 | ]); 283 | 284 | expect(injector.get(Engine) instanceof TurboEngine).toBeTruthy(); 285 | }); 286 | 287 | it('should use non-type tokens', () => { 288 | const injector = createInjector([{ provide: 'token', useValue: 'value' }]); 289 | 290 | expect(injector.get('token')).toEqual('value'); 291 | }); 292 | 293 | it('should throw when given invalid providers', () => { 294 | expect(() => createInjector(['blah'])).toThrowError( 295 | 'Invalid provider - only instances of Provider and Type are allowed, got: blah' 296 | ); 297 | }); 298 | 299 | it('should provide itself', () => { 300 | const parent = createInjector([]); 301 | const child = parent.resolveAndCreateChild([]); 302 | 303 | expect(child.get(Injector)).toBe(child); 304 | }); 305 | 306 | it('should throw when no provider defined', () => { 307 | const injector = createInjector([]); 308 | expect(() => injector.get('NonExisting')).toThrowError('No provider for NonExisting!'); 309 | }); 310 | 311 | it('should show the full path when no provider', () => { 312 | const injector = createInjector([CarWithDashboard, Engine, Dashboard]); 313 | expect(() => injector.get(CarWithDashboard)).toThrowError( 314 | `No provider for DashboardSoftware! (${stringify(CarWithDashboard)} -> ${stringify(Dashboard)} -> DashboardSoftware)` 315 | ); 316 | }); 317 | 318 | it('should throw when trying to instantiate a cyclic dependency', () => { 319 | const injector = createInjector([Car, { provide: Engine, useClass: CyclicEngine }]); 320 | 321 | expect(() => injector.get(Car)).toThrowError( 322 | `Cannot instantiate cyclic dependency! (${stringify(Car)} -> ${stringify(Engine)} -> ${stringify(Car)})` 323 | ); 324 | }); 325 | 326 | it('should show the full path when error happens in a constructor', () => { 327 | const providers = ReflectiveInjector.resolve([Car, { provide: Engine, useClass: BrokenEngine }]); 328 | const injector = new ReflectiveInjector_(providers); 329 | 330 | try { 331 | injector.get(Car); 332 | throw 'Must throw'; 333 | } catch (e: any) { 334 | expect(e.message).toContain(`Error during instantiation of Engine! (${stringify(Car)} -> Engine)`); 335 | expect(getOriginalError(e) instanceof Error).toBeTruthy(); 336 | expect(e.keys[0].token).toEqual(Engine); 337 | } 338 | }); 339 | 340 | it('should instantiate an object after a failed attempt', () => { 341 | let isBroken = true; 342 | 343 | const injector = createInjector([ 344 | Car, 345 | { 346 | provide: Engine, 347 | useFactory: () => (isBroken ? new BrokenEngine() : new Engine()), 348 | }, 349 | ]); 350 | 351 | expect(() => injector.get(Car)).toThrowError('Broken Engine: Error during instantiation of Engine! (Car -> Engine).'); 352 | 353 | isBroken = false; 354 | 355 | expect(injector.get(Car) instanceof Car).toBeTruthy(); 356 | }); 357 | 358 | it('should support null values', () => { 359 | const injector = createInjector([{ provide: 'null', useValue: null }]); 360 | expect(injector.get('null')).toBe(null); 361 | }); 362 | 363 | it('should support the inject() function', () => { 364 | const injector = createInjector([Glovebox, GloveboxManual]); 365 | const glovebox = injector.get(Glovebox); 366 | expect(glovebox instanceof Glovebox).toBe(true); 367 | expect(glovebox.manual instanceof GloveboxManual).toBe(true); 368 | }); 369 | }); 370 | 371 | describe('child', () => { 372 | it('should load instances from parent injector', () => { 373 | const parent = ReflectiveInjector.resolveAndCreate([Engine]); 374 | const child = parent.resolveAndCreateChild([]); 375 | 376 | const engineFromParent = parent.get(Engine); 377 | const engineFromChild = child.get(Engine); 378 | 379 | expect(engineFromChild).toBe(engineFromParent); 380 | }); 381 | 382 | it('should not use the child providers when resolving the dependencies of a parent provider', () => { 383 | const parent = ReflectiveInjector.resolveAndCreate([Car, Engine]); 384 | const child = parent.resolveAndCreateChild([{ provide: Engine, useClass: TurboEngine }]); 385 | 386 | const carFromChild = child.get(Car); 387 | expect(carFromChild.engine instanceof Engine).toBeTruthy(); 388 | }); 389 | 390 | it('should create new instance in a child injector', () => { 391 | const parent = ReflectiveInjector.resolveAndCreate([Engine]); 392 | const child = parent.resolveAndCreateChild([{ provide: Engine, useClass: TurboEngine }]); 393 | 394 | const engineFromParent = parent.get(Engine); 395 | const engineFromChild = child.get(Engine); 396 | 397 | expect(engineFromParent).not.toBe(engineFromChild); 398 | expect(engineFromChild instanceof TurboEngine).toBeTruthy(); 399 | }); 400 | 401 | it('should give access to parent', () => { 402 | const parent = ReflectiveInjector.resolveAndCreate([]); 403 | const child = parent.resolveAndCreateChild([]); 404 | expect(child.parent).toBe(parent); 405 | }); 406 | }); 407 | 408 | describe('resolveAndInstantiate', () => { 409 | it('should instantiate an object in the context of the injector', () => { 410 | const inj = ReflectiveInjector.resolveAndCreate([Engine]); 411 | const car = inj.resolveAndInstantiate(Car); 412 | expect(car instanceof Car).toBeTruthy(); 413 | expect(car.engine).toBe(inj.get(Engine)); 414 | }); 415 | 416 | it('should not store the instantiated object in the injector', () => { 417 | const inj = ReflectiveInjector.resolveAndCreate([Engine]); 418 | inj.resolveAndInstantiate(Car); 419 | expect(() => inj.get(Car)).toThrowError(); 420 | }); 421 | }); 422 | 423 | describe('instantiate', () => { 424 | it('should instantiate an object in the context of the injector', () => { 425 | const inj = ReflectiveInjector.resolveAndCreate([Engine]); 426 | const car = inj.instantiateResolved(ReflectiveInjector.resolve([Car])[0]); 427 | expect(car instanceof Car).toBeTruthy(); 428 | expect(car.engine).toBe(inj.get(Engine)); 429 | }); 430 | }); 431 | 432 | describe('depedency resolution', () => { 433 | describe('@Self()', () => { 434 | it('should return a dependency from self', () => { 435 | const inj = ReflectiveInjector.resolveAndCreate([ 436 | Engine, 437 | { 438 | provide: Car, 439 | useFactory: (e: Engine) => new Car(e), 440 | deps: [[Engine, new Self()]], 441 | }, 442 | ]); 443 | 444 | expect(inj.get(Car) instanceof Car).toBeTruthy(); 445 | }); 446 | 447 | it('should throw when not requested provider on self', () => { 448 | const parent = ReflectiveInjector.resolveAndCreate([Engine]); 449 | const child = parent.resolveAndCreateChild([ 450 | { 451 | provide: Car, 452 | useFactory: (e: Engine) => new Car(e), 453 | deps: [[Engine, new Self()]], 454 | }, 455 | ]); 456 | 457 | expect(() => child.get(Car)).toThrowError(`No provider for Engine! (${stringify(Car)} -> ${stringify(Engine)})`); 458 | }); 459 | }); 460 | 461 | describe('default', () => { 462 | it('should not skip self', () => { 463 | const parent = ReflectiveInjector.resolveAndCreate([Engine]); 464 | const child = parent.resolveAndCreateChild([ 465 | { provide: Engine, useClass: TurboEngine }, 466 | { provide: Car, useFactory: (e: Engine) => new Car(e), deps: [Engine] }, 467 | ]); 468 | 469 | expect(child.get(Car).engine instanceof TurboEngine).toBeTruthy(); 470 | }); 471 | }); 472 | }); 473 | 474 | describe('resolve', () => { 475 | it('should resolve and flatten', () => { 476 | const providers = ReflectiveInjector.resolve([Engine, [BrokenEngine]]); 477 | providers.forEach(function (b) { 478 | if (!b) return; // the result is a sparse array 479 | expect(b instanceof ResolvedReflectiveProvider_).toBe(true); 480 | }); 481 | }); 482 | 483 | it('should support multi providers', () => { 484 | const provider = ReflectiveInjector.resolve([ 485 | { provide: Engine, useClass: BrokenEngine, multi: true }, 486 | { provide: Engine, useClass: TurboEngine, multi: true }, 487 | ])[0]; 488 | 489 | expect(provider.key.token).toBe(Engine); 490 | expect(provider.multiProvider).toEqual(true); 491 | expect(provider.resolvedFactories.length).toEqual(2); 492 | }); 493 | 494 | it('should support providers as hash', () => { 495 | const provider = ReflectiveInjector.resolve([ 496 | { provide: Engine, useClass: BrokenEngine, multi: true }, 497 | { provide: Engine, useClass: TurboEngine, multi: true }, 498 | ])[0]; 499 | 500 | expect(provider.key.token).toBe(Engine); 501 | expect(provider.multiProvider).toEqual(true); 502 | expect(provider.resolvedFactories.length).toEqual(2); 503 | }); 504 | 505 | it('should support multi providers with only one provider', () => { 506 | const provider = ReflectiveInjector.resolve([{ provide: Engine, useClass: BrokenEngine, multi: true }])[0]; 507 | 508 | expect(provider.key.token).toBe(Engine); 509 | expect(provider.multiProvider).toEqual(true); 510 | expect(provider.resolvedFactories.length).toEqual(1); 511 | }); 512 | 513 | it('should throw when mixing multi providers with regular providers', () => { 514 | expect(() => { 515 | ReflectiveInjector.resolve([{ provide: Engine, useClass: BrokenEngine, multi: true }, Engine]); 516 | }).toThrowError(/Cannot mix multi providers and regular providers/); 517 | 518 | expect(() => { 519 | ReflectiveInjector.resolve([Engine, { provide: Engine, useClass: BrokenEngine, multi: true }]); 520 | }).toThrowError(/Cannot mix multi providers and regular providers/); 521 | }); 522 | 523 | it('should resolve forward references', () => { 524 | const providers = ReflectiveInjector.resolve([ 525 | forwardRef(() => Engine), 526 | [ 527 | { 528 | provide: forwardRef(() => BrokenEngine), 529 | useClass: forwardRef(() => Engine), 530 | }, 531 | ], 532 | { 533 | provide: forwardRef(() => String), 534 | useFactory: () => 'OK', 535 | deps: [forwardRef(() => Engine)], 536 | }, 537 | ]); 538 | 539 | const engineProvider = providers[0]; 540 | const brokenEngineProvider = providers[1]; 541 | const stringProvider = providers[2]; 542 | 543 | expect(engineProvider.resolvedFactories[0].factory() instanceof Engine).toBe(true); 544 | expect(brokenEngineProvider.resolvedFactories[0].factory() instanceof Engine).toBe(true); 545 | expect(stringProvider.resolvedFactories[0].dependencies[0].key).toEqual(ReflectiveKey.get(Engine)); 546 | }); 547 | 548 | it('should support overriding factory dependencies with dependency annotations', () => { 549 | const providers = ReflectiveInjector.resolve([ 550 | { 551 | provide: 'token', 552 | useFactory: (e: any /** TODO #9100 */) => 'result', 553 | deps: [[new Inject('dep')]], 554 | }, 555 | ]); 556 | 557 | const provider = providers[0]; 558 | 559 | expect(provider.resolvedFactories[0].dependencies[0].key.token).toEqual('dep'); 560 | }); 561 | 562 | it('should allow declaring dependencies with flat arrays', () => { 563 | const resolved = ReflectiveInjector.resolve([ 564 | { 565 | provide: 'token', 566 | useFactory: (e: any) => e, 567 | deps: [new Inject('dep')], 568 | }, 569 | ]); 570 | const nestedResolved = ReflectiveInjector.resolve([ 571 | { 572 | provide: 'token', 573 | useFactory: (e: any) => e, 574 | deps: [[new Inject('dep')]], 575 | }, 576 | ]); 577 | expect(resolved[0].resolvedFactories[0].dependencies[0].key.token).toEqual( 578 | nestedResolved[0].resolvedFactories[0].dependencies[0].key.token 579 | ); 580 | }); 581 | }); 582 | 583 | describe('displayName', () => { 584 | it('should work', () => { 585 | expect((ReflectiveInjector.resolveAndCreate([Engine, BrokenEngine])).displayName).toEqual( 586 | 'ReflectiveInjector(providers: [ "Engine" , "BrokenEngine" ])' 587 | ); 588 | }); 589 | }); 590 | -------------------------------------------------------------------------------- /test/reflective_key_spec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import { KeyRegistry } from '../lib/reflective_key'; 10 | 11 | describe('key', function () { 12 | let registry: KeyRegistry; 13 | 14 | beforeEach(function () { 15 | registry = new KeyRegistry(); 16 | }); 17 | 18 | it('should be equal to another key if type is the same', function () { 19 | expect(registry.get('car')).toBe(registry.get('car')); 20 | }); 21 | 22 | it('should not be equal to another key if types are different', function () { 23 | expect(registry.get('car')).not.toBe(registry.get('porsche')); 24 | }); 25 | 26 | it('should return the passed in key', function () { 27 | expect(registry.get(registry.get('car'))).toBe(registry.get('car')); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/resolve_dependencies_spec.ts: -------------------------------------------------------------------------------- 1 | import { resolveDependencies } from '../lib/util/resolve_dependencies'; 2 | import { Injectable, Optional, Inject, Provider } from '../lib'; 3 | import { ReflectiveInjector } from '../lib/reflective_injector'; 4 | 5 | class Engine {} 6 | 7 | class DashboardSoftware {} 8 | 9 | @Injectable() 10 | class Dashboard { 11 | constructor(software: DashboardSoftware) {} 12 | } 13 | 14 | class TurboEngine extends Engine {} 15 | 16 | @Injectable() 17 | class CarWithDashboard { 18 | engine: Engine; 19 | dashboard: Dashboard; 20 | constructor(engine: Engine, dashboard: Dashboard) { 21 | this.engine = engine; 22 | this.dashboard = dashboard; 23 | } 24 | } 25 | 26 | @Injectable() 27 | class CarWithOptionalEngine { 28 | constructor(@Optional() public engine: Engine) {} 29 | } 30 | 31 | @Injectable() 32 | class CarWithInject { 33 | constructor(@Inject(TurboEngine) public engine: Engine) {} 34 | } 35 | 36 | function createInjector(providers: Provider[]): ReflectiveInjector { 37 | return ReflectiveInjector.resolveAndCreate(providers); 38 | } 39 | 40 | describe('resolveDependencies', function () { 41 | let deps: Array any>; 42 | let injector: ReflectiveInjector | null; 43 | 44 | beforeEach(function () { 45 | deps = []; 46 | injector = null; 47 | }); 48 | 49 | it('should resolve direct dependencies', function () { 50 | deps = resolveDependencies(Dashboard); 51 | 52 | expect(deps).toEqual([Dashboard, DashboardSoftware]); 53 | 54 | injector = createInjector(deps); 55 | 56 | expect(injector.get(Dashboard) instanceof Dashboard).toBe(true); 57 | }); 58 | 59 | it('should resolve dependencies of dependencies', function () { 60 | deps = resolveDependencies(CarWithDashboard); 61 | 62 | expect(deps).toEqual([CarWithDashboard, Engine, Dashboard, DashboardSoftware]); 63 | 64 | injector = createInjector(deps); 65 | 66 | expect(injector.get(CarWithDashboard) instanceof CarWithDashboard).toBe(true); 67 | }); 68 | 69 | it('should resolve optional dependencies', function () { 70 | deps = resolveDependencies(CarWithOptionalEngine); 71 | 72 | expect(deps).toEqual([CarWithOptionalEngine, Engine]); 73 | 74 | injector = createInjector(deps); 75 | 76 | expect(injector.get(CarWithOptionalEngine) instanceof CarWithOptionalEngine).toBe(true); 77 | }); 78 | 79 | it('should resolve re-provided dependencies', function () { 80 | deps = resolveDependencies(CarWithInject); 81 | 82 | expect(deps).toEqual([CarWithInject, TurboEngine]); 83 | 84 | injector = createInjector(deps); 85 | 86 | expect(injector.get(CarWithInject) instanceof CarWithInject).toBe(true); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /tools/copy.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { writeFileSync, copyFileSync } = require('fs'); 3 | const { resolve } = require('path'); 4 | const packageJson = require('../package.json'); 5 | 6 | main(); 7 | 8 | function main() { 9 | const projectRoot = resolve(__dirname, '..'); 10 | const distPath = resolve(projectRoot, 'dist'); 11 | const distPackageJson = createDistPackageJson(packageJson); 12 | 13 | copyFileSync(resolve(projectRoot, 'README.md'), resolve(distPath, 'README.md')); 14 | writeFileSync(resolve(distPath, 'package.json'), distPackageJson); 15 | } 16 | 17 | /** 18 | * @param {typeof packageJson} packageConfig 19 | * @return {string} 20 | */ 21 | function createDistPackageJson(packageConfig) { 22 | const { devDependencies, scripts, engines, ...distPackageJson } = packageConfig; 23 | 24 | return JSON.stringify(distPackageJson, null, 2); 25 | } 26 | -------------------------------------------------------------------------------- /tools/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "commonjs", 5 | "strict": true, 6 | "allowJs": true, 7 | "noEmit": true, 8 | "resolveJsonModule": true, 9 | "moduleResolution": "node", 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig-es2015.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es2015", 5 | "outDir": "./dist/test/es2015", 6 | "lib": ["es2015", "dom"], 7 | "moduleResolution": "nodenext", 8 | "module": "NodeNext" 9 | }, 10 | "include": [ 11 | "./lib/index.ts", 12 | "./test/*.ts", 13 | "rollup.config.js", 14 | "eslint.config.mjs" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "ES2015", 5 | "sourceMap": true, 6 | "inlineSources": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "stripInternal": true, 10 | "declaration": true, 11 | "outDir": "./dist", 12 | "moduleResolution": "node", 13 | "allowJs": true, 14 | "lib": [ 15 | "es2015", 16 | "dom" 17 | ], 18 | "strict": true, 19 | "esModuleInterop": true, 20 | "importHelpers": true 21 | }, 22 | "files": [ 23 | "./lib/index.ts" 24 | ], 25 | "angularCompilerOptions": { 26 | "skipTemplateCodegen": true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@emnapi/core@^1.4.0": 6 | version "1.4.3" 7 | resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6" 8 | integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g== 9 | dependencies: 10 | "@emnapi/wasi-threads" "1.0.2" 11 | tslib "^2.4.0" 12 | 13 | "@emnapi/runtime@^1.4.0": 14 | version "1.4.3" 15 | resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d" 16 | integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ== 17 | dependencies: 18 | tslib "^2.4.0" 19 | 20 | "@emnapi/wasi-threads@1.0.2": 21 | version "1.0.2" 22 | resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c" 23 | integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA== 24 | dependencies: 25 | tslib "^2.4.0" 26 | 27 | "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": 28 | version "4.6.1" 29 | resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz#e4c58fdcf0696e7a5f19c30201ed43123ab15abc" 30 | integrity sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw== 31 | dependencies: 32 | eslint-visitor-keys "^3.4.3" 33 | 34 | "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": 35 | version "4.12.1" 36 | resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" 37 | integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== 38 | 39 | "@eslint/config-array@^0.20.0": 40 | version "0.20.0" 41 | resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.20.0.tgz#7a1232e82376712d3340012a2f561a2764d1988f" 42 | integrity sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ== 43 | dependencies: 44 | "@eslint/object-schema" "^2.1.6" 45 | debug "^4.3.1" 46 | minimatch "^3.1.2" 47 | 48 | "@eslint/config-helpers@^0.2.1": 49 | version "0.2.1" 50 | resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.1.tgz#26042c028d1beee5ce2235a7929b91c52651646d" 51 | integrity sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw== 52 | 53 | "@eslint/core@^0.13.0": 54 | version "0.13.0" 55 | resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.13.0.tgz#bf02f209846d3bf996f9e8009db62df2739b458c" 56 | integrity sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw== 57 | dependencies: 58 | "@types/json-schema" "^7.0.15" 59 | 60 | "@eslint/eslintrc@^3.3.1": 61 | version "3.3.1" 62 | resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" 63 | integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== 64 | dependencies: 65 | ajv "^6.12.4" 66 | debug "^4.3.2" 67 | espree "^10.0.1" 68 | globals "^14.0.0" 69 | ignore "^5.2.0" 70 | import-fresh "^3.2.1" 71 | js-yaml "^4.1.0" 72 | minimatch "^3.1.2" 73 | strip-json-comments "^3.1.1" 74 | 75 | "@eslint/js@9.25.1", "@eslint/js@^9.25.1": 76 | version "9.25.1" 77 | resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.25.1.tgz#25f5c930c2b68b5ebe7ac857f754cbd61ef6d117" 78 | integrity sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg== 79 | 80 | "@eslint/object-schema@^2.1.6": 81 | version "2.1.6" 82 | resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" 83 | integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== 84 | 85 | "@eslint/plugin-kit@^0.2.8": 86 | version "0.2.8" 87 | resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz#47488d8f8171b5d4613e833313f3ce708e3525f8" 88 | integrity sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA== 89 | dependencies: 90 | "@eslint/core" "^0.13.0" 91 | levn "^0.4.1" 92 | 93 | "@humanfs/core@^0.19.1": 94 | version "0.19.1" 95 | resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" 96 | integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== 97 | 98 | "@humanfs/node@^0.16.6": 99 | version "0.16.6" 100 | resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" 101 | integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== 102 | dependencies: 103 | "@humanfs/core" "^0.19.1" 104 | "@humanwhocodes/retry" "^0.3.0" 105 | 106 | "@humanwhocodes/module-importer@^1.0.1": 107 | version "1.0.1" 108 | resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" 109 | integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== 110 | 111 | "@humanwhocodes/retry@^0.3.0": 112 | version "0.3.1" 113 | resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" 114 | integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== 115 | 116 | "@humanwhocodes/retry@^0.4.2": 117 | version "0.4.2" 118 | resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161" 119 | integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== 120 | 121 | "@isaacs/cliui@^8.0.2": 122 | version "8.0.2" 123 | resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" 124 | integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== 125 | dependencies: 126 | string-width "^5.1.2" 127 | string-width-cjs "npm:string-width@^4.2.0" 128 | strip-ansi "^7.0.1" 129 | strip-ansi-cjs "npm:strip-ansi@^6.0.1" 130 | wrap-ansi "^8.1.0" 131 | wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" 132 | 133 | "@napi-rs/wasm-runtime@^0.2.4": 134 | version "0.2.9" 135 | resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz#7278122cf94f3b36d8170a8eee7d85356dfa6a96" 136 | integrity sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg== 137 | dependencies: 138 | "@emnapi/core" "^1.4.0" 139 | "@emnapi/runtime" "^1.4.0" 140 | "@tybys/wasm-util" "^0.9.0" 141 | 142 | "@nodelib/fs.scandir@2.1.5": 143 | version "2.1.5" 144 | resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" 145 | integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 146 | dependencies: 147 | "@nodelib/fs.stat" "2.0.5" 148 | run-parallel "^1.1.9" 149 | 150 | "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": 151 | version "2.0.5" 152 | resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" 153 | integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 154 | 155 | "@nodelib/fs.walk@^1.2.3": 156 | version "1.2.8" 157 | resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" 158 | integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 159 | dependencies: 160 | "@nodelib/fs.scandir" "2.1.5" 161 | fastq "^1.6.0" 162 | 163 | "@oxc-project/types@0.65.0": 164 | version "0.65.0" 165 | resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.65.0.tgz#ba40064b6ba43fddee44f0d8518e7929a7dffb05" 166 | integrity sha512-7MpMzyXCcwxrTxJ4L0siy63Ds/LA8LAM4szumTFiynxTJkfrIZEV4PyR4Th0CqFZQ+oNi8WvW3Dr1MLy7o9qPQ== 167 | 168 | "@pkgjs/parseargs@^0.11.0": 169 | version "0.11.0" 170 | resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" 171 | integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== 172 | 173 | "@pkgr/core@^0.2.3": 174 | version "0.2.4" 175 | resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" 176 | integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== 177 | 178 | "@rolldown/binding-darwin-arm64@1.0.0-beta.8": 179 | version "1.0.0-beta.8" 180 | resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.8.tgz#9793e0b95360cddaa89efb43417fc2b2e4604008" 181 | integrity sha512-4cwzBnUvPUVdjUMo9uFkcTvj+Z6IXaN/YJSz1RuI/DG5+vlQ9wYfKeDkvb1nsrhi4ZJ99OInOw1Vh/n2ReX8rA== 182 | 183 | "@rolldown/binding-darwin-x64@1.0.0-beta.8": 184 | version "1.0.0-beta.8" 185 | resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.8.tgz#f67f3345203161b15b9d59a2875ee66f46c2f6aa" 186 | integrity sha512-BYI7UXc0UqjdpmEyNpxulv8cYbTdL7zLzIr6GDdIvHH7fe/pKTmC9GpvkpF/j2cyP0SUKTd6ExX7nFDNDqKMBw== 187 | 188 | "@rolldown/binding-freebsd-x64@1.0.0-beta.8": 189 | version "1.0.0-beta.8" 190 | resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.8.tgz#adcabf00d9b28a68c414081927af20e0c4c7af8f" 191 | integrity sha512-KsX/nuGiuNugIeBelN7M7c/8kzcAW6IfH080z9IrIrlCaGa+xwjqMAf7JuYLZo82uokFq8nql0YpQIazFwFR0Q== 192 | 193 | "@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.8": 194 | version "1.0.0-beta.8" 195 | resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.8.tgz#75d43988d46a432592034e8516c645565c7ed2b9" 196 | integrity sha512-IzmoAB9J9iOnoC2Nb6AlyIPPULcbLb0qtJDq21+95u/qiE2GYtI5M4aNudbAIdyv0MU4SAdhkG2sXjMo79H/Zg== 197 | 198 | "@rolldown/binding-linux-arm64-gnu@1.0.0-beta.8": 199 | version "1.0.0-beta.8" 200 | resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.8.tgz#c03da3b644045fc0c4de8f399293dad3b3e7b073" 201 | integrity sha512-nGtOvVKMywOlqoFiMJgILgCpdVcPe0psH1oCWtieMyFFU/v2h2ucjstAEeCOe+JfMVVA7OpdNoWKc54Y1V7gGw== 202 | 203 | "@rolldown/binding-linux-arm64-musl@1.0.0-beta.8": 204 | version "1.0.0-beta.8" 205 | resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.8.tgz#49e7dfe0c31780fc19ba6aebbcbdf4fb435c903b" 206 | integrity sha512-paTZphpweKHNwlIu0JTAJCddn/psFzNUaKeGEY4vTQEqDcewKp9SsxN7240ao1eqTYy6TMFJiX6Ej2ym93MkSQ== 207 | 208 | "@rolldown/binding-linux-x64-gnu@1.0.0-beta.8": 209 | version "1.0.0-beta.8" 210 | resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.8.tgz#2fcbc7e4242eb3deaaa243d6221aeb98b2d5ecaa" 211 | integrity sha512-Pdt5iaG/wlWTvEz1lZ3kDkmVXM7DxQXPFZUX/UjDnUyxf4vSgxszbSx1tiNdU0D9v1IISgBapANSwJOGtF1lWw== 212 | 213 | "@rolldown/binding-linux-x64-musl@1.0.0-beta.8": 214 | version "1.0.0-beta.8" 215 | resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.8.tgz#afa791a210f453a1a9da3f23ab73e5091984f18b" 216 | integrity sha512-8LoLgKq+Wb030p+tzw0JrOrbJrR2wmqfARX1CHIhge8LBoxd2lfHtWfkg23qRa1S8So/nBZBhrQsg2kXUkpwxw== 217 | 218 | "@rolldown/binding-wasm32-wasi@1.0.0-beta.8": 219 | version "1.0.0-beta.8" 220 | resolved "https://registry.yarnpkg.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.8.tgz#27c1df63b82d8a44f3ca28e4fcad7d93bf927fb0" 221 | integrity sha512-+2y9Omf9tZRR44Y4EYqm3/Zq2f4Tv+Gh8NsExFWM6WpQZI3HyIB07lrTNQfOJgKSsAiUisnbjiPVTkiH5miy1w== 222 | dependencies: 223 | "@napi-rs/wasm-runtime" "^0.2.4" 224 | 225 | "@rolldown/binding-win32-arm64-msvc@1.0.0-beta.8": 226 | version "1.0.0-beta.8" 227 | resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.8.tgz#df46882718459c816463d4724b0aa96dd6aa3e0b" 228 | integrity sha512-bt5AOleb2yp+Br9Yzew+jbSEGjLoqGwknH0xhK8QkhXKx31sJLseaP7nFXr6JaEbmL4DVmAVgrOcyLzLbR6+Mw== 229 | 230 | "@rolldown/binding-win32-ia32-msvc@1.0.0-beta.8": 231 | version "1.0.0-beta.8" 232 | resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.8.tgz#c1b6c6326e8a89c0c5d914330ef911fed02f20bd" 233 | integrity sha512-Fa1OH6eUWtjBNNkKiSSq1fHVMuiqQ+Bi9uMNJz7gBFgjNiAB9k9rQr0j9eF1k4H6lXFkuoN5P7pXty6aBh93Cw== 234 | 235 | "@rolldown/binding-win32-x64-msvc@1.0.0-beta.8": 236 | version "1.0.0-beta.8" 237 | resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.8.tgz#7003571b44b20a0e83ecb5134e6ec34b3a2fb0ee" 238 | integrity sha512-hR81d84Poe6oIxaz4PnWBLVF0VuqtRfISIyXQAgk2etu2udrKnWKr3A+xqXe9ELjbLlRYGvEm2dlw/cldO9Kxg== 239 | 240 | "@rollup/rollup-android-arm-eabi@4.40.0": 241 | version "4.40.0" 242 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz#d964ee8ce4d18acf9358f96adc408689b6e27fe3" 243 | integrity sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg== 244 | 245 | "@rollup/rollup-android-arm64@4.40.0": 246 | version "4.40.0" 247 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz#9b5e130ecc32a5fc1e96c09ff371743ee71a62d3" 248 | integrity sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w== 249 | 250 | "@rollup/rollup-darwin-arm64@4.40.0": 251 | version "4.40.0" 252 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz#ef439182c739b20b3c4398cfc03e3c1249ac8903" 253 | integrity sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ== 254 | 255 | "@rollup/rollup-darwin-x64@4.40.0": 256 | version "4.40.0" 257 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz#d7380c1531ab0420ca3be16f17018ef72dd3d504" 258 | integrity sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA== 259 | 260 | "@rollup/rollup-freebsd-arm64@4.40.0": 261 | version "4.40.0" 262 | resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz#cbcbd7248823c6b430ce543c59906dd3c6df0936" 263 | integrity sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg== 264 | 265 | "@rollup/rollup-freebsd-x64@4.40.0": 266 | version "4.40.0" 267 | resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz#96bf6ff875bab5219c3472c95fa6eb992586a93b" 268 | integrity sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw== 269 | 270 | "@rollup/rollup-linux-arm-gnueabihf@4.40.0": 271 | version "4.40.0" 272 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz#d80cd62ce6d40f8e611008d8dbf03b5e6bbf009c" 273 | integrity sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA== 274 | 275 | "@rollup/rollup-linux-arm-musleabihf@4.40.0": 276 | version "4.40.0" 277 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz#75440cfc1e8d0f87a239b4c31dfeaf4719b656b7" 278 | integrity sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg== 279 | 280 | "@rollup/rollup-linux-arm64-gnu@4.40.0": 281 | version "4.40.0" 282 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz#ac527485ecbb619247fb08253ec8c551a0712e7c" 283 | integrity sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg== 284 | 285 | "@rollup/rollup-linux-arm64-musl@4.40.0": 286 | version "4.40.0" 287 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz#74d2b5cb11cf714cd7d1682e7c8b39140e908552" 288 | integrity sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ== 289 | 290 | "@rollup/rollup-linux-loongarch64-gnu@4.40.0": 291 | version "4.40.0" 292 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz#a0a310e51da0b5fea0e944b0abd4be899819aef6" 293 | integrity sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg== 294 | 295 | "@rollup/rollup-linux-powerpc64le-gnu@4.40.0": 296 | version "4.40.0" 297 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz#4077e2862b0ac9f61916d6b474d988171bd43b83" 298 | integrity sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw== 299 | 300 | "@rollup/rollup-linux-riscv64-gnu@4.40.0": 301 | version "4.40.0" 302 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz#5812a1a7a2f9581cbe12597307cc7ba3321cf2f3" 303 | integrity sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA== 304 | 305 | "@rollup/rollup-linux-riscv64-musl@4.40.0": 306 | version "4.40.0" 307 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz#973aaaf4adef4531375c36616de4e01647f90039" 308 | integrity sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ== 309 | 310 | "@rollup/rollup-linux-s390x-gnu@4.40.0": 311 | version "4.40.0" 312 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz#9bad59e907ba5bfcf3e9dbd0247dfe583112f70b" 313 | integrity sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw== 314 | 315 | "@rollup/rollup-linux-x64-gnu@4.40.0": 316 | version "4.40.0" 317 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz#68b045a720bd9b4d905f462b997590c2190a6de0" 318 | integrity sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ== 319 | 320 | "@rollup/rollup-linux-x64-musl@4.40.0": 321 | version "4.40.0" 322 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz#8e703e2c2ad19ba7b2cb3d8c3a4ad11d4ee3a282" 323 | integrity sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw== 324 | 325 | "@rollup/rollup-win32-arm64-msvc@4.40.0": 326 | version "4.40.0" 327 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz#c5bee19fa670ff5da5f066be6a58b4568e9c650b" 328 | integrity sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ== 329 | 330 | "@rollup/rollup-win32-ia32-msvc@4.40.0": 331 | version "4.40.0" 332 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz#846e02c17044bd922f6f483a3b4d36aac6e2b921" 333 | integrity sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA== 334 | 335 | "@rollup/rollup-win32-x64-msvc@4.40.0": 336 | version "4.40.0" 337 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz#fd92d31a2931483c25677b9c6698106490cbbc76" 338 | integrity sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ== 339 | 340 | "@tybys/wasm-util@^0.9.0": 341 | version "0.9.0" 342 | resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" 343 | integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw== 344 | dependencies: 345 | tslib "^2.4.0" 346 | 347 | "@types/estree@1.0.7", "@types/estree@^1.0.6": 348 | version "1.0.7" 349 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" 350 | integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== 351 | 352 | "@types/jasmine@^5.1.7": 353 | version "5.1.7" 354 | resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-5.1.7.tgz#b9f68cf05463717bbe36d53221839e7630a24d22" 355 | integrity sha512-DVOfk9FaClQfNFpSfaML15jjB5cjffDMvjtph525sroR5BEAW2uKnTOYUTqTFuZFjNvH0T5XMIydvIctnUKufw== 356 | 357 | "@types/json-schema@^7.0.15": 358 | version "7.0.15" 359 | resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" 360 | integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== 361 | 362 | "@types/node@^22.14.1": 363 | version "22.14.1" 364 | resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.1.tgz#53b54585cec81c21eee3697521e31312d6ca1e6f" 365 | integrity sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw== 366 | dependencies: 367 | undici-types "~6.21.0" 368 | 369 | "@typescript-eslint/eslint-plugin@^8.31.0": 370 | version "8.31.0" 371 | resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz#ef3ece95406a80026f82a19a2984c1e375981711" 372 | integrity sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ== 373 | dependencies: 374 | "@eslint-community/regexpp" "^4.10.0" 375 | "@typescript-eslint/scope-manager" "8.31.0" 376 | "@typescript-eslint/type-utils" "8.31.0" 377 | "@typescript-eslint/utils" "8.31.0" 378 | "@typescript-eslint/visitor-keys" "8.31.0" 379 | graphemer "^1.4.0" 380 | ignore "^5.3.1" 381 | natural-compare "^1.4.0" 382 | ts-api-utils "^2.0.1" 383 | 384 | "@typescript-eslint/parser@^8.31.0": 385 | version "8.31.0" 386 | resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.31.0.tgz#5ec28823d06dd20ed5f67b61224823f12ccde095" 387 | integrity sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw== 388 | dependencies: 389 | "@typescript-eslint/scope-manager" "8.31.0" 390 | "@typescript-eslint/types" "8.31.0" 391 | "@typescript-eslint/typescript-estree" "8.31.0" 392 | "@typescript-eslint/visitor-keys" "8.31.0" 393 | debug "^4.3.4" 394 | 395 | "@typescript-eslint/scope-manager@8.31.0": 396 | version "8.31.0" 397 | resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz#48c7f7d729ea038e36cae0ff511e48c2412fb11c" 398 | integrity sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw== 399 | dependencies: 400 | "@typescript-eslint/types" "8.31.0" 401 | "@typescript-eslint/visitor-keys" "8.31.0" 402 | 403 | "@typescript-eslint/type-utils@8.31.0": 404 | version "8.31.0" 405 | resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz#01536a993fae23e2def885b006aaa991cbfbe9e7" 406 | integrity sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg== 407 | dependencies: 408 | "@typescript-eslint/typescript-estree" "8.31.0" 409 | "@typescript-eslint/utils" "8.31.0" 410 | debug "^4.3.4" 411 | ts-api-utils "^2.0.1" 412 | 413 | "@typescript-eslint/types@8.31.0": 414 | version "8.31.0" 415 | resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.31.0.tgz#c48e20ec47a43b72747714f49ea9f7b38a4fa6c1" 416 | integrity sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ== 417 | 418 | "@typescript-eslint/typescript-estree@8.31.0": 419 | version "8.31.0" 420 | resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz#9c7f84eff6ad23d63cf086c6e93af571cd561270" 421 | integrity sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ== 422 | dependencies: 423 | "@typescript-eslint/types" "8.31.0" 424 | "@typescript-eslint/visitor-keys" "8.31.0" 425 | debug "^4.3.4" 426 | fast-glob "^3.3.2" 427 | is-glob "^4.0.3" 428 | minimatch "^9.0.4" 429 | semver "^7.6.0" 430 | ts-api-utils "^2.0.1" 431 | 432 | "@typescript-eslint/utils@8.31.0": 433 | version "8.31.0" 434 | resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.31.0.tgz#6fb52471a29fdd16fc253d568c5ad4b048f78ba4" 435 | integrity sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww== 436 | dependencies: 437 | "@eslint-community/eslint-utils" "^4.4.0" 438 | "@typescript-eslint/scope-manager" "8.31.0" 439 | "@typescript-eslint/types" "8.31.0" 440 | "@typescript-eslint/typescript-estree" "8.31.0" 441 | 442 | "@typescript-eslint/visitor-keys@8.31.0": 443 | version "8.31.0" 444 | resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz#9a1a97ed16c60d4d1e7399b41c11a6d94ebc1ce5" 445 | integrity sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ== 446 | dependencies: 447 | "@typescript-eslint/types" "8.31.0" 448 | eslint-visitor-keys "^4.2.0" 449 | 450 | "@valibot/to-json-schema@1.0.0": 451 | version "1.0.0" 452 | resolved "https://registry.yarnpkg.com/@valibot/to-json-schema/-/to-json-schema-1.0.0.tgz#69ce115d3b2c3d924a784f36247aff1949ad4daf" 453 | integrity sha512-/9crJgPptVsGCL6X+JPDQyaJwkalSZ/52WuF8DiRUxJgcmpNdzYRfZ+gqMEP8W3CTVfuMWPqqvIgfwJ97f9Etw== 454 | 455 | acorn-jsx@^5.3.2: 456 | version "5.3.2" 457 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" 458 | integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 459 | 460 | acorn@^8.14.0: 461 | version "8.14.1" 462 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" 463 | integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== 464 | 465 | ajv@^6.12.4: 466 | version "6.12.6" 467 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 468 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 469 | dependencies: 470 | fast-deep-equal "^3.1.1" 471 | fast-json-stable-stringify "^2.0.0" 472 | json-schema-traverse "^0.4.1" 473 | uri-js "^4.2.2" 474 | 475 | ansi-regex@^5.0.1: 476 | version "5.0.1" 477 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 478 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 479 | 480 | ansi-regex@^6.0.1: 481 | version "6.1.0" 482 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" 483 | integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== 484 | 485 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 486 | version "4.3.0" 487 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 488 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 489 | dependencies: 490 | color-convert "^2.0.1" 491 | 492 | ansi-styles@^6.1.0: 493 | version "6.2.1" 494 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" 495 | integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== 496 | 497 | ansis@^3.17.0: 498 | version "3.17.0" 499 | resolved "https://registry.yarnpkg.com/ansis/-/ansis-3.17.0.tgz#fa8d9c2a93fe7d1177e0c17f9eeb562a58a832d7" 500 | integrity sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg== 501 | 502 | argparse@^2.0.1: 503 | version "2.0.1" 504 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 505 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 506 | 507 | balanced-match@^1.0.0: 508 | version "1.0.2" 509 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 510 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 511 | 512 | brace-expansion@^1.1.7: 513 | version "1.1.11" 514 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 515 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 516 | dependencies: 517 | balanced-match "^1.0.0" 518 | concat-map "0.0.1" 519 | 520 | brace-expansion@^2.0.1: 521 | version "2.0.1" 522 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 523 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 524 | dependencies: 525 | balanced-match "^1.0.0" 526 | 527 | braces@^3.0.3: 528 | version "3.0.3" 529 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 530 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 531 | dependencies: 532 | fill-range "^7.1.1" 533 | 534 | callsites@^3.0.0: 535 | version "3.1.0" 536 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 537 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 538 | 539 | chalk@^4.0.0: 540 | version "4.1.2" 541 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 542 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 543 | dependencies: 544 | ansi-styles "^4.1.0" 545 | supports-color "^7.1.0" 546 | 547 | color-convert@^2.0.1: 548 | version "2.0.1" 549 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 550 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 551 | dependencies: 552 | color-name "~1.1.4" 553 | 554 | color-name@~1.1.4: 555 | version "1.1.4" 556 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 557 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 558 | 559 | concat-map@0.0.1: 560 | version "0.0.1" 561 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 562 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 563 | 564 | cross-spawn@^7.0.6: 565 | version "7.0.6" 566 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" 567 | integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== 568 | dependencies: 569 | path-key "^3.1.0" 570 | shebang-command "^2.0.0" 571 | which "^2.0.1" 572 | 573 | debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: 574 | version "4.4.0" 575 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" 576 | integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== 577 | dependencies: 578 | ms "^2.1.3" 579 | 580 | deep-is@^0.1.3: 581 | version "0.1.4" 582 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" 583 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 584 | 585 | eastasianwidth@^0.2.0: 586 | version "0.2.0" 587 | resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" 588 | integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== 589 | 590 | emoji-regex@^8.0.0: 591 | version "8.0.0" 592 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 593 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 594 | 595 | emoji-regex@^9.2.2: 596 | version "9.2.2" 597 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" 598 | integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== 599 | 600 | escape-string-regexp@^4.0.0: 601 | version "4.0.0" 602 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 603 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 604 | 605 | eslint-config-prettier@^10.1.2: 606 | version "10.1.2" 607 | resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz#31a4b393c40c4180202c27e829af43323bf85276" 608 | integrity sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA== 609 | 610 | eslint-plugin-prettier@^5.2.6: 611 | version "5.2.6" 612 | resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.6.tgz#be39e3bb23bb3eeb7e7df0927cdb46e4d7945096" 613 | integrity sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ== 614 | dependencies: 615 | prettier-linter-helpers "^1.0.0" 616 | synckit "^0.11.0" 617 | 618 | eslint-scope@^8.3.0: 619 | version "8.3.0" 620 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.3.0.tgz#10cd3a918ffdd722f5f3f7b5b83db9b23c87340d" 621 | integrity sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ== 622 | dependencies: 623 | esrecurse "^4.3.0" 624 | estraverse "^5.2.0" 625 | 626 | eslint-visitor-keys@^3.4.3: 627 | version "3.4.3" 628 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" 629 | integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== 630 | 631 | eslint-visitor-keys@^4.2.0: 632 | version "4.2.0" 633 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" 634 | integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== 635 | 636 | eslint@^9.25.1: 637 | version "9.25.1" 638 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.25.1.tgz#8a7cf8dd0e6acb858f86029720adb1785ee57580" 639 | integrity sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ== 640 | dependencies: 641 | "@eslint-community/eslint-utils" "^4.2.0" 642 | "@eslint-community/regexpp" "^4.12.1" 643 | "@eslint/config-array" "^0.20.0" 644 | "@eslint/config-helpers" "^0.2.1" 645 | "@eslint/core" "^0.13.0" 646 | "@eslint/eslintrc" "^3.3.1" 647 | "@eslint/js" "9.25.1" 648 | "@eslint/plugin-kit" "^0.2.8" 649 | "@humanfs/node" "^0.16.6" 650 | "@humanwhocodes/module-importer" "^1.0.1" 651 | "@humanwhocodes/retry" "^0.4.2" 652 | "@types/estree" "^1.0.6" 653 | "@types/json-schema" "^7.0.15" 654 | ajv "^6.12.4" 655 | chalk "^4.0.0" 656 | cross-spawn "^7.0.6" 657 | debug "^4.3.2" 658 | escape-string-regexp "^4.0.0" 659 | eslint-scope "^8.3.0" 660 | eslint-visitor-keys "^4.2.0" 661 | espree "^10.3.0" 662 | esquery "^1.5.0" 663 | esutils "^2.0.2" 664 | fast-deep-equal "^3.1.3" 665 | file-entry-cache "^8.0.0" 666 | find-up "^5.0.0" 667 | glob-parent "^6.0.2" 668 | ignore "^5.2.0" 669 | imurmurhash "^0.1.4" 670 | is-glob "^4.0.0" 671 | json-stable-stringify-without-jsonify "^1.0.1" 672 | lodash.merge "^4.6.2" 673 | minimatch "^3.1.2" 674 | natural-compare "^1.4.0" 675 | optionator "^0.9.3" 676 | 677 | espree@^10.0.1, espree@^10.3.0: 678 | version "10.3.0" 679 | resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" 680 | integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== 681 | dependencies: 682 | acorn "^8.14.0" 683 | acorn-jsx "^5.3.2" 684 | eslint-visitor-keys "^4.2.0" 685 | 686 | esquery@^1.5.0: 687 | version "1.6.0" 688 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" 689 | integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== 690 | dependencies: 691 | estraverse "^5.1.0" 692 | 693 | esrecurse@^4.3.0: 694 | version "4.3.0" 695 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 696 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 697 | dependencies: 698 | estraverse "^5.2.0" 699 | 700 | estraverse@^5.1.0, estraverse@^5.2.0: 701 | version "5.3.0" 702 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 703 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 704 | 705 | esutils@^2.0.2: 706 | version "2.0.3" 707 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 708 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 709 | 710 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 711 | version "3.1.3" 712 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 713 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 714 | 715 | fast-diff@^1.1.2: 716 | version "1.3.0" 717 | resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" 718 | integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== 719 | 720 | fast-glob@^3.3.2: 721 | version "3.3.3" 722 | resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" 723 | integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== 724 | dependencies: 725 | "@nodelib/fs.stat" "^2.0.2" 726 | "@nodelib/fs.walk" "^1.2.3" 727 | glob-parent "^5.1.2" 728 | merge2 "^1.3.0" 729 | micromatch "^4.0.8" 730 | 731 | fast-json-stable-stringify@^2.0.0: 732 | version "2.1.0" 733 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 734 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 735 | 736 | fast-levenshtein@^2.0.6: 737 | version "2.0.6" 738 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 739 | integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== 740 | 741 | fastq@^1.6.0: 742 | version "1.19.1" 743 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" 744 | integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== 745 | dependencies: 746 | reusify "^1.0.4" 747 | 748 | file-entry-cache@^8.0.0: 749 | version "8.0.0" 750 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" 751 | integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== 752 | dependencies: 753 | flat-cache "^4.0.0" 754 | 755 | fill-range@^7.1.1: 756 | version "7.1.1" 757 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 758 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 759 | dependencies: 760 | to-regex-range "^5.0.1" 761 | 762 | find-up@^5.0.0: 763 | version "5.0.0" 764 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 765 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 766 | dependencies: 767 | locate-path "^6.0.0" 768 | path-exists "^4.0.0" 769 | 770 | flat-cache@^4.0.0: 771 | version "4.0.1" 772 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" 773 | integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== 774 | dependencies: 775 | flatted "^3.2.9" 776 | keyv "^4.5.4" 777 | 778 | flatted@^3.2.9: 779 | version "3.3.3" 780 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" 781 | integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== 782 | 783 | foreground-child@^3.1.0: 784 | version "3.3.1" 785 | resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" 786 | integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== 787 | dependencies: 788 | cross-spawn "^7.0.6" 789 | signal-exit "^4.0.1" 790 | 791 | fsevents@~2.3.2: 792 | version "2.3.3" 793 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 794 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 795 | 796 | glob-parent@^5.1.2: 797 | version "5.1.2" 798 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 799 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 800 | dependencies: 801 | is-glob "^4.0.1" 802 | 803 | glob-parent@^6.0.2: 804 | version "6.0.2" 805 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" 806 | integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== 807 | dependencies: 808 | is-glob "^4.0.3" 809 | 810 | glob@^10.2.2: 811 | version "10.4.5" 812 | resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" 813 | integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== 814 | dependencies: 815 | foreground-child "^3.1.0" 816 | jackspeak "^3.1.2" 817 | minimatch "^9.0.4" 818 | minipass "^7.1.2" 819 | package-json-from-dist "^1.0.0" 820 | path-scurry "^1.11.1" 821 | 822 | glob@^11.0.0: 823 | version "11.0.1" 824 | resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.1.tgz#1c3aef9a59d680e611b53dcd24bb8639cef064d9" 825 | integrity sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw== 826 | dependencies: 827 | foreground-child "^3.1.0" 828 | jackspeak "^4.0.1" 829 | minimatch "^10.0.0" 830 | minipass "^7.1.2" 831 | package-json-from-dist "^1.0.0" 832 | path-scurry "^2.0.0" 833 | 834 | globals@^14.0.0: 835 | version "14.0.0" 836 | resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" 837 | integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== 838 | 839 | globals@^16.0.0: 840 | version "16.0.0" 841 | resolved "https://registry.yarnpkg.com/globals/-/globals-16.0.0.tgz#3d7684652c5c4fbd086ec82f9448214da49382d8" 842 | integrity sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A== 843 | 844 | graphemer@^1.4.0: 845 | version "1.4.0" 846 | resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" 847 | integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== 848 | 849 | has-flag@^4.0.0: 850 | version "4.0.0" 851 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 852 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 853 | 854 | ignore@^5.2.0, ignore@^5.3.1: 855 | version "5.3.2" 856 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" 857 | integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== 858 | 859 | import-fresh@^3.2.1: 860 | version "3.3.1" 861 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" 862 | integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== 863 | dependencies: 864 | parent-module "^1.0.0" 865 | resolve-from "^4.0.0" 866 | 867 | imurmurhash@^0.1.4: 868 | version "0.1.4" 869 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 870 | integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== 871 | 872 | is-extglob@^2.1.1: 873 | version "2.1.1" 874 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 875 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 876 | 877 | is-fullwidth-code-point@^3.0.0: 878 | version "3.0.0" 879 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 880 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 881 | 882 | is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: 883 | version "4.0.3" 884 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 885 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 886 | dependencies: 887 | is-extglob "^2.1.1" 888 | 889 | is-number@^7.0.0: 890 | version "7.0.0" 891 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 892 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 893 | 894 | isexe@^2.0.0: 895 | version "2.0.0" 896 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 897 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 898 | 899 | jackspeak@^3.1.2: 900 | version "3.4.3" 901 | resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" 902 | integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== 903 | dependencies: 904 | "@isaacs/cliui" "^8.0.2" 905 | optionalDependencies: 906 | "@pkgjs/parseargs" "^0.11.0" 907 | 908 | jackspeak@^4.0.1: 909 | version "4.1.0" 910 | resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.0.tgz#c489c079f2b636dc4cbe9b0312a13ff1282e561b" 911 | integrity sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw== 912 | dependencies: 913 | "@isaacs/cliui" "^8.0.2" 914 | 915 | jasmine-core@~5.6.0: 916 | version "5.6.0" 917 | resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-5.6.0.tgz#4b979c254e7d9b1fe8e767ab00c5d2901c00bd4f" 918 | integrity sha512-niVlkeYVRwKFpmfWg6suo6H9CrNnydfBLEqefM5UjibYS+UoTjZdmvPJSiuyrRLGnFj1eYRhFd/ch+5hSlsFVA== 919 | 920 | jasmine@^5.6.0: 921 | version "5.6.0" 922 | resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-5.6.0.tgz#83be3acf8dd44ad365d15f01c13c019a5e9c01cc" 923 | integrity sha512-6frlW22jhgRjtlp68QY/DDVCUfrYqmSxDBWM13mrBzYQGx1XITfVcJltnY15bk8B5cRfN5IpKvemkDiDTSRCsA== 924 | dependencies: 925 | glob "^10.2.2" 926 | jasmine-core "~5.6.0" 927 | 928 | js-yaml@^4.1.0: 929 | version "4.1.0" 930 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 931 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 932 | dependencies: 933 | argparse "^2.0.1" 934 | 935 | json-buffer@3.0.1: 936 | version "3.0.1" 937 | resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" 938 | integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== 939 | 940 | json-schema-traverse@^0.4.1: 941 | version "0.4.1" 942 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 943 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 944 | 945 | json-stable-stringify-without-jsonify@^1.0.1: 946 | version "1.0.1" 947 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 948 | integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== 949 | 950 | keyv@^4.5.4: 951 | version "4.5.4" 952 | resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" 953 | integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== 954 | dependencies: 955 | json-buffer "3.0.1" 956 | 957 | levn@^0.4.1: 958 | version "0.4.1" 959 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" 960 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 961 | dependencies: 962 | prelude-ls "^1.2.1" 963 | type-check "~0.4.0" 964 | 965 | locate-path@^6.0.0: 966 | version "6.0.0" 967 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 968 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 969 | dependencies: 970 | p-locate "^5.0.0" 971 | 972 | lodash.merge@^4.6.2: 973 | version "4.6.2" 974 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" 975 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 976 | 977 | lru-cache@^10.2.0: 978 | version "10.4.3" 979 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" 980 | integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== 981 | 982 | lru-cache@^11.0.0: 983 | version "11.1.0" 984 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.1.0.tgz#afafb060607108132dbc1cf8ae661afb69486117" 985 | integrity sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A== 986 | 987 | merge2@^1.3.0: 988 | version "1.4.1" 989 | resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" 990 | integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== 991 | 992 | micromatch@^4.0.8: 993 | version "4.0.8" 994 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" 995 | integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== 996 | dependencies: 997 | braces "^3.0.3" 998 | picomatch "^2.3.1" 999 | 1000 | minimatch@^10.0.0: 1001 | version "10.0.1" 1002 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" 1003 | integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== 1004 | dependencies: 1005 | brace-expansion "^2.0.1" 1006 | 1007 | minimatch@^3.1.2: 1008 | version "3.1.2" 1009 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 1010 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1011 | dependencies: 1012 | brace-expansion "^1.1.7" 1013 | 1014 | minimatch@^9.0.4: 1015 | version "9.0.5" 1016 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" 1017 | integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== 1018 | dependencies: 1019 | brace-expansion "^2.0.1" 1020 | 1021 | "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: 1022 | version "7.1.2" 1023 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" 1024 | integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== 1025 | 1026 | ms@^2.1.3: 1027 | version "2.1.3" 1028 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1029 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1030 | 1031 | natural-compare@^1.4.0: 1032 | version "1.4.0" 1033 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 1034 | integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== 1035 | 1036 | optionator@^0.9.3: 1037 | version "0.9.4" 1038 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" 1039 | integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== 1040 | dependencies: 1041 | deep-is "^0.1.3" 1042 | fast-levenshtein "^2.0.6" 1043 | levn "^0.4.1" 1044 | prelude-ls "^1.2.1" 1045 | type-check "^0.4.0" 1046 | word-wrap "^1.2.5" 1047 | 1048 | p-limit@^3.0.2: 1049 | version "3.1.0" 1050 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 1051 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1052 | dependencies: 1053 | yocto-queue "^0.1.0" 1054 | 1055 | p-locate@^5.0.0: 1056 | version "5.0.0" 1057 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1058 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1059 | dependencies: 1060 | p-limit "^3.0.2" 1061 | 1062 | package-json-from-dist@^1.0.0: 1063 | version "1.0.1" 1064 | resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" 1065 | integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== 1066 | 1067 | parent-module@^1.0.0: 1068 | version "1.0.1" 1069 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 1070 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1071 | dependencies: 1072 | callsites "^3.0.0" 1073 | 1074 | path-exists@^4.0.0: 1075 | version "4.0.0" 1076 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1077 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1078 | 1079 | path-key@^3.1.0: 1080 | version "3.1.1" 1081 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1082 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1083 | 1084 | path-scurry@^1.11.1: 1085 | version "1.11.1" 1086 | resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" 1087 | integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== 1088 | dependencies: 1089 | lru-cache "^10.2.0" 1090 | minipass "^5.0.0 || ^6.0.2 || ^7.0.0" 1091 | 1092 | path-scurry@^2.0.0: 1093 | version "2.0.0" 1094 | resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580" 1095 | integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== 1096 | dependencies: 1097 | lru-cache "^11.0.0" 1098 | minipass "^7.1.2" 1099 | 1100 | picomatch@^2.3.1: 1101 | version "2.3.1" 1102 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1103 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1104 | 1105 | prelude-ls@^1.2.1: 1106 | version "1.2.1" 1107 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" 1108 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 1109 | 1110 | prettier-linter-helpers@^1.0.0: 1111 | version "1.0.0" 1112 | resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" 1113 | integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== 1114 | dependencies: 1115 | fast-diff "^1.1.2" 1116 | 1117 | prettier@^3.5.3: 1118 | version "3.5.3" 1119 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" 1120 | integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== 1121 | 1122 | punycode@^2.1.0: 1123 | version "2.3.1" 1124 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" 1125 | integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 1126 | 1127 | queue-microtask@^1.2.2: 1128 | version "1.2.3" 1129 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 1130 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 1131 | 1132 | reflect-metadata@^0.2.2: 1133 | version "0.2.2" 1134 | resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" 1135 | integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== 1136 | 1137 | resolve-from@^4.0.0: 1138 | version "4.0.0" 1139 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1140 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1141 | 1142 | reusify@^1.0.4: 1143 | version "1.1.0" 1144 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" 1145 | integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== 1146 | 1147 | rimraf@^6.0.1: 1148 | version "6.0.1" 1149 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-6.0.1.tgz#ffb8ad8844dd60332ab15f52bc104bc3ed71ea4e" 1150 | integrity sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A== 1151 | dependencies: 1152 | glob "^11.0.0" 1153 | package-json-from-dist "^1.0.0" 1154 | 1155 | rolldown@^1.0.0-beta.8: 1156 | version "1.0.0-beta.8" 1157 | resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.0.0-beta.8.tgz#be4f19988259ea7dda58a1ef8eeddebafb1fcfc8" 1158 | integrity sha512-lwctoQjonOosxGhVbuoIARk8TNO2roqAh/ArhNmT/e/INMN+fzO0++yCypVZLZczOdgTARrYmsOEnTgMOt9sSg== 1159 | dependencies: 1160 | "@oxc-project/types" "0.65.0" 1161 | "@valibot/to-json-schema" "1.0.0" 1162 | ansis "^3.17.0" 1163 | valibot "1.0.0" 1164 | optionalDependencies: 1165 | "@rolldown/binding-darwin-arm64" "1.0.0-beta.8" 1166 | "@rolldown/binding-darwin-x64" "1.0.0-beta.8" 1167 | "@rolldown/binding-freebsd-x64" "1.0.0-beta.8" 1168 | "@rolldown/binding-linux-arm-gnueabihf" "1.0.0-beta.8" 1169 | "@rolldown/binding-linux-arm64-gnu" "1.0.0-beta.8" 1170 | "@rolldown/binding-linux-arm64-musl" "1.0.0-beta.8" 1171 | "@rolldown/binding-linux-x64-gnu" "1.0.0-beta.8" 1172 | "@rolldown/binding-linux-x64-musl" "1.0.0-beta.8" 1173 | "@rolldown/binding-wasm32-wasi" "1.0.0-beta.8" 1174 | "@rolldown/binding-win32-arm64-msvc" "1.0.0-beta.8" 1175 | "@rolldown/binding-win32-ia32-msvc" "1.0.0-beta.8" 1176 | "@rolldown/binding-win32-x64-msvc" "1.0.0-beta.8" 1177 | 1178 | rollup@^4.40.0: 1179 | version "4.40.0" 1180 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.40.0.tgz#13742a615f423ccba457554f006873d5a4de1920" 1181 | integrity sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w== 1182 | dependencies: 1183 | "@types/estree" "1.0.7" 1184 | optionalDependencies: 1185 | "@rollup/rollup-android-arm-eabi" "4.40.0" 1186 | "@rollup/rollup-android-arm64" "4.40.0" 1187 | "@rollup/rollup-darwin-arm64" "4.40.0" 1188 | "@rollup/rollup-darwin-x64" "4.40.0" 1189 | "@rollup/rollup-freebsd-arm64" "4.40.0" 1190 | "@rollup/rollup-freebsd-x64" "4.40.0" 1191 | "@rollup/rollup-linux-arm-gnueabihf" "4.40.0" 1192 | "@rollup/rollup-linux-arm-musleabihf" "4.40.0" 1193 | "@rollup/rollup-linux-arm64-gnu" "4.40.0" 1194 | "@rollup/rollup-linux-arm64-musl" "4.40.0" 1195 | "@rollup/rollup-linux-loongarch64-gnu" "4.40.0" 1196 | "@rollup/rollup-linux-powerpc64le-gnu" "4.40.0" 1197 | "@rollup/rollup-linux-riscv64-gnu" "4.40.0" 1198 | "@rollup/rollup-linux-riscv64-musl" "4.40.0" 1199 | "@rollup/rollup-linux-s390x-gnu" "4.40.0" 1200 | "@rollup/rollup-linux-x64-gnu" "4.40.0" 1201 | "@rollup/rollup-linux-x64-musl" "4.40.0" 1202 | "@rollup/rollup-win32-arm64-msvc" "4.40.0" 1203 | "@rollup/rollup-win32-ia32-msvc" "4.40.0" 1204 | "@rollup/rollup-win32-x64-msvc" "4.40.0" 1205 | fsevents "~2.3.2" 1206 | 1207 | run-parallel@^1.1.9: 1208 | version "1.2.0" 1209 | resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" 1210 | integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 1211 | dependencies: 1212 | queue-microtask "^1.2.2" 1213 | 1214 | semver@^7.6.0: 1215 | version "7.7.1" 1216 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" 1217 | integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== 1218 | 1219 | shebang-command@^2.0.0: 1220 | version "2.0.0" 1221 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1222 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1223 | dependencies: 1224 | shebang-regex "^3.0.0" 1225 | 1226 | shebang-regex@^3.0.0: 1227 | version "3.0.0" 1228 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1229 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1230 | 1231 | signal-exit@^4.0.1: 1232 | version "4.1.0" 1233 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" 1234 | integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== 1235 | 1236 | "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: 1237 | name string-width-cjs 1238 | version "4.2.3" 1239 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1240 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1241 | dependencies: 1242 | emoji-regex "^8.0.0" 1243 | is-fullwidth-code-point "^3.0.0" 1244 | strip-ansi "^6.0.1" 1245 | 1246 | string-width@^5.0.1, string-width@^5.1.2: 1247 | version "5.1.2" 1248 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" 1249 | integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== 1250 | dependencies: 1251 | eastasianwidth "^0.2.0" 1252 | emoji-regex "^9.2.2" 1253 | strip-ansi "^7.0.1" 1254 | 1255 | "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1256 | name strip-ansi-cjs 1257 | version "6.0.1" 1258 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1259 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1260 | dependencies: 1261 | ansi-regex "^5.0.1" 1262 | 1263 | strip-ansi@^7.0.1: 1264 | version "7.1.0" 1265 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" 1266 | integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== 1267 | dependencies: 1268 | ansi-regex "^6.0.1" 1269 | 1270 | strip-json-comments@^3.1.1: 1271 | version "3.1.1" 1272 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1273 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1274 | 1275 | supports-color@^7.1.0: 1276 | version "7.2.0" 1277 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1278 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1279 | dependencies: 1280 | has-flag "^4.0.0" 1281 | 1282 | synckit@^0.11.0: 1283 | version "0.11.4" 1284 | resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.4.tgz#48972326b59723fc15b8d159803cf8302b545d59" 1285 | integrity sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ== 1286 | dependencies: 1287 | "@pkgr/core" "^0.2.3" 1288 | tslib "^2.8.1" 1289 | 1290 | to-regex-range@^5.0.1: 1291 | version "5.0.1" 1292 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1293 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1294 | dependencies: 1295 | is-number "^7.0.0" 1296 | 1297 | ts-api-utils@^2.0.1: 1298 | version "2.1.0" 1299 | resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" 1300 | integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== 1301 | 1302 | tslib@^2.0.0, tslib@^2.4.0, tslib@^2.8.1: 1303 | version "2.8.1" 1304 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" 1305 | integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== 1306 | 1307 | type-check@^0.4.0, type-check@~0.4.0: 1308 | version "0.4.0" 1309 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" 1310 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 1311 | dependencies: 1312 | prelude-ls "^1.2.1" 1313 | 1314 | typescript@^5.8.3: 1315 | version "5.8.3" 1316 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" 1317 | integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== 1318 | 1319 | undici-types@~6.21.0: 1320 | version "6.21.0" 1321 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" 1322 | integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== 1323 | 1324 | uri-js@^4.2.2: 1325 | version "4.4.1" 1326 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1327 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1328 | dependencies: 1329 | punycode "^2.1.0" 1330 | 1331 | valibot@1.0.0: 1332 | version "1.0.0" 1333 | resolved "https://registry.yarnpkg.com/valibot/-/valibot-1.0.0.tgz#1f82514296abcd23d0ae4280088ba85f8651c564" 1334 | integrity sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw== 1335 | 1336 | which@^2.0.1: 1337 | version "2.0.2" 1338 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1339 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1340 | dependencies: 1341 | isexe "^2.0.0" 1342 | 1343 | word-wrap@^1.2.5: 1344 | version "1.2.5" 1345 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" 1346 | integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== 1347 | 1348 | "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": 1349 | version "7.0.0" 1350 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1351 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1352 | dependencies: 1353 | ansi-styles "^4.0.0" 1354 | string-width "^4.1.0" 1355 | strip-ansi "^6.0.0" 1356 | 1357 | wrap-ansi@^8.1.0: 1358 | version "8.1.0" 1359 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" 1360 | integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== 1361 | dependencies: 1362 | ansi-styles "^6.1.0" 1363 | string-width "^5.0.1" 1364 | strip-ansi "^7.0.1" 1365 | 1366 | yocto-queue@^0.1.0: 1367 | version "0.1.0" 1368 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1369 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1370 | --------------------------------------------------------------------------------