ts-morph#SyntaxKind TypeScript Examples

The following examples show how to use ts-morph#SyntaxKind. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: languageServerFeatures.test.ts    From zod with MIT License 6 votes vote down vote up
getPropertyBeingAssigned = (node: Node, name: string) => {
  const propertyAssignment = node.forEachDescendant((descendent) =>
    Node.isPropertyAssignment(descendent) && descendent.getName() == name
      ? descendent
      : undefined
  );

  if (propertyAssignment == null)
    fail(`Could not find property assignment with name ${name}`);

  const propertyLiteral = propertyAssignment.getFirstDescendantByKind(
    SyntaxKind.Identifier
  );

  if (propertyLiteral == null)
    fail(`Could not find property literal with name ${name}`);

  return propertyLiteral;
}
Example #2
Source File: class.ts    From cli with MIT License 6 votes vote down vote up
// 获得类的方法声明,可根据方法名查找
export function getExistClassMethodsDeclaration(
  source: SourceFile,
  className: string,
  methodName?: string
) {
  const classDeclarations = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.ClassDeclaration);

  const targetClass = classDeclarations.filter(
    classDecs =>
      classDecs.getFirstChildByKind(SyntaxKind.Identifier).getText() ===
      className
  );

  if (!targetClass.length) {
    return;
  }

  const targetClassItem = targetClass[0];

  const methods = targetClassItem.getMethods();

  if (methodName) {
    return methods.filter(
      m => m.getFirstChildByKind(SyntaxKind.Identifier).getText() === methodName
    )[0];
  } else {
    return methods;
  }
}
Example #3
Source File: class.ts    From cli with MIT License 6 votes vote down vote up
// 获取类的属性声明,可根据属性名查找
export function getExistClassPropDeclarations(
  source: SourceFile,
  className: string,
  propName?: string
): PropertyDeclaration | PropertyDeclaration[] {
  const classDeclarations = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.ClassDeclaration);

  const targetClass = classDeclarations.filter(
    classDecs =>
      classDecs.getFirstChildByKind(SyntaxKind.Identifier).getText() ===
      className
  );

  if (!targetClass.length) {
    return;
  }

  const targetClassItem = targetClass[0];

  const props = targetClassItem.getProperties();

  if (propName) {
    return props.filter(
      m => m.getFirstChildByKind(SyntaxKind.Identifier).getText() === propName
    )[0];
  } else {
    return props;
  }
}
Example #4
Source File: class.ts    From cli with MIT License 6 votes vote down vote up
// 为类新增方法
export function addPlainClassMethods(
  source: SourceFile,
  className: string,
  methods: string[],
  apply = true
) {
  const existClassMethods: string[] = getExistClassMethods(source, className);
  const methodsCanBeAdded = methods.filter(
    method => !existClassMethods.includes(method)
  );
  if (!methodsCanBeAdded.length) {
    return;
  }
  const classDec = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getFirstChildByKind(SyntaxKind.ClassDeclaration);

  if (!classDec) {
    return;
  }

  methodsCanBeAdded.forEach(m => {
    classDec.addMethod({
      name: m,
      // hasQuestionToken: true,
      isAsync: false,
      parameters: [],
      returnType: 'void',
      statements: 'console.log("Method Added By Midway Code Mod")',
      typeParameters: [],
    });
  });

  apply && source.saveSync();
}
Example #5
Source File: class.ts    From cli with MIT License 6 votes vote down vote up
// 基于类名获取类的定义
export function getClassDecByName(source: SourceFile, className: string) {
  return source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.ClassDeclaration)
    .find(
      cls =>
        cls.getFirstChildByKind(SyntaxKind.Identifier).getText() === className
    );
}
Example #6
Source File: import.ts    From cli with MIT License 6 votes vote down vote up
// 获得导入声明的来源
export function findImportsSpecifier(source: SourceFile): string[] {
  const importDeclarations = findImportsDeclaration(source);

  const specifiers = importDeclarations
    .map(imp => imp.getFirstChildByKind(SyntaxKind.StringLiteral))
    // TODO: use RegExp
    .map(l => l.getText().replaceAll("'", ''));

  return specifiers;
}
Example #7
Source File: import.ts    From cli with MIT License 6 votes vote down vote up
// 获得所有导入声明
export function findImportsDeclaration(
  source: SourceFile,
  specifier?: string
): ImportDeclaration | ImportDeclaration[] {
  const importDeclarations = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.ImportDeclaration);

  if (specifier) {
    return importDeclarations.filter(imp => {
      const str = imp.getFirstChildByKind(SyntaxKind.StringLiteral);
      return str.getText() === `'${specifier}'`;
    })[0];
  }

  return importDeclarations;
}
Example #8
Source File: import.ts    From cli with MIT License 6 votes vote down vote up
export function appendStatementAfterImports(
  source: SourceFile,
  statement: string,
  apply = true
) {
  const imports = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.ImportDeclaration);

  let appendIdx: number;

  if (!imports.length) {
    appendIdx = 0;
  } else {
    appendIdx =
      source.getLastChildByKind(SyntaxKind.ImportDeclaration).getChildIndex() +
      1;
  }

  source.insertStatements(appendIdx, writer => {
    writer.newLine();
    writer.write(statement);
  });
  apply && source.saveSync();
}
Example #9
Source File: export.ts    From cli with MIT License 6 votes vote down vote up
// 获取所有的导出语句(可根据export的identifier查找)
export function getExportVariableStatements(
  source: SourceFile,
  varIdentifier?: string
): VariableStatement | VariableStatement[] {
  const topLevelVarStatements = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.VariableStatement);

  const exportVarStatements = topLevelVarStatements.filter(v => {
    const syntaxBeforeVarIdentifier = v.getFirstChildIfKind(
      SyntaxKind.SyntaxList
    );

    return (
      syntaxBeforeVarIdentifier &&
      syntaxBeforeVarIdentifier.getText() &&
      syntaxBeforeVarIdentifier.getText() === 'export'
    );
  });

  if (varIdentifier) {
    return exportVarStatements.find(statement => {
      return (
        statement
          .getFirstChildByKind(SyntaxKind.VariableDeclarationList)
          .getFirstChildByKind(SyntaxKind.SyntaxList)
          .getFirstChildByKind(SyntaxKind.VariableDeclaration)
          .getFirstChildByKind(SyntaxKind.Identifier)
          .getText() === varIdentifier
      );
    });
  }

  return exportVarStatements;
}
Example #10
Source File: export.ts    From cli with MIT License 6 votes vote down vote up
// 获取所有的导出语句的变量值
export function getExportVariableIdentifiers(source: SourceFile): string[] {
  const exportVarStatements = getExportVariableStatements(source);
  const exportVars = exportVarStatements.map(v =>
    v
      .getFirstChildByKind(SyntaxKind.VariableDeclarationList)
      .getFirstChildByKind(SyntaxKind.SyntaxList)
      .getFirstChildByKind(SyntaxKind.VariableDeclaration)
      // [ 'Identifier', 'EqualsToken', 'ObjectLiteralExpression' ]
      .getFirstChildByKind(SyntaxKind.Identifier)
      .getText()
  );

  return exportVars;
}
Example #11
Source File: export.ts    From cli with MIT License 6 votes vote down vote up
// 新增类型断言
export function addConstExportTypeAssertion(
  source: SourceFile,
  exportVar: string,
  typeRef = 'unknown',
  apply = true
) {
  const targetExport = getExportVariableStatements(source, exportVar);

  const varDec = targetExport
    .getFirstChildByKind(SyntaxKind.VariableDeclarationList)
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getFirstChildByKind(SyntaxKind.VariableDeclaration);

  console.log(varDec.getChildren().map(x => x.getKindName()));

  // {} as any -> AsExpression

  if (
    varDec
      .getChildren()
      .map(c => c.getKind())
      .includes(SyntaxKind.AsExpression)
  ) {
    consola.error(`Variable ${exportVar} has type assertion yet.`);
    process.exit(0);
  }

  // varDec.getLastChild().replaceWithText()

  // console.log(
  //   ts.factory.createAsExpression(
  //     ts.factory.createObjectLiteralExpression([]),
  //     ts.factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
  //   )
  //   // .getText()
  // );
  // const t1 = varDec.getFirstChildByKind(SyntaxKind.ObjectLiteralExpression)
}
Example #12
Source File: bundle-module-declare.ts    From mf-lite with MIT License 5 votes vote down vote up
bundleModuleDeclare = (fileOptions: FileOptions[]) => {
  const project = new Project();

  const content = [];

  fileOptions.forEach(file => {
    // 添加源代码
    const source = project.addSourceFileAtPath(file.path);

    // 遍历每一个子节点,如果是 SyntaxKind.DeclareKeyword(即 declare 关键词),进行文本替换
    source.forEachDescendant(item => {
      if (item.getKind() === SyntaxKind.DeclareKeyword) {
        // 删除即可, 需要判断是不是第一个节点,否则会报异常
        item.replaceWithText(item.isFirstNodeOnLine() ? 'export' : '');
      }
    });

    // 备份根节点
    const baseStatements = source.getStructure().statements;

    // 移除现存的所有节点
    source.getStatements().forEach(res => res.remove());

    // 创建一个 module declaration,将上面备份的根节点插入之
    source.addModule({
      name: `'${file.moduleName}'`,
      declarationKind: ModuleDeclarationKind.Module,
      hasDeclareKeyword: true,
      statements: baseStatements,
    });

    // 格式化代码
    source.formatText();

    // 补充一些注释
    content.push(`// module name: ${file.moduleName}\n\n`);
    content.push(source.getText());
    content.push('\n');
  });

  return content.join('');
}
Example #13
Source File: import.ts    From cli with MIT License 5 votes vote down vote up
// 新增具名导入成员
// 在importSpec不存在时,会新增一条具名导入
// 会过滤已存在的具名导入成员
export function addNamedImportsMember(
  source: SourceFile,
  importSpec: string,
  members: string[],
  apply = true
): void {
  const importDec = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.ImportDeclaration)
    .filter(importDec => {
      const importString = importDec
        .getFirstChildByKind(SyntaxKind.StringLiteral)
        .getText();
      return `'${importSpec}'` === importString;
    })[0];

  if (!importDec) {
    source.addImportDeclaration({
      moduleSpecifier: importSpec,
      namedImports: members,
    });
    apply && source.saveSync();

    return;
  }

  const importClause = importDec.getImportClause();
  const namedImports = importClause.getNamedImports().map(x => x.getText());

  const namedImportsCanBeAdded = members.filter(
    mem => !namedImports.includes(mem)
  );

  if (!namedImportsCanBeAdded.length) {
    return;
  }

  importDec.addNamedImports(namedImportsCanBeAdded);

  apply && source.saveSync();
}
Example #14
Source File: export.ts    From cli with MIT License 5 votes vote down vote up
// 新增类型定义 export const x:xxx = {}
export function addConstExportTypeRef(
  source: SourceFile,
  exportVar: string,
  typeRef = 'unknown',
  infer = true,
  apply = true
) {
  const targetExport = getExportVariableStatements(source, exportVar);

  const varDec = targetExport
    .getFirstChildByKind(SyntaxKind.VariableDeclarationList)
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getFirstChildByKind(SyntaxKind.VariableDeclaration);

  if (
    varDec.getChildren().length > 3 &&
    varDec
      .getChildren()
      .map(c => c.getKind())
      .includes(SyntaxKind.ColonToken)
  ) {
    consola.error(`Variable ${exportVar} has type reference yet.`);
    process.exit(0);
  }

  const varValueLiteral = varDec.getLastChild();

  const varValueKind = varValueLiteral.getKind();

  const typeRefToApply = infer
    ? varValueKind === SyntaxKind.StringLiteral
      ? 'string'
      : varValueKind === SyntaxKind.NumericLiteral
      ? 'number'
      : [SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword].includes(varValueKind)
      ? 'boolean'
      : varValueKind === SyntaxKind.ObjectLiteralExpression
      ? 'Record<string, unknown>'
      : varValueKind === SyntaxKind.ArrowFunction
      ? '(...args: unknown) => unknown'
      : 'unknown'
    : typeRef;

  varDec.setType(typeRefToApply).getText();

  apply && source.saveSync();
}
Example #15
Source File: export.ts    From cli with MIT License 5 votes vote down vote up
export function updateConstExportIdentifier(
  source: SourceFile,
  currentKey: string,
  updatedKey: string,
  apply = true
) {
  const exportVars = getExportVariableIdentifiers(source);

  if (!exportVars.includes(currentKey)) {
    consola.error(`export ${currentKey} doesnot exist!`);
    return;
  }

  const targetVar = getExportVariableStatements(source, currentKey);

  const targetVarDeclaration = targetVar
    .getFirstChildByKind(SyntaxKind.VariableDeclarationList)
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getFirstChildByKind(SyntaxKind.VariableDeclaration);

  const targetVarValueNode = targetVarDeclaration.getLastChild();

  const targetVarValueKind = targetVarValueNode.getKind();
  const targetVarTextValue = targetVarValueNode.getText();

  if (targetVarValueKind === SyntaxKind.NumericLiteral) {
    addConstExport(
      source,
      updatedKey,
      Number(targetVarTextValue),
      undefined,
      false
    );
    targetVar.remove();
  } else if (targetVarValueKind === SyntaxKind.StringLiteral) {
    addConstExport(
      source,
      updatedKey,
      String(targetVarTextValue).replaceAll("'", ''),
      undefined,
      false
    );
    targetVar.remove();
  } else if (
    [SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword].includes(
      targetVarValueKind
    )
  ) {
    addConstExport(
      source,
      updatedKey,
      targetVarTextValue !== 'false',
      undefined,
      false
    );
    targetVar.remove();
  } else if (targetVarValueKind === SyntaxKind.ArrowFunction) {
    addConstExport(source, updatedKey, targetVarTextValue, false, false);
    targetVar.remove();
  } else if (targetVarValueKind === SyntaxKind.ObjectLiteralExpression) {
    addConstExport(source, updatedKey, targetVarTextValue, false, false);
    targetVar.remove();
  }

  apply && source.saveSync();
}
Example #16
Source File: configuration.ts    From cli with MIT License 5 votes vote down vote up
// 确保容器配置类的方法具有标准参数
export function ensureLifeCycleMethodArguments(
  source: SourceFile,
  methods: LifeCycleMethod[],
  apply = true
) {
  ensureLifeCycleMethods(source, methods);

  const existMethodDeclarations = getExistClassMethodsDeclaration(
    source,
    LIFE_CYCLE_CLASS_IDENTIFIER
  );

  const methodsShouldBeFix: MethodDeclaration[] = [];

  existMethodDeclarations.forEach((m, idx) => {
    if (m.getFirstChildByKind(SyntaxKind.SyntaxList).getText() !== 'async') {
      return;
    }

    const argsSyntaxList = m.getChildrenOfKind(SyntaxKind.SyntaxList)[1];

    // 只处理参数为空的方法
    if (!argsSyntaxList.getText()) {
      methodsShouldBeFix.push(m);
      return;
    }

    // 存在参数
    const paramSyntaxList = argsSyntaxList.getChildrenOfKind(
      SyntaxKind.Parameter
    );

    // 参数数量不正确 需要手动补全 因为case太多了
    if (paramSyntaxList.length !== 2) {
      consola.error(
        `Incorrect arguments count in ${m.getName()}, expect: 2, found: ${
          paramSyntaxList.length
        }`
      );
      return;
    }
  });

  if (!methodsShouldBeFix.length) {
    return;
  }

  // 仅修正无参数的方法
  methodsShouldBeFix.forEach(m => {
    m.addParameters([
      {
        name: 'container',
        type: 'IMidwayContainer',
        hasQuestionToken: false,
        initializer: null,
        isReadonly: false,
        isRestParameter: false,
      },
      {
        name: 'app',
        type: 'IMidwayApplication',
        hasQuestionToken: true,
        initializer: null,
        isReadonly: false,
        isRestParameter: false,
      },
    ]);
  });

  apply && source.saveSync();
}
Example #17
Source File: config.ts    From cli with MIT License 5 votes vote down vote up
// config.x = {}
// 仅适用于默认导出方法形式
export function addConfigKey(
  source: SourceFile,
  key: string,
  value: any,
  apply = true
) {
  const arrowFunc = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getFirstChildByKind(SyntaxKind.ExportAssignment)
    .getFirstChildByKind(SyntaxKind.ArrowFunction);

  const returnStatement = arrowFunc
    .getFirstChildByKind(SyntaxKind.Block)
    .getFirstChildByKind(SyntaxKind.ReturnStatement);

  const stripedReturnStatement = strip(returnStatement.getText());

  const configVarIdentifier = arrowFunc
    .getBody()
    // const config = {} as DefaultConfig;
    .getFirstChildByKind(SyntaxKind.VariableStatement)
    .getFirstChildByKind(SyntaxKind.VariableDeclarationList)
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    //  [ 'Identifier', 'EqualsToken', 'AsExpression' ]
    .getFirstChildByKind(SyntaxKind.VariableDeclaration)
    .getFirstChildByKind(SyntaxKind.Identifier)
    .getText();

  const existPropAssignmentKeys = arrowFunc
    .getBody()
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.ExpressionStatement)
    .map(child => {
      const propsAssignTokens = child
        // a.b = x
        .getFirstChildByKind(SyntaxKind.BinaryExpression)
        // a.b
        .getFirstChildByKind(SyntaxKind.PropertyAccessExpression);
      return propsAssignTokens;
    })
    .map(prop => {
      // [ 'Identifier', 'DotToken', 'Identifier' ]
      const children = prop.getChildren();
      if (
        children.length === 3 &&
        children[1].getKind() === SyntaxKind.DotToken
      ) {
        return children[2].getText();
      }
    });

  if (existPropAssignmentKeys.includes(key)) {
    console.error(`${configVarIdentifier}.${key} exist !`);
    process.exit(0);
  }

  returnStatement.remove();

  // FIXME:
  arrowFunc.addStatements(
    `${configVarIdentifier}.${key} = ${JSON.stringify(value)}`
  );

  arrowFunc.addStatements(stripedReturnStatement);

  apply && source.saveSync();

  // const absWritePath = source.getFilePath();

  // const formatted = prettier.format(
  //   fs.readFileSync(absWritePath, { encoding: 'utf8' }),
  //   {
  //     parser: 'typescript',
  //   }
  // );

  // fs.writeFileSync(absWritePath, formatted);
}
Example #18
Source File: decorator.ts    From cli with MIT License 4 votes vote down vote up
// 更新数组类型的装饰器参数
// 暂时只支持@Deco({  })
export function updateDecoratorArrayArgs(
  source: SourceFile,
  decoratorName: string,
  argKey: string,
  identifier: string,
  apply = true
) {
  const decoratorSyntaxList = source
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getFirstChildByKind(SyntaxKind.ClassDeclaration)
    .getFirstChildByKind(SyntaxKind.SyntaxList);

  const correspondingDecorator = decoratorSyntaxList
    .getChildren()
    .filter(child => {
      if (child.getKind() !== SyntaxKind.Decorator) {
        return false;
      } else {
        return (
          child
            .getFirstChildByKind(SyntaxKind.CallExpression)
            .getFirstChildByKind(SyntaxKind.Identifier)
            .getText() === decoratorName
        );
      }
    })[0]
    .asKind(SyntaxKind.Decorator);

  const decoratorArg = correspondingDecorator
    .getArguments()[0]
    .asKind(SyntaxKind.ObjectLiteralExpression);

  const currentArgObjectKeys = decoratorArg
    .getFirstChildByKind(SyntaxKind.SyntaxList)
    .getChildrenOfKind(SyntaxKind.PropertyAssignment)
    .map(assign => assign.getFirstChildByKind(SyntaxKind.Identifier).getText());

  if (currentArgObjectKeys.includes(argKey)) {
    // 参数已存在 合并
    // imports: [orm]
    // add args by addChildText
    const propAssignments = decoratorArg
      .getFirstChildByKind(SyntaxKind.SyntaxList)
      .getChildrenOfKind(SyntaxKind.PropertyAssignment)
      .find(
        assign =>
          assign.getChildrenOfKind(SyntaxKind.Identifier)[0].getText() ===
          argKey
      );

    // orm
    const existPropAssignedValue = propAssignments
      .getFirstChildByKindOrThrow(SyntaxKind.ArrayLiteralExpression)
      .getFirstChildByKind(SyntaxKind.SyntaxList);

    existPropAssignedValue.getText()
      ? existPropAssignedValue.addChildText(`, ${identifier}`)
      : existPropAssignedValue.addChildText(identifier);

    // const existPropAssign = decoratorArg
    //   .getProperty(argKey)
    //   .getFirstChildByKind(SyntaxKind.ArrayLiteralExpression)
    //   .getFirstChildByKind(SyntaxKind.SyntaxList);

    // const existPropAssignValue = existPropAssign.getFirstChildByKind(
    //   SyntaxKind.Identifier
    // );

    // const val: string[] = [];

    // if (!existPropAssignValue) {
    //   val.push(identifier);
    // } else {
    //   val.push(String(existPropAssignValue.getText()), `, ${identifier}`);
    // }
  } else {
    // TODO: support insert at start or end
    decoratorArg.insertPropertyAssignment(0, {
      name: argKey,
      initializer: `[${identifier}]`,
    });
  }

  apply && source.saveSync();
}
Example #19
Source File: instructions.ts    From adonis5-jwt with MIT License 4 votes vote down vote up
/**
 * Makes the auth config file
 */
async function editConfig(
    projectRoot: string,
    app: ApplicationContract,
    sink: typeof sinkStatic,
    state: InstructionsState
) {
    const configDirectory = app.directoriesMap.get("config") || "config";
    const configPath = join(configDirectory, "auth.ts");

    let tokenProvider;
    if (state.tokensProvider === "redis") {
        tokenProvider = Writers.object({
            type: "'jwt'",
            driver: "'redis'",
            redisConnection: "'local'",
            foreignKey: "'user_id'",
        });
    } else {
        tokenProvider = Writers.object({
            type: "'api'",
            driver: "'database'",
            table: "'jwt_tokens'",
            foreignKey: "'user_id'",
        });
    }

    let provider;
    if (state.provider === "database") {
        provider = Writers.object({
            driver: "'database'",
            identifierKey: "'id'",
            uids: "['email']",
            usersTable: `'${state.usersTableName}'`,
        });
    } else if (state.provider === "lucid") {
        provider = Writers.object({
            driver: '"lucid"',
            identifierKey: '"id"',
            uids: "[]",
            model: `() => import('${state.usersModelNamespace}')`,
        });
    } else {
        throw new Error(`Invalid state.provider: ${state.provider}`);
    }

    //Instantiate ts-morph
    const project = await getTsMorphProject(projectRoot);
    const authConfigFile = project.getSourceFileOrThrow(configPath);

    //Remove Env import, if already present
    authConfigFile.getImportDeclaration("@ioc:Adonis/Core/Env")?.remove();

    //Add Env import
    authConfigFile.addImportDeclaration({
        defaultImport: "Env",
        moduleSpecifier: "@ioc:Adonis/Core/Env",
    });

    const variable = authConfigFile
        ?.getVariableDeclarationOrThrow("authConfig")
        .getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
    let guardsProperty = variable?.getPropertyOrThrow("guards") as PropertyAssignment;
    let guardsObject = guardsProperty.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);

    //Remove JWT config, if already present
    guardsObject.getProperty("jwt")?.remove();

    //Add JWT config
    guardsObject?.addPropertyAssignment({
        name: "jwt",
        initializer: Writers.object({
            driver: '"jwt"',
            publicKey: `Env.get('JWT_PUBLIC_KEY', '').replace(/\\\\n/g, '\\n')`,
            privateKey: `Env.get('JWT_PRIVATE_KEY', '').replace(/\\\\n/g, '\\n')`,
            persistJwt: `${state.persistJwt ? "true" : "false"}`,
            jwtDefaultExpire: `'${state.jwtDefaultExpire}'`,
            refreshTokenDefaultExpire: `'${state.refreshTokenDefaultExpire}'`,
            tokenProvider: tokenProvider,
            provider: provider,
        }),
    });

    authConfigFile.formatText();
    await authConfigFile?.save();

    sink.logger.action("update").succeeded(configPath);
}
Example #20
Source File: languageServerFeatures.test.ts    From zod with MIT License 4 votes vote down vote up
// The following tool is helpful for understanding the TypeScript AST associated with these tests:
// https://ts-ast-viewer.com/ (just copy the contents of languageServerFeatures.source into the viewer)

describe("Executing Go To Definition (and therefore Find Usages and Rename Refactoring) using an IDE works on inferred object properties", () => {
  // Compile file developmentEnvironment.source
  const project = new Project({
    tsConfigFilePath: path.join(__dirname, "..", "..", "tsconfig.json"),
    skipAddingFilesFromTsConfig: true,
  });
  const sourceFile = project.addSourceFileAtPath(filePath);

  test("works for object properties inferred from z.object()", () => {
    // Find usage of Test.f1 property
    const instanceVariable =
      sourceFile.getVariableDeclarationOrThrow("instanceOfTest");
    const propertyBeingAssigned = getPropertyBeingAssigned(
      instanceVariable,
      "f1"
    );

    // Find definition of Test.f1 property
    const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
    const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
      SyntaxKind.VariableDeclaration
    );

    // Assert that find definition returned the Zod definition of Test
    expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
    expect(parentOfProperty?.getName()).toEqual("Test");
  });

  test("works for first object properties inferred from z.object().merge()", () => {
    // Find usage of TestMerge.f1 property
    const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
      "instanceOfTestMerge"
    );
    const propertyBeingAssigned = getPropertyBeingAssigned(
      instanceVariable,
      "f1"
    );

    // Find definition of TestMerge.f1 property
    const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
    const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
      SyntaxKind.VariableDeclaration
    );

    // Assert that find definition returned the Zod definition of Test
    expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
    expect(parentOfProperty?.getName()).toEqual("Test");
  });

  test("works for second object properties inferred from z.object().merge()", () => {
    // Find usage of TestMerge.f2 property
    const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
      "instanceOfTestMerge"
    );
    const propertyBeingAssigned = getPropertyBeingAssigned(
      instanceVariable,
      "f2"
    );

    // Find definition of TestMerge.f2 property
    const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
    const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
      SyntaxKind.VariableDeclaration
    );

    // Assert that find definition returned the Zod definition of TestMerge
    expect(definitionOfProperty?.getText()).toEqual(
      "f2: z.string().optional()"
    );
    expect(parentOfProperty?.getName()).toEqual("TestMerge");
  });

  test("works for first object properties inferred from z.union()", () => {
    // Find usage of TestUnion.f1 property
    const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
      "instanceOfTestUnion"
    );
    const propertyBeingAssigned = getPropertyBeingAssigned(
      instanceVariable,
      "f1"
    );

    // Find definition of TestUnion.f1 property
    const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
    const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
      SyntaxKind.VariableDeclaration
    );

    // Assert that find definition returned the Zod definition of Test
    expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
    expect(parentOfProperty?.getName()).toEqual("Test");
  });

  test("works for second object properties inferred from z.union()", () => {
    // Find usage of TestUnion.f2 property
    const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
      "instanceOfTestUnion"
    );
    const propertyBeingAssigned = getPropertyBeingAssigned(
      instanceVariable,
      "f2"
    );

    // Find definition of TestUnion.f2 property
    const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
    const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
      SyntaxKind.VariableDeclaration
    );

    // Assert that find definition returned the Zod definition of TestUnion
    expect(definitionOfProperty?.getText()).toEqual(
      "f2: z.string().optional()"
    );
    expect(parentOfProperty?.getName()).toEqual("TestUnion");
  });

  test("works for object properties inferred from z.object().partial()", () => {
    // Find usage of TestPartial.f1 property
    const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
      "instanceOfTestPartial"
    );
    const propertyBeingAssigned = getPropertyBeingAssigned(
      instanceVariable,
      "f1"
    );

    // Find definition of TestPartial.f1 property
    const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
    const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
      SyntaxKind.VariableDeclaration
    );

    // Assert that find definition returned the Zod definition of Test
    expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
    expect(parentOfProperty?.getName()).toEqual("Test");
  });

  test("works for object properties inferred from z.object().pick()", () => {
    // Find usage of TestPick.f1 property
    const instanceVariable =
      sourceFile.getVariableDeclarationOrThrow("instanceOfTestPick");
    const propertyBeingAssigned = getPropertyBeingAssigned(
      instanceVariable,
      "f1"
    );

    // Find definition of TestPick.f1 property
    const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
    const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
      SyntaxKind.VariableDeclaration
    );

    // Assert that find definition returned the Zod definition of Test
    expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
    expect(parentOfProperty?.getName()).toEqual("Test");
  });

  test("works for object properties inferred from z.object().omit()", () => {
    // Find usage of TestOmit.f1 property
    const instanceVariable =
      sourceFile.getVariableDeclarationOrThrow("instanceOfTestOmit");
    const propertyBeingAssigned = getPropertyBeingAssigned(
      instanceVariable,
      "f1"
    );

    // Find definition of TestOmit.f1 property
    const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
    const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
      SyntaxKind.VariableDeclaration
    );

    // Assert that find definition returned the Zod definition of Test
    expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
    expect(parentOfProperty?.getName()).toEqual("Test");
  });
});