diff --git a/packages/compiler-cli/ngcc/src/host/commonjs_host.ts b/packages/compiler-cli/ngcc/src/host/commonjs_host.ts index 762a77d0a65fc..00b4bf4f5bccc 100644 --- a/packages/compiler-cli/ngcc/src/host/commonjs_host.ts +++ b/packages/compiler-cli/ngcc/src/host/commonjs_host.ts @@ -34,11 +34,6 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost { } getImportOfIdentifier(id: ts.Identifier): Import|null { - const superImport = super.getImportOfIdentifier(id); - if (superImport !== null) { - return superImport; - } - const requireCall = this.findCommonJsImport(id); if (requireCall === null) { return null; @@ -47,8 +42,7 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost { } getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null { - return (!id.getSourceFile().isDeclarationFile && this.getCommonJsImportedDeclaration(id)) || - super.getDeclarationOfIdentifier(id); + return this.getCommonJsImportedDeclaration(id) || super.getDeclarationOfIdentifier(id); } getExportsOfModule(module: ts.Node): Map|null { diff --git a/packages/compiler-cli/ngcc/src/host/delegating_host.ts b/packages/compiler-cli/ngcc/src/host/delegating_host.ts new file mode 100644 index 0000000000000..3bef3e432dec0 --- /dev/null +++ b/packages/compiler-cli/ngcc/src/host/delegating_host.ts @@ -0,0 +1,157 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as ts from 'typescript'; + +import {ClassDeclaration, ClassMember, CtorParameter, Declaration, Decorator, FunctionDefinition, Import, ReflectionHost} from '../../../src/ngtsc/reflection'; +import {isFromDtsFile} from '../../../src/ngtsc/util/src/typescript'; + +import {ModuleWithProvidersFunction, NgccClassSymbol, NgccReflectionHost, SwitchableVariableDeclaration} from './ngcc_host'; + +/** + * A reflection host implementation that delegates reflector queries depending on whether they + * reflect on declaration files (for dependent libraries) or source files within the entry-point + * that is being compiled. The first type of queries are handled by the regular TypeScript + * reflection host, whereas the other queries are handled by an `NgccReflectionHost` that is + * specific to the entry-point's format. + */ +export class DelegatingReflectionHost implements NgccReflectionHost { + constructor(private tsHost: ReflectionHost, private ngccHost: NgccReflectionHost) {} + + getConstructorParameters(clazz: ClassDeclaration): CtorParameter[]|null { + if (isFromDtsFile(clazz)) { + return this.tsHost.getConstructorParameters(clazz); + } + return this.ngccHost.getConstructorParameters(clazz); + } + + getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null { + if (isFromDtsFile(id)) { + return this.tsHost.getDeclarationOfIdentifier(id); + } + return this.ngccHost.getDeclarationOfIdentifier(id); + } + + getDecoratorsOfDeclaration(declaration: ts.Declaration): Decorator[]|null { + if (isFromDtsFile(declaration)) { + return this.tsHost.getDecoratorsOfDeclaration(declaration); + } + return this.ngccHost.getDecoratorsOfDeclaration(declaration); + } + + getDefinitionOfFunction(fn: ts.Node): FunctionDefinition|null { + if (isFromDtsFile(fn)) { + return this.tsHost.getDefinitionOfFunction(fn); + } + return this.ngccHost.getDefinitionOfFunction(fn); + } + + getDtsDeclaration(declaration: ts.Declaration): ts.Declaration|null { + if (isFromDtsFile(declaration)) { + return this.tsHost.getDtsDeclaration(declaration); + } + return this.ngccHost.getDtsDeclaration(declaration); + } + + getExportsOfModule(module: ts.Node): Map|null { + if (isFromDtsFile(module)) { + return this.tsHost.getExportsOfModule(module); + } + return this.ngccHost.getExportsOfModule(module); + } + + getGenericArityOfClass(clazz: ClassDeclaration): number|null { + if (isFromDtsFile(clazz)) { + return this.tsHost.getGenericArityOfClass(clazz); + } + return this.ngccHost.getGenericArityOfClass(clazz); + } + + getImportOfIdentifier(id: ts.Identifier): Import|null { + if (isFromDtsFile(id)) { + return this.tsHost.getImportOfIdentifier(id); + } + return this.ngccHost.getImportOfIdentifier(id); + } + + getInternalNameOfClass(clazz: ClassDeclaration): ts.Identifier { + if (isFromDtsFile(clazz)) { + return this.tsHost.getInternalNameOfClass(clazz); + } + return this.ngccHost.getInternalNameOfClass(clazz); + } + + getAdjacentNameOfClass(clazz: ClassDeclaration): ts.Identifier { + if (isFromDtsFile(clazz)) { + return this.tsHost.getAdjacentNameOfClass(clazz); + } + return this.ngccHost.getAdjacentNameOfClass(clazz); + } + + getMembersOfClass(clazz: ClassDeclaration): ClassMember[] { + if (isFromDtsFile(clazz)) { + return this.tsHost.getMembersOfClass(clazz); + } + return this.ngccHost.getMembersOfClass(clazz); + } + + getVariableValue(declaration: ts.VariableDeclaration): ts.Expression|null { + if (isFromDtsFile(declaration)) { + return this.tsHost.getVariableValue(declaration); + } + return this.ngccHost.getVariableValue(declaration); + } + + hasBaseClass(clazz: ClassDeclaration): boolean { + if (isFromDtsFile(clazz)) { + return this.tsHost.hasBaseClass(clazz); + } + return this.ngccHost.hasBaseClass(clazz); + } + + getBaseClassExpression(clazz: ClassDeclaration): ts.Expression|null { + if (isFromDtsFile(clazz)) { + return this.tsHost.getBaseClassExpression(clazz); + } + return this.ngccHost.getBaseClassExpression(clazz); + } + + isClass(node: ts.Node): node is ClassDeclaration { + if (isFromDtsFile(node)) { + return this.tsHost.isClass(node); + } + return this.ngccHost.isClass(node); + } + + // Note: the methods below are specific to ngcc and the entry-point that is being compiled, so + // they don't take declaration files into account. + + findClassSymbols(sourceFile: ts.SourceFile): NgccClassSymbol[] { + return this.ngccHost.findClassSymbols(sourceFile); + } + + getClassSymbol(node: ts.Node): NgccClassSymbol|undefined { + return this.ngccHost.getClassSymbol(node); + } + + getDecoratorsOfSymbol(symbol: NgccClassSymbol): Decorator[]|null { + return this.ngccHost.getDecoratorsOfSymbol(symbol); + } + + getModuleWithProvidersFunctions(sf: ts.SourceFile): ModuleWithProvidersFunction[] { + return this.ngccHost.getModuleWithProvidersFunctions(sf); + } + + getSwitchableDeclarations(module: ts.Node): SwitchableVariableDeclaration[] { + return this.ngccHost.getSwitchableDeclarations(module); + } + + getEndOfClass(classSymbol: NgccClassSymbol): ts.Node { + return this.ngccHost.getEndOfClass(classSymbol); + } +} diff --git a/packages/compiler-cli/ngcc/src/host/esm5_host.ts b/packages/compiler-cli/ngcc/src/host/esm5_host.ts index 6ffbe339524fc..4c8bb221260fc 100644 --- a/packages/compiler-cli/ngcc/src/host/esm5_host.ts +++ b/packages/compiler-cli/ngcc/src/host/esm5_host.ts @@ -41,8 +41,6 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { * @param clazz a `ClassDeclaration` representing the class over which to reflect. */ hasBaseClass(clazz: ClassDeclaration): boolean { - if (super.hasBaseClass(clazz)) return true; - const classSymbol = this.getClassSymbol(clazz); if (classSymbol === undefined) { return false; @@ -58,11 +56,6 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { } getBaseClassExpression(clazz: ClassDeclaration): ts.Expression|null { - const superBaseClassIdentifier = super.getBaseClassExpression(clazz); - if (superBaseClassIdentifier) { - return superBaseClassIdentifier; - } - const classSymbol = this.getClassSymbol(clazz); if (classSymbol === undefined) { return null; diff --git a/packages/compiler-cli/ngcc/src/host/umd_host.ts b/packages/compiler-cli/ngcc/src/host/umd_host.ts index 1486dedea4222..b053820c77621 100644 --- a/packages/compiler-cli/ngcc/src/host/umd_host.ts +++ b/packages/compiler-cli/ngcc/src/host/umd_host.ts @@ -33,11 +33,6 @@ export class UmdReflectionHost extends Esm5ReflectionHost { } getImportOfIdentifier(id: ts.Identifier): Import|null { - const superImport = super.getImportOfIdentifier(id); - if (superImport !== null) { - return superImport; - } - // Is `id` a namespaced property access, e.g. `Directive` in `core.Directive`? // If so capture the symbol of the namespace, e.g. `core`. const nsIdentifier = findNamespaceOfIdentifier(id); @@ -47,8 +42,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost { } getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null { - return (!id.getSourceFile().isDeclarationFile && this.getUmdImportedDeclaration(id)) || - super.getDeclarationOfIdentifier(id); + return this.getUmdImportedDeclaration(id) || super.getDeclarationOfIdentifier(id); } getExportsOfModule(module: ts.Node): Map|null { diff --git a/packages/compiler-cli/ngcc/src/packages/transformer.ts b/packages/compiler-cli/ngcc/src/packages/transformer.ts index 65c3f0a223540..6ae9785929eef 100644 --- a/packages/compiler-cli/ngcc/src/packages/transformer.ts +++ b/packages/compiler-cli/ngcc/src/packages/transformer.ts @@ -8,6 +8,7 @@ import * as ts from 'typescript'; import {FileSystem} from '../../../src/ngtsc/file_system'; +import {TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; import {DecorationAnalyzer} from '../analysis/decoration_analyzer'; import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../analysis/module_with_providers_analyzer'; import {NgccReferencesRegistry} from '../analysis/ngcc_references_registry'; @@ -15,6 +16,7 @@ import {ExportInfo, PrivateDeclarationsAnalyzer} from '../analysis/private_decla import {SwitchMarkerAnalyses, SwitchMarkerAnalyzer} from '../analysis/switch_marker_analyzer'; import {CompiledFile} from '../analysis/types'; import {CommonJsReflectionHost} from '../host/commonjs_host'; +import {DelegatingReflectionHost} from '../host/delegating_host'; import {Esm2015ReflectionHost} from '../host/esm2015_host'; import {Esm5ReflectionHost} from '../host/esm5_host'; import {NgccReflectionHost} from '../host/ngcc_host'; @@ -69,7 +71,9 @@ export class Transformer { * @returns information about the files that were transformed. */ transform(bundle: EntryPointBundle): TransformResult { - const reflectionHost = this.getHost(bundle); + const ngccReflectionHost = this.getHost(bundle); + const tsReflectionHost = new TypeScriptReflectionHost(bundle.src.program.getTypeChecker()); + const reflectionHost = new DelegatingReflectionHost(tsReflectionHost, ngccReflectionHost); // Parse and analyze the files. const {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses, @@ -81,7 +85,7 @@ export class Transformer { } // Transform the source files and source maps. - const srcFormatter = this.getRenderingFormatter(reflectionHost, bundle); + const srcFormatter = this.getRenderingFormatter(ngccReflectionHost, bundle); const renderer = new Renderer(reflectionHost, srcFormatter, this.fs, this.logger, bundle); let renderedFiles = renderer.renderProgram( diff --git a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts index e232dde2017d2..3ebd4f1fd526c 100644 --- a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts @@ -1607,30 +1607,6 @@ exports.ExternalModule = ExternalModule; expect(importOfIdent).toEqual({name: 'a', from: './file_a'}); }); - it('should find the import of an identifier in a declaration file', () => { - loadTestFiles([ - { - name: _('/index.d.ts'), - contents: ` - import {MyClass} from './myclass.d.ts'; - export declare const a: MyClass;` - }, - { - name: _('/myclass.d.ts'), - contents: `export declare class MyClass {}`, - } - ]); - const bundle = makeTestBundleProgram(_('/index.d.ts')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); - const variableNode = - getDeclaration(bundle.program, _('/index.d.ts'), 'a', isNamedVariableDeclaration); - const identifier = - ((variableNode.type as ts.TypeReferenceNode).typeName as ts.Identifier); - - const importOfIdent = host.getImportOfIdentifier(identifier !); - expect(importOfIdent).toEqual({name: 'MyClass', from: './myclass.d.ts'}); - }); - it('should return null if the identifier was not imported', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); @@ -1816,39 +1792,6 @@ exports.ExternalModule = ExternalModule; expect(importOfIdent.viaModule).toBe('lib'); }); - it('should return the correct declaration of an identifier imported in a typings file', - () => { - const files = [ - { - name: _('/node_modules/test-package/index.d.ts'), - contents: ` - import {SubModule} from 'sub_module'; - export const x = SubModule; - `, - }, - { - name: _('/node_modules/sub_module/index.d.ts'), - contents: 'export class SubModule {}', - } - ]; - loadTestFiles(files); - const bundle = makeTestBundleProgram(files[0].name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); - const expectedDeclaration = getDeclaration( - bundle.program, files[1].name, 'SubModule', isNamedClassDeclaration); - const x = - getDeclaration(bundle.program, files[0].name, 'x', isNamedVariableDeclaration); - if (x.initializer === undefined || !ts.isIdentifier(x.initializer)) { - return fail('Expected constant `x` to have an identifer as an initializer.'); - } - const decl = host.getDeclarationOfIdentifier(x.initializer); - if (decl === null) { - return fail('Expected to find a declaration for ' + x.initializer.getText()); - } - expect(decl.viaModule).toEqual('sub_module'); - expect(decl.node).toBe(expectedDeclaration); - }); - it('should recognize TypeScript helpers (as function declarations)', () => { const file: TestFile = { name: _('/test.js'), diff --git a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts index e4e2dd14cfebd..6a549b65eba32 100644 --- a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts @@ -1776,29 +1776,6 @@ runInEachFileSystem(() => { expect(importOfIdent).toEqual({name: 'a', from: './file_a'}); }); - it('should find the import of an identifier in a declaration file', () => { - loadTestFiles([ - { - name: _('/index.d.ts'), - contents: ` - import {MyClass} from './myclass.d.ts'; - export declare const a: MyClass;` - }, - { - name: _('/myclass.d.ts'), - contents: `export declare class MyClass {}`, - } - ]); - const bundle = makeTestBundleProgram(_('/index.d.ts')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); - const variableNode = - getDeclaration(bundle.program, _('/index.d.ts'), 'a', isNamedVariableDeclaration); - const identifier = ((variableNode.type as ts.TypeReferenceNode).typeName as ts.Identifier); - - const importOfIdent = host.getImportOfIdentifier(identifier !); - expect(importOfIdent).toEqual({name: 'MyClass', from: './myclass.d.ts'}); - }); - it('should return null if the identifier was not imported', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); @@ -1942,39 +1919,6 @@ runInEachFileSystem(() => { expect(actualDeclaration !.viaModule).toBe('@angular/core'); }); - it('should return the correct declaration of an identifier imported in a typings file', - () => { - - const FILES = [ - { - name: _('/node_modules/test-package/index.d.ts'), - contents: ` - import {SubModule} from 'sub_module'; - export const x = SubModule; - `, - }, - { - name: _('/node_modules/sub_module/index.d.ts'), - contents: `export class SubModule {}`, - } - ]; - loadTestFiles(FILES); - const bundle = makeTestBundleProgram(FILES[0].name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); - const expectedDeclaration = - getDeclaration(bundle.program, FILES[1].name, 'SubModule', isNamedClassDeclaration); - const x = getDeclaration(bundle.program, FILES[0].name, 'x', isNamedVariableDeclaration); - if (x.initializer === undefined || !ts.isIdentifier(x.initializer)) { - return fail('Expected constant `x` to have an identifer as an initializer.'); - } - const decl = host.getDeclarationOfIdentifier(x.initializer); - if (decl === null) { - return fail('Expected to find a declaration for ' + x.initializer.getText()); - } - expect(decl.viaModule).toEqual('sub_module'); - expect(decl.node).toBe(expectedDeclaration); - }); - it('should recognize TypeScript helpers (as function declarations)', () => { const file: TestFile = { name: _('/test.js'), diff --git a/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts b/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts index 0d68b909433db..fe44a49b46455 100644 --- a/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts +++ b/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts @@ -132,7 +132,7 @@ runInEachFileSystem(() => { mainNgcc({ basePath: '/node_modules', targetEntryPointPath: 'test-package', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], }); const jsContents = fs.readFile(_(`/node_modules/test-package/index.js`)).replace(/\s+/g, ' '); @@ -242,13 +242,77 @@ runInEachFileSystem(() => { mainNgcc({ basePath: '/node_modules', targetEntryPointPath: 'test-package', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], }); const jsContents = fs.readFile(_(`/node_modules/test-package/index.js`)); expect(jsContents).not.toMatch(/\bconst \w+\s*=/); }); + it('should be able to reflect into external libraries', () => { + compileIntoApf('lib', { + '/index.ts': ` + export * from './constants'; + export * from './module'; + `, + '/constants.ts': ` + export const selectorA = '[selector-a]'; + + export class Selectors { + static readonly B = '[selector-b]'; + } + `, + '/module.ts': ` + import {NgModule, ModuleWithProviders} from '@angular/core'; + + @NgModule() + export class MyOtherModule {} + + export class MyModule { + static forRoot(): ModuleWithProviders { + return {ngModule: MyOtherModule}; + } + } + ` + }); + + compileIntoFlatEs5Package('test-package', { + '/index.ts': ` + import {Directive, Input, NgModule} from '@angular/core'; + import * as lib from 'lib'; + + @Directive({ + selector: lib.selectorA, + }) + export class DirectiveA { + } + + @Directive({ + selector: lib.Selectors.B, + }) + export class DirectiveB { + } + + @NgModule({ + imports: [lib.MyModule.forRoot()], + declarations: [DirectiveA, DirectiveB], + }) + export class FooModule {} + `, + }); + + mainNgcc({ + basePath: '/node_modules', + targetEntryPointPath: 'test-package', + propertiesToConsider: ['module'], + }); + + const jsContents = fs.readFile(_(`/node_modules/test-package/index.js`)); + expect(jsContents).toContain('"selector-a"'); + expect(jsContents).toContain('"selector-b"'); + expect(jsContents).toContain('imports: [ɵngcc1.MyOtherModule]'); + }); + it('should add ɵfac but not duplicate ɵprov properties on injectables', () => { compileIntoFlatEs5Package('test-package', { '/index.ts': ` @@ -266,7 +330,7 @@ runInEachFileSystem(() => { mainNgcc({ basePath: '/node_modules', targetEntryPointPath: 'test-package', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], }); const after = fs.readFile(_(`/node_modules/test-package/index.js`)); @@ -298,7 +362,7 @@ runInEachFileSystem(() => { mainNgcc({ basePath: '/node_modules', targetEntryPointPath: 'test-package', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], }); const jsContents = fs.readFile(_(`/node_modules/test-package/index.js`)); @@ -408,7 +472,7 @@ runInEachFileSystem(() => { mainNgcc({ basePath: '/node_modules', targetEntryPointPath: 'test-package', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], }); const jsContents = fs.readFile(_(`/node_modules/test-package/index.js`)); @@ -669,7 +733,7 @@ runInEachFileSystem(() => { }); mainNgcc({ basePath: '/node_modules', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], logger: new MockLogger(), }); @@ -685,15 +749,15 @@ runInEachFileSystem(() => { // Now run ngcc again to see that it cleans out the outdated artifacts mainNgcc({ basePath: '/node_modules', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], logger: new MockLogger(), }); const newPackageJson = loadPackage('test-package', _('/node_modules')); expect(newPackageJson.__processed_by_ivy_ngcc__).toEqual({ - main: '0.0.0-PLACEHOLDER', + module: '0.0.0-PLACEHOLDER', typings: '0.0.0-PLACEHOLDER', }); - expect(newPackageJson.main_ivy_ngcc).toBeUndefined(); + expect(newPackageJson.module_ivy_ngcc).toBeUndefined(); expect(fs.exists(_('/node_modules/test-package/x.js'))).toBe(true); expect(fs.exists(_('/node_modules/test-package/x.js.__ivy_ngcc_bak'))).toBe(false); expect(fs.readFile(_('/node_modules/test-package/x.js'))).toEqual('original content'); @@ -1274,7 +1338,7 @@ runInEachFileSystem(() => { mainNgcc({ basePath: '/node_modules', targetEntryPointPath: 'test-package', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], }); @@ -1315,7 +1379,7 @@ runInEachFileSystem(() => { mainNgcc({ basePath: '/node_modules', targetEntryPointPath: 'test-package', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], }); @@ -1358,7 +1422,7 @@ runInEachFileSystem(() => { mainNgcc({ basePath: '/node_modules', targetEntryPointPath: 'test-package', - propertiesToConsider: ['main'], + propertiesToConsider: ['module'], }); const dtsContents = fs.readFile(_(`/node_modules/test-package/index.d.ts`)); diff --git a/packages/compiler-cli/ngcc/test/integration/util.ts b/packages/compiler-cli/ngcc/test/integration/util.ts index 32a42a2078ab1..e0880074831f5 100644 --- a/packages/compiler-cli/ngcc/test/integration/util.ts +++ b/packages/compiler-cli/ngcc/test/integration/util.ts @@ -33,6 +33,7 @@ export function compileIntoFlatEs5Package(pkgName: string, sources: PackageSourc compileIntoFlatPackage(pkgName, sources, { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.ESNext, + formatProperty: 'module', }); } @@ -46,6 +47,11 @@ export interface FlatLayoutOptions { * The module kind to use in the compiled result. */ module: ts.ModuleKind; + + /** + * The name of the property in package.json that refers to the root source file. + */ + formatProperty: string; } /** @@ -90,7 +96,7 @@ function compileIntoFlatPackage( const pkgJson: unknown = { name: pkgName, version: '0.0.1', - main: './index.js', + [options.formatProperty]: './index.js', typings: './index.d.ts', };