UNPKG

@jfconley/di-compiler

Version:

A Custom Transformer for Typescript that enables compile-time Dependency Injection

1 lines 101 kB
{"version":3,"file":"common.cjs","sources":["../../../src/transformer/constant.ts","../../../src/transformer/before/util.ts","../../../src/transformer/before/visitor/visit-class-like-declaration.ts","../../../src/util/ts-util.ts","../../../src/util/util.ts","../../../src/transformer/before/visitor/visit-call-expression.ts","../../../src/transformer/before/visitor/visit-node.ts","../../../src/transformer/before/before-transformer.ts","../../../src/transformer/after/visitor/visit-root-block.ts","../../../src/transformer/after/visitor/visit-root-block-source-file.ts","../../../src/transformer/after/visitor/visit-root-block-block.ts","../../../src/transformer/after/visitor/visit-define-array-literal-expression.ts","../../../src/transformer/after/visitor/visit-node.ts","../../../src/transformer/after/after-transformer.ts","../../../src/transformer/get-base-visitor-context.ts","../../../src/transformer/di.ts","../../../src/transformer/transform.ts","../../../src/transformer/cache.ts"],"sourcesContent":["export const CONSTRUCTOR_ARGUMENTS_SYMBOL_IDENTIFIER = `___CTOR_ARGS___`;\nexport const DI_CONTAINER_NAME = \"DIContainer\";\n","/* eslint-disable deprecation/deprecation */\nimport type {TS} from \"../../type/type.js\";\nimport type {VisitorContext} from \"../visitor-context.js\";\n\n/**\n * A TypeNode such as IFoo<string> should still yield the service name \"IFoo\".\n * This helper generates a proper service name from a TypeNode\n */\nexport function pickServiceOrImplementationName(node: TS.Expression | TS.TypeNode | TS.EntityName, context: VisitorContext): string {\n\tconst {typescript} = context;\n\n\tif (typescript.isTypeReferenceNode(node)) {\n\t\treturn pickServiceOrImplementationName(node.typeName, context);\n\t} else if (typescript.isIndexedAccessTypeNode(node)) {\n\t\treturn `${pickServiceOrImplementationName(node.objectType, context)}[${pickServiceOrImplementationName(node.indexType, context)}]`;\n\t} else {\n\t\treturn node.getText().trim();\n\t}\n}\n\nexport function getModifierLikes(node: TS.Node): readonly TS.ModifierLike[] | undefined {\n\tif (\"decorators\" in node && Array.isArray(node.decorators)) {\n\t\treturn [...(node.decorators ?? []), ...(node.modifiers ?? [])];\n\t} else {\n\t\treturn node.modifiers;\n\t}\n}\n","import {CONSTRUCTOR_ARGUMENTS_SYMBOL_IDENTIFIER} from \"../../constant.js\";\nimport type {TS} from \"../../../type/type.js\";\nimport type {BeforeVisitorOptions} from \"../before-visitor-options.js\";\nimport type {VisitorContext} from \"../../visitor-context.js\";\nimport {getModifierLikes, pickServiceOrImplementationName} from \"../util.js\";\n\nexport function visitClassLikeDeclaration(options: BeforeVisitorOptions<TS.ClassLikeDeclaration>): TS.VisitResult<TS.Node> {\n\tconst {node, childContinuation, continuation, context} = options;\n\tconst {typescript, factory} = context;\n\tconst constructorDeclaration = node.members.find(typescript.isConstructorDeclaration);\n\n\t// If there are no constructor declaration for the ClassLikeDeclaration, there's nothing to do\n\tif (constructorDeclaration == null) {\n\t\treturn childContinuation(node);\n\t}\n\n\tconst updatedClassMembers: readonly TS.ClassElement[] = [\n\t\t...(node.members.map(continuation) as TS.ClassElement[]),\n\t\tfactory.createGetAccessorDeclaration(\n\t\t\t[factory.createModifier(typescript.SyntaxKind.StaticKeyword)],\n\t\t\tfactory.createComputedPropertyName(factory.createIdentifier(`Symbol.for(\"${CONSTRUCTOR_ARGUMENTS_SYMBOL_IDENTIFIER}\")`)),\n\t\t\t[],\n\t\t\tundefined,\n\t\t\tfactory.createBlock([factory.createReturnStatement(getParameterTypeNamesAsArrayLiteral(constructorDeclaration.parameters, context))])\n\t\t)\n\t];\n\n\tconst modifierLikes = getModifierLikes(node);\n\n\tif (typescript.isClassDeclaration(node)) {\n\t\treturn factory.updateClassDeclaration(node, modifierLikes, node.name, node.typeParameters, node.heritageClauses, updatedClassMembers);\n\t} else {\n\t\treturn factory.updateClassExpression(node, modifierLikes, node.name, node.typeParameters, node.heritageClauses, updatedClassMembers);\n\t}\n}\n\n/**\n * Takes ConstructorParams for the given NodeArray of ParameterDeclarations\n */\nfunction getParameterTypeNamesAsArrayLiteral(parameters: TS.NodeArray<TS.ParameterDeclaration>, context: VisitorContext): TS.ArrayLiteralExpression {\n\tconst {factory} = context;\n\tconst constructorParams: TS.Expression[] = [];\n\n\tfor (let i = 0; i < parameters.length; i++) {\n\t\tconst parameter = parameters[i];\n\t\t// If the parameter has no type, there's nothing to extract\n\t\tif (parameter.type == null) {\n\t\t\tconstructorParams[i] = factory.createIdentifier(\"undefined\");\n\t\t} else {\n\t\t\tconstructorParams[i] = factory.createNoSubstitutionTemplateLiteral(pickServiceOrImplementationName(parameter.type, context));\n\t\t}\n\t}\n\n\treturn factory.createArrayLiteralExpression(constructorParams);\n}\n","import {TS} from \"../type/type.js\";\nimport type {ImportedSymbol} from \"../type/imported-symbol.js\";\nimport type {BaseVisitorContext, VisitorContext} from \"../transformer/visitor-context.js\";\nimport type {RootBlock} from \"../type/root-block.js\";\n\ntype TSWithHelpers = typeof TS & {\n\timportDefaultHelper?: TS.EmitHelper;\n\timportStarHelper?: TS.EmitHelper;\n};\n\n// For some TypeScript versions, such as 3.1, these helpers are not exposed by TypeScript,\n// so they will have to be duplicated and reused from here in these rare cases\nconst HELPERS = {\n\timportDefaultHelper: {\n\t\tname: \"typescript:commonjsimportdefault\",\n\t\tscoped: false,\n\t\ttext: '\\nvar __importDefault = (this && this.__importDefault) || function (mod) {\\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\\n};'\n\t},\n\timportStarHelper: {\n\t\tname: \"typescript:commonjsimportstar\",\n\t\tscoped: false,\n\t\ttext: '\\nvar __importStar = (this && this.__importStar) || function (mod) {\\n if (mod && mod.__esModule) return mod;\\n var result = {};\\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\\n result[\"default\"] = mod;\\n return result;\\n};'\n\t}\n} as const;\n\nexport function needsImportPreservationLogic(context: Pick<BaseVisitorContext, \"compilerOptions\" | \"typescript\">): boolean;\nexport function needsImportPreservationLogic(typescript: typeof TS, compilerOptions: TS.CompilerOptions): boolean;\nexport function needsImportPreservationLogic(\n\ttypescriptOrContext: Pick<BaseVisitorContext, \"compilerOptions\" | \"typescript\"> | typeof TS,\n\tcompilerOptionsOrUndefined?: TS.CompilerOptions\n): boolean {\n\tconst typescript = arguments.length >= 2 ? (typescriptOrContext as typeof TS) : (typescriptOrContext as Pick<BaseVisitorContext, \"compilerOptions\" | \"typescript\">).typescript;\n\tconst compilerOptions = arguments.length >= 2 ? compilerOptionsOrUndefined! : (typescriptOrContext as Pick<BaseVisitorContext, \"compilerOptions\" | \"typescript\">).compilerOptions;\n\n\t// If value imports shouldn't always be preserved, we'll have to perform import preservation logic\n\tif (!Boolean(compilerOptions.preserveValueImports)) return true;\n\n\t// Only TypeScript v4.5 and newer supports the `preserValueImports` Compiler option\n\tif (parseFloat(typescript.version) < 4.5) return true;\n\n\tswitch (compilerOptions.module) {\n\t\tcase typescript.ModuleKind.AMD:\n\t\tcase typescript.ModuleKind.UMD:\n\t\tcase typescript.ModuleKind.CommonJS:\n\t\tcase typescript.ModuleKind.System:\n\t\tcase typescript.ModuleKind.None:\n\t\t\t// None of these module systems support the `preserValueImports` Compiler option\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function getImportDefaultHelper(typescript: TSWithHelpers): TS.EmitHelper {\n\treturn typescript.importDefaultHelper ?? HELPERS.importDefaultHelper;\n}\n\nexport function getImportStarHelper(typescript: TSWithHelpers): TS.EmitHelper {\n\treturn typescript.importStarHelper ?? HELPERS.importStarHelper;\n}\n\nexport function moduleKindSupportsImportHelpers(moduleKind: TS.ModuleKind = TS.ModuleKind.CommonJS, typescript: typeof TS): boolean {\n\tswitch (moduleKind) {\n\t\tcase typescript.ModuleKind.CommonJS:\n\t\tcase typescript.ModuleKind.UMD:\n\t\tcase typescript.ModuleKind.AMD:\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function moduleKindDefinesDependencies(moduleKind: TS.ModuleKind = TS.ModuleKind.CommonJS, typescript: typeof TS): boolean {\n\tswitch (moduleKind) {\n\t\tcase typescript.ModuleKind.UMD:\n\t\tcase typescript.ModuleKind.AMD:\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\ninterface EmitHelperFactory {\n\tgetUnscopedHelperName(helperName: string): TS.Identifier;\n}\n\ntype TSWithEmitHelpers = typeof TS &\n\t(\n\t\t| EmitHelperFactory\n\t\t| {\n\t\t\t\tcreateEmitHelperFactory(factory: TS.TransformationContext): EmitHelperFactory;\n\t\t }\n\t\t| {\n\t\t\t\tgetHelperName(helperName: string): TS.Identifier;\n\t\t }\n\t);\n\nexport function getUnscopedHelperName(context: VisitorContext, helperName: string): TS.Identifier {\n\tconst typescript = context.typescript as TSWithEmitHelpers;\n\tif (\"getUnscopedHelperName\" in typescript) {\n\t\treturn typescript.getUnscopedHelperName(helperName);\n\t} else if (\"createEmitHelperFactory\" in typescript) {\n\t\treturn typescript.createEmitHelperFactory(context.transformationContext).getUnscopedHelperName(helperName);\n\t} else {\n\t\treturn typescript.getHelperName(helperName);\n\t}\n}\n\nexport function getRootBlockInsertionPosition(rootBlock: RootBlock, typescript: typeof TS): number {\n\tlet insertPosition = 0;\n\n\tfor (let i = 0; i < rootBlock.statements.length; i++) {\n\t\tconst statement = rootBlock.statements[i];\n\n\t\tconst isUseStrict = typescript.isExpressionStatement(statement) && typescript.isStringLiteralLike(statement.expression) && statement.expression.text === \"use strict\";\n\n\t\tconst isEsModuleSymbol =\n\t\t\ttypescript.isExpressionStatement(statement) &&\n\t\t\ttypescript.isCallExpression(statement.expression) &&\n\t\t\ttypescript.isPropertyAccessExpression(statement.expression.expression) &&\n\t\t\ttypescript.isIdentifier(statement.expression.expression.expression) &&\n\t\t\ttypescript.isIdentifier(statement.expression.expression.name) &&\n\t\t\tstatement.expression.expression.expression.text === \"Object\" &&\n\t\t\tstatement.expression.expression.name.text === \"defineProperty\" &&\n\t\t\tstatement.expression.arguments.length >= 2 &&\n\t\t\ttypescript.isIdentifier(statement.expression.arguments[0]) &&\n\t\t\tstatement.expression.arguments[0].text === \"exports\" &&\n\t\t\ttypescript.isStringLiteralLike(statement.expression.arguments[1]) &&\n\t\t\tstatement.expression.arguments[1].text === \"__esModule\";\n\n\t\tif (isUseStrict || isEsModuleSymbol) {\n\t\t\tinsertPosition = Math.max(insertPosition, i + 1);\n\t\t}\n\t}\n\treturn insertPosition;\n}\n\nexport function getDefineArrayLiteralExpression(sourceFile: TS.SourceFile, context: VisitorContext): TS.ArrayLiteralExpression | undefined {\n\tconst {compilerOptions, typescript} = context;\n\n\tswitch (compilerOptions.module) {\n\t\tcase typescript.ModuleKind.ESNext:\n\t\tcase typescript.ModuleKind.ES2015:\n\t\tcase typescript.ModuleKind.ES2020:\n\t\tcase typescript.ModuleKind.ES2022:\n\t\tcase typescript.ModuleKind.NodeNext:\n\t\t\t// There are no such thing for these module types\n\t\t\treturn undefined;\n\n\t\t// If we're targeting UMD, the root block won't be the root scope, but the Function Body of an iife\n\t\tcase typescript.ModuleKind.UMD: {\n\t\t\tfor (const statement of sourceFile.statements) {\n\t\t\t\tif (\n\t\t\t\t\ttypescript.isExpressionStatement(statement) &&\n\t\t\t\t\ttypescript.isCallExpression(statement.expression) &&\n\t\t\t\t\ttypescript.isParenthesizedExpression(statement.expression.expression) &&\n\t\t\t\t\ttypescript.isFunctionExpression(statement.expression.expression.expression) &&\n\t\t\t\t\tstatement.expression.expression.expression.parameters.length === 1\n\t\t\t\t) {\n\t\t\t\t\tconst [firstParameter] = statement.expression.expression.expression.parameters;\n\t\t\t\t\tif (typescript.isIdentifier(firstParameter.name)) {\n\t\t\t\t\t\tif (firstParameter.name.text === \"factory\") {\n\t\t\t\t\t\t\tfor (const subStatement of statement.expression.expression.expression.body.statements) {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\ttypescript.isIfStatement(subStatement) &&\n\t\t\t\t\t\t\t\t\tsubStatement.elseStatement != null &&\n\t\t\t\t\t\t\t\t\ttypescript.isIfStatement(subStatement.elseStatement) &&\n\t\t\t\t\t\t\t\t\ttypescript.isBlock(subStatement.elseStatement.thenStatement)\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\tfor (const subSubStatement of subStatement.elseStatement.thenStatement.statements) {\n\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\ttypescript.isExpressionStatement(subSubStatement) &&\n\t\t\t\t\t\t\t\t\t\t\ttypescript.isCallExpression(subSubStatement.expression) &&\n\t\t\t\t\t\t\t\t\t\t\tsubSubStatement.expression.arguments.length === 2 &&\n\t\t\t\t\t\t\t\t\t\t\ttypescript.isIdentifier(subSubStatement.expression.expression) &&\n\t\t\t\t\t\t\t\t\t\t\tsubSubStatement.expression.expression.text === \"define\"\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\tconst [firstSubSubStatementExpressionArgument] = subSubStatement.expression.arguments;\n\t\t\t\t\t\t\t\t\t\t\tif (typescript.isArrayLiteralExpression(firstSubSubStatementExpressionArgument)) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn firstSubSubStatementExpressionArgument;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase typescript.ModuleKind.AMD: {\n\t\t\tfor (const statement of sourceFile.statements) {\n\t\t\t\tif (\n\t\t\t\t\ttypescript.isExpressionStatement(statement) &&\n\t\t\t\t\ttypescript.isCallExpression(statement.expression) &&\n\t\t\t\t\ttypescript.isIdentifier(statement.expression.expression) &&\n\t\t\t\t\tstatement.expression.expression.text === \"define\" &&\n\t\t\t\t\tstatement.expression.arguments.length === 2\n\t\t\t\t) {\n\t\t\t\t\tconst [firstArgument, secondArgument] = statement.expression.arguments;\n\t\t\t\t\tif (typescript.isArrayLiteralExpression(firstArgument)) {\n\t\t\t\t\t\tif (typescript.isFunctionExpression(secondArgument) && secondArgument.parameters.length >= 2) {\n\t\t\t\t\t\t\tconst [firstParameter, secondParameter] = secondArgument.parameters;\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\ttypescript.isIdentifier(firstParameter.name) &&\n\t\t\t\t\t\t\t\ttypescript.isIdentifier(secondParameter.name) &&\n\t\t\t\t\t\t\t\tfirstParameter.name.text === \"require\" &&\n\t\t\t\t\t\t\t\tsecondParameter.name.text === \"exports\"\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn firstArgument;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nexport function getRootBlock(sourceFile: TS.SourceFile, context: VisitorContext): RootBlock {\n\tconst {compilerOptions, typescript} = context;\n\n\tswitch (compilerOptions.module) {\n\t\t// If we're targeting UMD, the root block won't be the root scope, but the Function Body of an iife\n\t\tcase typescript.ModuleKind.UMD: {\n\t\t\tfor (const statement of sourceFile.statements) {\n\t\t\t\tif (typescript.isExpressionStatement(statement) && typescript.isCallExpression(statement.expression) && statement.expression.arguments.length === 1) {\n\t\t\t\t\tconst [firstArgument] = statement.expression.arguments;\n\t\t\t\t\tif (typescript.isFunctionExpression(firstArgument) && firstArgument.parameters.length === 2) {\n\t\t\t\t\t\tconst [firstParameter, secondParameter] = firstArgument.parameters;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypescript.isIdentifier(firstParameter.name) &&\n\t\t\t\t\t\t\ttypescript.isIdentifier(secondParameter.name) &&\n\t\t\t\t\t\t\tfirstParameter.name.text === \"require\" &&\n\t\t\t\t\t\t\tsecondParameter.name.text === \"exports\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn firstArgument.body;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\t// If we're targeting AMD, the root block won't be the root scope, but the Function Body of the\n\t\t// anonymous function provided as a second argument to the define() function\n\t\tcase typescript.ModuleKind.AMD: {\n\t\t\tfor (const statement of sourceFile.statements) {\n\t\t\t\tif (\n\t\t\t\t\ttypescript.isExpressionStatement(statement) &&\n\t\t\t\t\ttypescript.isCallExpression(statement.expression) &&\n\t\t\t\t\ttypescript.isIdentifier(statement.expression.expression) &&\n\t\t\t\t\tstatement.expression.expression.text === \"define\" &&\n\t\t\t\t\tstatement.expression.arguments.length === 2\n\t\t\t\t) {\n\t\t\t\t\tconst [, secondArgument] = statement.expression.arguments;\n\t\t\t\t\tif (typescript.isFunctionExpression(secondArgument) && secondArgument.parameters.length >= 2) {\n\t\t\t\t\t\tconst [firstParameter, secondParameter] = secondArgument.parameters;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypescript.isIdentifier(firstParameter.name) &&\n\t\t\t\t\t\t\ttypescript.isIdentifier(secondParameter.name) &&\n\t\t\t\t\t\t\tfirstParameter.name.text === \"require\" &&\n\t\t\t\t\t\t\tsecondParameter.name.text === \"exports\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn secondArgument.body;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn sourceFile;\n}\n\nexport function isImportedSymbolImported(importedSymbol: ImportedSymbol, rootBlock: RootBlock, context: VisitorContext): boolean {\n\tconst {compilerOptions, typescript} = context;\n\n\tswitch (compilerOptions.module) {\n\t\tcase typescript.ModuleKind.ES2022:\n\t\tcase typescript.ModuleKind.ES2020:\n\t\tcase typescript.ModuleKind.ES2015:\n\t\tcase typescript.ModuleKind.ESNext:\n\t\tcase typescript.ModuleKind.NodeNext: {\n\t\t\tfor (const statement of rootBlock.statements) {\n\t\t\t\tif (!typescript.isImportDeclaration(statement)) continue;\n\t\t\t\tif (!typescript.isStringLiteralLike(statement.moduleSpecifier)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (statement.moduleSpecifier.text !== importedSymbol.moduleSpecifier) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (statement.importClause == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (\"isDefaultImport\" in importedSymbol) {\n\t\t\t\t\tif (importedSymbol.isDefaultImport) {\n\t\t\t\t\t\tif (statement.importClause.name == null) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (statement.importClause.name.text !== importedSymbol.name) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (statement.importClause.namedBindings == null) continue;\n\t\t\t\t\t\tif (!typescript.isNamedImports(statement.importClause.namedBindings)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (const importSpecifier of statement.importClause.namedBindings.elements) {\n\t\t\t\t\t\t\tif (importSpecifier.name.text !== importedSymbol.name) continue;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (\"isNamespaceImport\" in importedSymbol) {\n\t\t\t\t\tif (statement.importClause.namedBindings == null) continue;\n\t\t\t\t\tif (!typescript.isNamespaceImport(statement.importClause.namedBindings)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (statement.importClause.namedBindings.name.text !== importedSymbol.name) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tcase typescript.ModuleKind.CommonJS:\n\t\tcase typescript.ModuleKind.AMD:\n\t\tcase typescript.ModuleKind.UMD: {\n\t\t\tfor (const statement of rootBlock.statements) {\n\t\t\t\tif (!typescript.isVariableStatement(statement)) continue;\n\t\t\t\tfor (const declaration of statement.declarationList.declarations) {\n\t\t\t\t\tif (!typescript.isIdentifier(declaration.name)) continue;\n\t\t\t\t\tif (declaration.name.text !== importedSymbol.name) continue;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO: Add support for other module systems\n\treturn false;\n}\n\nexport function generateImportStatementForImportedSymbolInContext(importedSymbol: ImportedSymbol, context: VisitorContext): TS.Statement | undefined {\n\tconst {compilerOptions, typescript, factory} = context;\n\n\tswitch (compilerOptions.module) {\n\t\tcase typescript.ModuleKind.ES2022:\n\t\tcase typescript.ModuleKind.ES2020:\n\t\tcase typescript.ModuleKind.ES2015:\n\t\tcase typescript.ModuleKind.ESNext:\n\t\tcase typescript.ModuleKind.NodeNext: {\n\t\t\treturn factory.createImportDeclaration(\n\t\t\t\tundefined,\n\t\t\t\t\"isDefaultImport\" in importedSymbol\n\t\t\t\t\t? factory.createImportClause(\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t!importedSymbol.isDefaultImport ? undefined : factory.createIdentifier(importedSymbol.name),\n\t\t\t\t\t\t\timportedSymbol.isDefaultImport\n\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t: factory.createNamedImports([\n\t\t\t\t\t\t\t\t\t\tfactory.createImportSpecifier(\n\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\timportedSymbol.propertyName === importedSymbol.name ? undefined : factory.createIdentifier(importedSymbol.propertyName),\n\t\t\t\t\t\t\t\t\t\t\tfactory.createIdentifier(importedSymbol.name)\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t ])\n\t\t\t\t\t )\n\t\t\t\t\t: \"isNamespaceImport\" in importedSymbol\n\t\t\t\t\t? factory.createImportClause(false, undefined, factory.createNamespaceImport(factory.createIdentifier(importedSymbol.name)))\n\t\t\t\t\t: undefined,\n\t\t\t\tfactory.createStringLiteral(importedSymbol.moduleSpecifier)\n\t\t\t);\n\t\t}\n\n\t\tcase typescript.ModuleKind.CommonJS:\n\t\tcase typescript.ModuleKind.AMD:\n\t\tcase typescript.ModuleKind.UMD: {\n\t\t\tconst requireCall = factory.createCallExpression(factory.createIdentifier(\"require\"), undefined, [factory.createStringLiteral(importedSymbol.moduleSpecifier)]);\n\n\t\t\tlet wrappedRequireCall = requireCall;\n\n\t\t\t// We'll need to use a helper, '__importDefault', and wrap the require call with it\n\t\t\tif (\n\t\t\t\tcompilerOptions.esModuleInterop === true &&\n\t\t\t\t((\"isDefaultImport\" in importedSymbol && importedSymbol.isDefaultImport) || (!(\"isDefaultImport\" in importedSymbol) && importedSymbol.isNamespaceImport))\n\t\t\t) {\n\t\t\t\t// If tslib is being used, we can do something like 'require(\"tslib\").__import{Default|Star}(<requireCall>)'\n\t\t\t\tif (compilerOptions.importHelpers === true) {\n\t\t\t\t\twrappedRequireCall = factory.createCallExpression(\n\t\t\t\t\t\tfactory.createPropertyAccessExpression(\n\t\t\t\t\t\t\tfactory.createCallExpression(factory.createIdentifier(\"require\"), undefined, [factory.createStringLiteral(\"tslib\")]),\n\t\t\t\t\t\t\tgetUnscopedHelperName(context, \"isDefaultImport\" in importedSymbol ? \"__importDefault\" : \"__importStar\")\n\t\t\t\t\t\t),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t[requireCall]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Otherwise, we'll have to make sure that the helper is being inlined in an transformation step later\n\t\t\t\telse {\n\t\t\t\t\t// We've already requested the __importDefault helper in the before transformer under these\n\t\t\t\t\t// circumstances\n\t\t\t\t\twrappedRequireCall = factory.createCallExpression(getUnscopedHelperName(context, \"isDefaultImport\" in importedSymbol ? \"__importDefault\" : \"__importStar\"), undefined, [\n\t\t\t\t\t\trequireCall\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn factory.createVariableStatement(\n\t\t\t\tundefined,\n\t\t\t\tfactory.createVariableDeclarationList(\n\t\t\t\t\t[factory.createVariableDeclaration(factory.createIdentifier(importedSymbol.name), undefined, undefined, wrappedRequireCall)],\n\t\t\t\t\ttypescript.NodeFlags.Const\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\t}\n\n\t// TODO: Handle other module types as well\n\treturn undefined;\n}\n","import type {Nullable} from \"helpertypes\";\nimport crypto from \"crypto\";\n\n/**\n * Ensures that the given item is an array\n */\nexport function ensureArray<T>(item: T[] | T): T[] {\n\treturn Array.isArray(item) ? item : [item];\n}\n\n/**\n * Converts the given string to a boolean\n */\nexport function booleanize(str: string | boolean | undefined): boolean {\n\tif (str == null) return false;\n\tif (typeof str === \"boolean\") return str;\n\n\tif (isTrueLike(str)) {\n\t\treturn true;\n\t} else if (isFalseLike(str)) {\n\t\treturn false;\n\t} else {\n\t\treturn Boolean(str);\n\t}\n}\n\nexport function isTrueLike(str: Nullable<string | boolean>): boolean {\n\tif (typeof str === \"boolean\") return str === true;\n\tif (str == null) return false;\n\n\tswitch (str.toLowerCase().trim()) {\n\t\tcase \"true\":\n\t\tcase \"yes\":\n\t\tcase \"1\":\n\t\tcase \"\":\n\t\t\treturn true;\n\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isFalseLike(str: Nullable<string | boolean>): boolean {\n\tif (typeof str === \"boolean\") return str === false;\n\tif (str == null) return true;\n\n\tswitch (str.toLowerCase().trim()) {\n\t\tcase \"false\":\n\t\tcase \"no\":\n\t\tcase \"0\":\n\t\t\treturn true;\n\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport const sha1 = (data: string) => crypto.createHash(\"sha1\").update(data).digest(\"hex\");\nexport const NOOP = () => {\n\t// Noop\n};\n","import {DI_CONTAINER_NAME} from \"../../constant.js\";\nimport type {TS} from \"../../../type/type.js\";\nimport type {BeforeVisitorOptions} from \"../before-visitor-options.js\";\nimport type {DiMethodName} from \"../../di-method-kind.js\";\nimport type {VisitorContext} from \"../../visitor-context.js\";\nimport {getImportDefaultHelper, getImportStarHelper, moduleKindDefinesDependencies, moduleKindSupportsImportHelpers} from \"../../../util/ts-util.js\";\nimport {pickServiceOrImplementationName} from \"../util.js\";\nimport {ensureArray} from \"../../../util/util.js\";\n\nexport function visitCallExpression(options: BeforeVisitorOptions<TS.CallExpression>): TS.VisitResult<TS.Node> {\n\tconst {node, childContinuation, continuation, context, addTslibDefinition, requireImportedSymbol} = options;\n\tconst {typescript, factory, compilerOptions, transformationContext, needsImportPreservationLogic} = context;\n\n\tconst diMethod = getDiMethodName(node.expression, context);\n\n\tif (diMethod != null) {\n\t\tswitch (diMethod) {\n\t\t\tcase \"get\":\n\t\t\tcase \"has\": {\n\t\t\t\t// If no type arguments are given, don't modify the node at all\n\t\t\t\tif (node.typeArguments == null || node.typeArguments[0] == null) {\n\t\t\t\t\treturn childContinuation(node);\n\t\t\t\t}\n\n\t\t\t\tconst [firstTypeArgument] = node.typeArguments;\n\n\t\t\t\treturn factory.updateCallExpression(node, node.expression, node.typeArguments, [\n\t\t\t\t\tfactory.createObjectLiteralExpression([\n\t\t\t\t\t\tfactory.createPropertyAssignment(\"identifier\", factory.createStringLiteral((firstTypeArgument.getFirstToken()?.getText() ?? firstTypeArgument.getText()).trim()))\n\t\t\t\t\t])\n\t\t\t\t]);\n\t\t\t}\n\n\t\t\tcase \"registerSingleton\":\n\t\t\tcase \"registerTransient\": {\n\t\t\t\tconst [typeArg, secondTypeArg] = (node.typeArguments ?? []) as unknown as [TS.TypeNode | undefined, TS.TypeNode | TS.Expression | undefined];\n\t\t\t\tconst [firstArgument] = node.arguments ?? [];\n\n\t\t\t\t// The user may explicitly pass 'undefined' as a value here, which shouldn't count as a custom implementation\n\t\t\t\tconst customImplementation = firstArgument == null || (typescript.isIdentifier(firstArgument) && firstArgument.text === \"undefined\") ? undefined : firstArgument;\n\n\t\t\t\tconst implementationArg =\n\t\t\t\t\t// If another implementation is passed, used that one instead\n\t\t\t\t\tcustomImplementation ??\n\t\t\t\t\t// If not implementation is provided, use the type argument *as* the implementation\n\t\t\t\t\tsecondTypeArg ??\n\t\t\t\t\ttypeArg;\n\n\t\t\t\tif (typeArg == null || implementationArg == null) {\n\t\t\t\t\treturn childContinuation(node);\n\t\t\t\t}\n\n\t\t\t\tconst typeArgText = pickServiceOrImplementationName(typeArg, context);\n\t\t\t\tconst implementationArgText = pickServiceOrImplementationName(implementationArg, context);\n\n\t\t\t\t// If the Implementation is a TypeNode, and if it originates from an ImportDeclaration, it may be stripped from the file since Typescript won't Type-check the updates from\n\t\t\t\t// a CustomTransformer and such a node would normally be removed from the imports.\n\t\t\t\t// to fix it, add an ImportDeclaration if needed. This is only needed if `preserveValueImports` is falsy\n\t\t\t\tif (needsImportPreservationLogic && customImplementation == null) {\n\t\t\t\t\tconst matchingImport = findMatchingImportDeclarationForIdentifier(implementationArgText, options);\n\t\t\t\t\tif (matchingImport != null && typescript.isStringLiteralLike(matchingImport.importDeclaration.moduleSpecifier)) {\n\t\t\t\t\t\tswitch (matchingImport.kind) {\n\t\t\t\t\t\t\tcase \"default\": {\n\t\t\t\t\t\t\t\t// Log a request for the __importDefault helper already if we will\n\t\t\t\t\t\t\t\t// need it in a later transformation step\n\t\t\t\t\t\t\t\tif (moduleKindSupportsImportHelpers(compilerOptions.module, typescript) && compilerOptions.esModuleInterop === true && compilerOptions.importHelpers !== true) {\n\t\t\t\t\t\t\t\t\ttransformationContext.requestEmitHelper(getImportDefaultHelper(typescript));\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Log a request for adding 'tslib' to the define([...]) array for the current\n\t\t\t\t\t\t\t\t// module system if it relies on declaring dependencies (such as UMD, AMD, and SystemJS does)\n\t\t\t\t\t\t\t\tif (moduleKindDefinesDependencies(compilerOptions.module, typescript) && compilerOptions.esModuleInterop === true && compilerOptions.importHelpers === true) {\n\t\t\t\t\t\t\t\t\taddTslibDefinition();\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\trequireImportedSymbol({\n\t\t\t\t\t\t\t\t\tisDefaultImport: true,\n\t\t\t\t\t\t\t\t\tmoduleSpecifier: matchingImport.importDeclaration.moduleSpecifier.text,\n\t\t\t\t\t\t\t\t\tname: matchingImport.identifier.text,\n\t\t\t\t\t\t\t\t\tpropertyName: matchingImport.identifier.text\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase \"namedImport\": {\n\t\t\t\t\t\t\t\trequireImportedSymbol({\n\t\t\t\t\t\t\t\t\tisDefaultImport: false,\n\t\t\t\t\t\t\t\t\tmoduleSpecifier: matchingImport.importDeclaration.moduleSpecifier.text,\n\t\t\t\t\t\t\t\t\tname: matchingImport.importSpecifier.name.text,\n\t\t\t\t\t\t\t\t\tpropertyName: matchingImport.importSpecifier.propertyName?.text ?? matchingImport.importSpecifier.name.text\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase \"namespace\": {\n\t\t\t\t\t\t\t\t// Log a request for the __importStar helper already if you will\n\t\t\t\t\t\t\t\t// need it in a later transformation step\n\t\t\t\t\t\t\t\tif (moduleKindSupportsImportHelpers(compilerOptions.module, typescript) && compilerOptions.esModuleInterop === true && compilerOptions.importHelpers !== true) {\n\t\t\t\t\t\t\t\t\ttransformationContext.requestEmitHelper(getImportStarHelper(typescript));\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\trequireImportedSymbol({\n\t\t\t\t\t\t\t\t\tisNamespaceImport: true,\n\t\t\t\t\t\t\t\t\tmoduleSpecifier: matchingImport.importDeclaration.moduleSpecifier.text,\n\t\t\t\t\t\t\t\t\tname: matchingImport.identifier.text\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn factory.updateCallExpression(node, node.expression, node.typeArguments, [\n\t\t\t\t\tcustomImplementation == null ? factory.createIdentifier(\"undefined\") : (continuation(implementationArg) as TS.Expression),\n\t\t\t\t\tfactory.createObjectLiteralExpression([\n\t\t\t\t\t\tfactory.createPropertyAssignment(\"identifier\", factory.createNoSubstitutionTemplateLiteral(typeArgText)),\n\t\t\t\t\t\t...(customImplementation != null\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: [factory.createPropertyAssignment(\"implementation\", factory.createIdentifier(rewriteImplementationName(implementationArgText, options)))])\n\t\t\t\t\t])\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn childContinuation(node);\n}\n\ninterface FindMatchingImportDeclarationForIdentifierBaseResult {\n\tkind: \"default\" | \"namespace\" | \"namedImport\";\n\timportDeclaration: TS.ImportDeclaration;\n}\n\ninterface FindMatchingImportDeclarationForIdentifierNamedImportResult extends FindMatchingImportDeclarationForIdentifierBaseResult {\n\tkind: \"namedImport\";\n\timportSpecifier: TS.ImportSpecifier;\n}\n\ninterface FindMatchingImportDeclarationForIdentifierDefaultResult extends FindMatchingImportDeclarationForIdentifierBaseResult {\n\tkind: \"default\";\n\tidentifier: TS.Identifier;\n}\n\ninterface FindMatchingImportDeclarationForIdentifierNamespaceResult extends FindMatchingImportDeclarationForIdentifierBaseResult {\n\tkind: \"namespace\";\n\tidentifier: TS.Identifier;\n}\n\ntype FindMatchingImportDeclarationForIdentifierResult =\n\t| FindMatchingImportDeclarationForIdentifierNamedImportResult\n\t| FindMatchingImportDeclarationForIdentifierDefaultResult\n\t| FindMatchingImportDeclarationForIdentifierNamespaceResult;\n\nfunction findMatchingImportDeclarationForIdentifier(\n\tidentifier: string,\n\toptions: BeforeVisitorOptions<TS.CallExpression>\n): FindMatchingImportDeclarationForIdentifierResult | undefined {\n\tconst {\n\t\tsourceFile,\n\t\tcontext: {typescript}\n\t} = options;\n\n\t// Find the matching import\n\tconst importDeclarations = sourceFile.statements.filter(typescript.isImportDeclaration);\n\n\tfor (const importDeclaration of importDeclarations) {\n\t\tif (importDeclaration.importClause == null) continue;\n\n\t\t// Default import\n\t\tif (importDeclaration.importClause.name?.text === identifier) {\n\t\t\treturn {\n\t\t\t\timportDeclaration,\n\t\t\t\tkind: \"default\",\n\t\t\t\tidentifier: importDeclaration.importClause.name\n\t\t\t};\n\t\t} else if (importDeclaration.importClause.namedBindings != null) {\n\t\t\tif (typescript.isNamespaceImport(importDeclaration.importClause.namedBindings)) {\n\t\t\t\tif (importDeclaration.importClause.namedBindings.name.text === identifier) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\timportDeclaration,\n\t\t\t\t\t\tkind: \"namespace\",\n\t\t\t\t\t\tidentifier: importDeclaration.importClause.namedBindings.name\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (const importSpecifier of importDeclaration.importClause.namedBindings.elements) {\n\t\t\t\t\tif (importSpecifier.name.text === identifier) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\timportDeclaration,\n\t\t\t\t\t\t\tkind: \"namedImport\",\n\t\t\t\t\t\t\timportSpecifier: importSpecifier\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// No import was matched\n\treturn undefined;\n}\n\nfunction rewriteImplementationName(name: string, options: BeforeVisitorOptions<TS.CallExpression>): string {\n\tconst {\n\t\tcontext: {typescript, compilerOptions}\n\t} = options;\n\n\tswitch (compilerOptions.module) {\n\t\tcase typescript.ModuleKind.ES2022:\n\t\tcase typescript.ModuleKind.ES2020:\n\t\tcase typescript.ModuleKind.ES2015:\n\t\tcase typescript.ModuleKind.ESNext:\n\t\t\treturn name;\n\n\t\tcase typescript.ModuleKind.CommonJS:\n\t\tcase typescript.ModuleKind.AMD:\n\t\tcase typescript.ModuleKind.UMD: {\n\t\t\t// Find the matching import\n\t\t\tconst match = findMatchingImportDeclarationForIdentifier(name, options);\n\t\t\tif (match == null) {\n\t\t\t\treturn name;\n\t\t\t}\n\n\t\t\tswitch (match.kind) {\n\t\t\t\tcase \"default\":\n\t\t\t\t\treturn `${name}.default`;\n\t\t\t\tcase \"namespace\":\n\t\t\t\t\treturn name;\n\t\t\t\tcase \"namedImport\":\n\t\t\t\t\treturn `${name}.${(match.importSpecifier.propertyName ?? match.importSpecifier.name).text}`;\n\t\t\t}\n\n\t\t\t// Fall back to returning the original name\n\t\t\treturn name;\n\t\t}\n\n\t\tdefault:\n\t\t\t// TODO: Add support for SystemJS here\n\t\t\treturn name;\n\t}\n}\n\nfunction getDiMethodName(node: TS.Expression, context: VisitorContext): DiMethodName | undefined {\n\tif (!context.typescript.isPropertyAccessExpression(node) && !context.typescript.isElementAccessExpression(node)) {\n\t\treturn undefined;\n\t}\n\n\t// If it is an element access expression, evaluate the argument expression\n\tif (context.typescript.isElementAccessExpression(node)) {\n\t\t// Do nothing at this point if this isn't a DIContainer instance, as we can avoid invoking evaluate at this point\n\t\tif (!isDiContainerInstance(node, context)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst evaluationResult = context.evaluate(node.argumentExpression);\n\n\t\t// If no value could be computed, or if the value isn't of type string, do nothing\n\t\tif (!evaluationResult.success || typeof evaluationResult.value !== \"string\") {\n\t\t\treturn undefined;\n\t\t} else {\n\t\t\treturn isDiContainerMethodName(evaluationResult.value) ? evaluationResult.value : undefined;\n\t\t}\n\t} else {\n\t\t// If the name is any of the relevant ones, assert that it is invoked on an instance of DIContainer\n\t\treturn isDiContainerMethodName(node.name.text) && isDiContainerInstance(node, context) ? node.name.text : undefined;\n\t}\n}\n\nfunction isDiContainerMethodName(name: string): name is DiMethodName {\n\tswitch (name) {\n\t\tcase \"get\":\n\t\tcase \"has\":\n\t\tcase \"registerSingleton\":\n\t\tcase \"registerTransient\":\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nfunction isDiContainerInstance(node: TS.PropertyAccessExpression | TS.ElementAccessExpression, context: VisitorContext): boolean {\n\tif (\"typeChecker\" in context) {\n\t\t// Don't proceed unless the left-hand expression is the DIServiceContainer\n\t\tconst type = context.typeChecker.getTypeAtLocation(node.expression);\n\n\t\tif (type == null || type.symbol == null || type.symbol.escapedName !== DI_CONTAINER_NAME) {\n\t\t\treturn false;\n\t\t}\n\t} else {\n\t\t// If one or more variable names were passed in, check those directly\n\t\tif (context.identifier != null && context.identifier.length > 0) {\n\t\t\t// Pick the left-hand side of the expression here\n\t\t\tconst name = (node.expression.getFirstToken()?.getText() ?? node.expression.getText()).trim();\n\t\t\t// If not a single matcher matches the text, this does not represent an instance of DIContainer.\n\t\t\tif (!ensureArray(context.identifier).some(matcher => name === matcher)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\t// Otherwise, attempt to resolve the value of the expression and check if it is an instance of DIContainer\n\t\t\tconst evaluationResult = context.evaluate(node.expression);\n\n\t\t\tif (\n\t\t\t\t!evaluationResult.success ||\n\t\t\t\tevaluationResult.value == null ||\n\t\t\t\ttypeof evaluationResult.value !== \"object\" ||\n\t\t\t\tevaluationResult.value.constructor?.name !== DI_CONTAINER_NAME\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n","import type {BeforeVisitorOptions} from \"../before-visitor-options.js\";\nimport type {TS} from \"../../../type/type.js\";\nimport {visitClassLikeDeclaration} from \"./visit-class-like-declaration.js\";\nimport {visitCallExpression} from \"./visit-call-expression.js\";\n\nexport function visitNode<T extends TS.Node>(options: BeforeVisitorOptions<T>): TS.VisitResult<TS.Node> {\n\tif (options.context.typescript.isClassLike(options.node)) {\n\t\treturn visitClassLikeDeclaration({...options, node: options.node});\n\t} else if (options.context.typescript.isCallExpression(options.node)) {\n\t\treturn visitCallExpression({...options, node: options.node});\n\t}\n\n\treturn options.childContinuation(options.node);\n}\n","import type {BaseVisitorContext, VisitorContext} from \"../visitor-context.js\";\nimport type {TS} from \"../../type/type.js\";\nimport type {BeforeVisitorOptions} from \"./before-visitor-options.js\";\nimport {visitNode} from \"./visitor/visit-node.js\";\nimport type {ImportedSymbol} from \"../../type/imported-symbol.js\";\nimport {ensureNodeFactory} from \"compatfactory\";\n\nexport function beforeTransformer(context: BaseVisitorContext): TS.TransformerFactory<TS.SourceFile> {\n\treturn transformationContext => {\n\t\tconst factory = ensureNodeFactory(transformationContext.factory ?? context.typescript);\n\n\t\treturn sourceFile =>\n\t\t\ttransformSourceFile(sourceFile, {\n\t\t\t\t...context,\n\t\t\t\ttransformationContext,\n\t\t\t\tfactory\n\t\t\t});\n\t};\n}\n\nexport function transformSourceFile(sourceFile: TS.SourceFile, context: VisitorContext): TS.SourceFile {\n\tconst requiredImportedSymbolSet = new Set<ImportedSymbol>();\n\n\t/**\n\t * An optimization in which every imported symbol is converted into\n\t * a string that can be matched against directly to guard against\n\t * duplicates\n\t */\n\tconst requiredImportedSymbolSetFlags = new Set<string>();\n\n\tif (context.needsImportPreservationLogic) {\n\t\tcontext.sourceFileToAddTslibDefinition.set(sourceFile.fileName, false);\n\t\tcontext.sourceFileToRequiredImportedSymbolSet.set(sourceFile.fileName, requiredImportedSymbolSet);\n\t}\n\n\tconst computeImportedSymbolFlag = (symbol: ImportedSymbol): string =>\n\t\t[\"name\", \"propertyName\", \"moduleSpecifier\", \"isNamespaceImport\", \"isDefaultImport\"]\n\t\t\t.map(property => `${property}:${symbol[property as keyof ImportedSymbol] ?? false}`)\n\t\t\t.join(\"|\");\n\n\tconst visitorOptions: Omit<BeforeVisitorOptions<TS.Node>, \"node\" | \"sourceFile\"> = {\n\t\tcontext,\n\n\t\taddTslibDefinition: (): void => {\n\t\t\tif (!context.needsImportPreservationLogic) return;\n\t\t\tcontext.sourceFileToAddTslibDefinition.set(sourceFile.fileName, true);\n\t\t},\n\n\t\trequireImportedSymbol: (importedSymbol: ImportedSymbol): void => {\n\t\t\tif (!context.needsImportPreservationLogic) return;\n\n\t\t\t// Guard against duplicates and compute a string so we can do\n\t\t\t// constant time lookups to compare against existing symbols\n\t\t\tconst flag = computeImportedSymbolFlag(importedSymbol);\n\t\t\tif (requiredImportedSymbolSetFlags.has(flag)) return;\n\t\t\trequiredImportedSymbolSetFlags.add(flag);\n\n\t\t\trequiredImportedSymbolSet.add(importedSymbol);\n\t\t},\n\n\t\tcontinuation: node =>\n\t\t\tvisitNode({\n\t\t\t\t...visitorOptions,\n\t\t\t\tsourceFile,\n\t\t\t\tnode\n\t\t\t}),\n\t\tchildContinuation: node =>\n\t\t\tcontext.typescript.visitEachChild(\n\t\t\t\tnode,\n\t\t\t\tcbNode =>\n\t\t\t\t\tvisitNode({\n\t\t\t\t\t\t...visitorOptions,\n\t\t\t\t\t\tsourceFile,\n\t\t\t\t\t\tnode: cbNode\n\t\t\t\t\t}),\n\t\t\t\tcontext.transformationContext\n\t\t\t)\n\t};\n\n\treturn visitorOptions.continuation(sourceFile) as TS.SourceFile;\n}\n","import type {TS} from \"../../../type/type.js\";\nimport type {AfterVisitorOptions} from \"../after-visitor-options.js\";\nimport {generateImportStatementForImportedSymbolInContext, getRootBlockInsertionPosition, isImportedSymbolImported} from \"../../../util/ts-util.js\";\nimport type {RootBlock} from \"../../../type/root-block.js\";\n\nexport function visitRootBlock(options: AfterVisitorOptions<RootBlock>): TS.Statement[] {\n\tconst {node, sourceFile, context} = options;\n\tconst {typescript} = context;\n\n\tconst leadingExtraStatements: TS.Statement[] = [];\n\n\tfor (const importedSymbol of context.sourceFileToRequiredImportedSymbolSet.get(sourceFile.fileName) ?? new Set()) {\n\t\tif (isImportedSymbolImported(importedSymbol, node, context)) continue;\n\n\t\tconst missingImportStatement = generateImportStatementForImportedSymbolInContext(importedSymbol, context);\n\n\t\tif (missingImportStatement != null) {\n\t\t\tleadingExtraStatements.push(missingImportStatement);\n\t\t}\n\t}\n\n\tconst insertPosition = getRootBlockInsertionPosition(node, typescript);\n\n\treturn [...node.statements.slice(0, insertPosition), ...leadingExtraStatements, ...node.statements.slice(insertPosition)];\n}\n","import type {TS} from \"../../../type/type.js\";\nimport type {AfterVisitorOptions} from \"../after-visitor-options.js\";\nimport {visitRootBlock} from \"./visit-root-block.js\";\n\nexport function visitRootBlockSourceFile(options: AfterVisitorOptions<TS.SourceFile>): TS.VisitResult<TS.Node> {\n\tconst {node, context} = options;\n\tconst {factory} = context;\n\n\treturn factory.updateSourceFile(\n\t\tnode,\n\t\tvisitRootBlock(options),\n\t\tnode.isDeclarationFile,\n\t\tnode.referencedFiles,\n\t\tnode.typeReferenceDirectives,\n\t\tnode.hasNoDefaultLib,\n\t\tnode.libReferenceDirectives\n\t);\n}\n","import type {TS} from \"../../../type/type.js\";\nimport type {AfterVisitorOptions} from \"../after-visitor-options.js\";\nimport {visitRootBlock} from \"./visit-root-block.js\";\n\nexport function visitRootBlockBlock(options: AfterVisitorOptions<TS.Block>): TS.VisitResult<TS.Node> {\n\tconst {node, context} = options;\n\tconst {factory} = context;\n\n\treturn factory.updateBlock(node, visitRootBlock(options));\n}\n","import type {TS} from \"../../../type/type.js\";\nimport type {AfterVisitorOptions} from \"../after-visitor-options.js\";\n\nexport function visitDefineArrayLiteralExpression(options: AfterVisitorOptions<TS.ArrayLiteralExpression>): TS.ArrayLiteralExpression {\n\tconst {node, sourceFile, context} = options;\n\tconst {typescript, factory} = context;\n\n\tconst trailingExtraExpressions: TS.Expression[] = [];\n\n\tfor (const importedSymbol of context.sourceFileToRequiredImportedSymbolSet.get(sourceFile.fileName) ?? new Set()) {\n\t\t// Skip the node if it is already declared as a dependency\n\t\tif (node.elements.some(element => typescript.isStringLiteralLike(element) && element.text === importedSymbol.moduleSpecifier)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\ttrailingExtraExpressions.push(factory.createStringLiteral(importedSymbol.moduleSpecifier));\n\t}\n\n\tif (context.sourceFileToAddTslibDefinition.get(sourceFile.fileName) === true) {\n\t\ttrailingExtraExpressions.push(factory.createStringLiteral(\"tslib\"));\n\t}\n\n\tif (trailingExtraExpressions.length < 1) {\n\t\treturn node;\n\t}\n\n\treturn factory.updateArrayLiteralExpression(node, [...node.elements, ...trailingExtraExpressions]);\n}\n","import type {TS} from \"../../../type/type.js\";\nimport {visitRootBlockSourceFile} from \"./visit-root-block-source-file.js\";\nimport type {AfterVisitorOptions} from \"../after-visitor-options.js\";\nimport {visitRootBlockBlock} from \"./visit-root-block-block.js\";\nimport {visitDefineArrayLiteralExpression} from \"./visit-define-array-literal-expression.js\";\n\nexport function visitNode<T extends TS.Node>(options: AfterVisitorOptions<T>): TS.VisitResult<TS.Node> {\n\tconst {\n\t\tnode,\n\t\tchildContinuation,\n\t\tdefineArrayLiteralExpression,\n\t\trootBlock,\n\t\tcontext: {typescript}\n\t} = options;\n\tif (typescript.isSourceFile(node) && rootBlock === node) {\n\t\treturn visitRootBlockSourceFile({...options, node});\n\t} else if (typescript.isBlock(node) && rootBlock === node) {\n\t\treturn visitRootBlockBlock({...options, node});\n\t} else if (typescript.isArrayLiteralExpression(node) && defineArrayLiteralExpression === node) {\n\t\treturn visitDefineArrayLiteralExpression({\n\t\t\t...options,\n\t\t\tnode\n\t\t});\n\t}\n\n\treturn childContinuation(options.node);\n}\n","import type {BaseVisitorContext, VisitorContext} from \"../visitor-context.js\";\nimport type {TS} from \"../../type/type.js\";\nimport type {AfterVisitorOptions} from \"./after-visitor-options.js\";\nimport {visitNode} from \"./visitor/visit-node.js\";\nimport {getDefineArrayLiteralExpression, getRootBlock} from \"../../util/ts-util.js\";\nimport {ensureNodeFactory} from \"compatfactory\";\n\ntype SourceFileWithEmitNodes = TS.SourceFile & {\n\temitNode?: {\n\t\thelpers?: TS.EmitHelper[];\n\t};\n};\n\nexport function afterTransformer(context: BaseVisitorContext): TS.TransformerFactory<TS.SourceFile> {\n\treturn transformationContext => {\n\t\tconst factory = ensureNodeFactory(transformationContext.factory ?? context.typescript);\n\n\t\treturn sourceFile =>\n\t\t\ttransformSourceFile(sourceFile, {\n\t\t\t\t...context,\n\t\t\t\ttransformationContext,\n\t\t\t\tfactory\n\t\t\t});\n\t};\n}\n\nfunction transformSourceFile(sourceFile: SourceFileWithEmitNodes, context: VisitorContext): TS.SourceFile {\n\t// For TypeScript versions below 3.5, there may be instances\n\t// where EmitHelpers such as __importDefault or __importStar is duplicated.\n\t// For these TypeScript versions, well have to guard against this behavior\n\tif (sourceFile.emitNode != null && sourceFile.emitNode.helpers != null) {\n\t\tconst seenNames = new Set();\n\t\tconst filtered = sourceFile.emitNode.helpers.filter(helper => {\n\t\t\tif (seenNames.has(helper.name)) return false;\n\t\t\tseenNames.add(helper.name);\n\t\t\treturn true;\n\t\t});\n\n\t\t// Reassign the emitNodes if they changed\n\t\tif (filtered.length !== sourceFile.emitNode.helpers.length) {\n\t\t\tsourceFile.emitNode.helpers = filtered;\n\t\t}\n\t}\n\n\tconst visitorOptions: Omit<AfterVisitorOptions<TS.Node>, \"node\" | \"sourceFile\"> = {\n\t\tcontext,\n\t\tdefineArrayLiteralExpression: getDefineArrayLiteralExpression(sourceFile, context),\n\t\trootBlock: getRootBlock(sourceFile, context),\n\n\t\tcontinuation: node =>\n\t\t\tvisitNode({\n\t\t\t\t...visitorOptions,\n\t\t\t\tsourceFile,\n\t\t\t\tnode\n\t\t\t}),\n\t\tchildContinuation: node =>\n\t\t\tcontext.typescript.visitEachChild(\n\t\t\t\tnode,\n\t\t\t\tcbNode =>\n\t\t\t\t\tvisitNode({\n\t\t\t\t\t\t...visitorOptions,\n\t\t\t\t\t\tsourceFile,\n\t\t\t\t\t\tnode: cbNode\n\t\t\t\t\t}),\n\t\t\t\tcontext.transformationContext\n\t\t\t)\n\t};\n\n\treturn visitorOptions.continuation(sourceFile) as TS.SourceFile;\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport type {DiOptions} from \"./di-options.js\";\nimport type {BaseVisitorContext} from \"./visitor-context.js\";\nimport {evaluate} from \"ts-evaluator\";\nimport TSModule from \"typescript\";\nimport {DI_CONTAINER_NAME} from \"./constant.js\";\nimport {needsImportPreservationLogic} from \"../util/ts-util.js\";\n\n/**\n * Shim the @wessberg/di module\n */\nconst EVALUATE_MODULE_OVERRIDES = {\n\t\"@wessber