{"version":3,"sources":["../src/factory.ts"],"names":["modifiers","questionToken","propertyName"],"mappings":"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","sourcesContent":["import { isNumber } from 'remeda'\nimport ts from 'typescript'\n\nconst { factory } = ts\n\n// https://ts-ast-viewer.com/\n\nexport const modifiers = {\n  async: factory.createModifier(ts.SyntaxKind.AsyncKeyword),\n  export: factory.createModifier(ts.SyntaxKind.ExportKeyword),\n  const: factory.createModifier(ts.SyntaxKind.ConstKeyword),\n  static: factory.createModifier(ts.SyntaxKind.StaticKeyword),\n} as const\n\nfunction isValidIdentifier(str: string): boolean {\n  if (!str.length || str.trim() !== str) {\n    return false\n  }\n  const node = ts.parseIsolatedEntityName(str, ts.ScriptTarget.Latest)\n\n  return !!node && node.kind === ts.SyntaxKind.Identifier && ts.identifierToKeywordKind(node.kind as unknown as ts.Identifier) === undefined\n}\n\nfunction propertyName(name: string | ts.PropertyName): ts.PropertyName {\n  if (typeof name === 'string') {\n    return isValidIdentifier(name) ? factory.createIdentifier(name) : factory.createStringLiteral(name)\n  }\n  return name\n}\n\nconst questionToken = factory.createToken(ts.SyntaxKind.QuestionToken)\n\nexport function createQuestionToken(token?: boolean | ts.QuestionToken) {\n  if (!token) {\n    return undefined\n  }\n  if (token === true) {\n    return questionToken\n  }\n  return token\n}\n\nexport function createIntersectionDeclaration({\n  nodes,\n  withParentheses,\n}: {\n  nodes: Array<ts.TypeNode>\n  withParentheses?: boolean\n}): ts.TypeNode | null {\n  if (!nodes.length) {\n    return null\n  }\n\n  if (nodes.length === 1) {\n    return nodes[0] || null\n  }\n\n  const node = factory.createIntersectionTypeNode(nodes)\n\n  if (withParentheses) {\n    return factory.createParenthesizedType(node)\n  }\n\n  return node\n}\n\n/**\n * Minimum nodes length of 2\n * @example `string & number`\n */\nexport function createTupleDeclaration({\n  nodes,\n  withParentheses,\n}: {\n  nodes: Array<ts.TypeNode>\n  withParentheses?: boolean\n}): ts.TypeNode | null {\n  if (!nodes.length) {\n    return null\n  }\n\n  if (nodes.length === 1) {\n    return nodes[0] || null\n  }\n\n  const node = factory.createTupleTypeNode(nodes)\n\n  if (withParentheses) {\n    return factory.createParenthesizedType(node)\n  }\n\n  return node\n}\n\nexport function createArrayDeclaration({\n  nodes,\n}: {\n  nodes: Array<ts.TypeNode>\n}): ts.TypeNode | null {\n  if (!nodes.length) {\n    return factory.createTupleTypeNode([])\n  }\n\n  if (nodes.length === 1) {\n    return factory.createArrayTypeNode(nodes.at(0)!)\n  }\n\n  return factory.createExpressionWithTypeArguments(factory.createIdentifier('Array'), [factory.createUnionTypeNode(nodes)])\n}\n\n/**\n * Minimum nodes length of 2\n * @example `string | number`\n */\nexport function createUnionDeclaration({\n  nodes,\n  withParentheses,\n}: {\n  nodes: Array<ts.TypeNode>\n  withParentheses?: boolean\n}): ts.TypeNode | null {\n  if (!nodes.length) {\n    return null\n  }\n\n  if (nodes.length === 1) {\n    return nodes[0] || null\n  }\n\n  const node = factory.createUnionTypeNode(nodes)\n\n  if (withParentheses) {\n    return factory.createParenthesizedType(node)\n  }\n\n  return node\n}\n\nexport function createPropertySignature({\n  readOnly,\n  modifiers = [],\n  name,\n  questionToken,\n  type,\n}: {\n  readOnly?: boolean\n  modifiers?: Array<ts.Modifier>\n  name: ts.PropertyName | string\n  questionToken?: ts.QuestionToken | boolean\n  type?: ts.TypeNode\n}) {\n  return factory.createPropertySignature(\n    [...modifiers, readOnly ? factory.createToken(ts.SyntaxKind.ReadonlyKeyword) : undefined].filter(Boolean),\n    propertyName(name),\n    createQuestionToken(questionToken),\n    type,\n  )\n}\n\nexport function createParameterSignature(\n  name: string | ts.BindingName,\n  {\n    modifiers,\n    dotDotDotToken,\n    questionToken,\n    type,\n    initializer,\n  }: {\n    decorators?: Array<ts.Decorator>\n    modifiers?: Array<ts.Modifier>\n    dotDotDotToken?: ts.DotDotDotToken\n    questionToken?: ts.QuestionToken | boolean\n    type?: ts.TypeNode\n    initializer?: ts.Expression\n  },\n): ts.ParameterDeclaration {\n  return factory.createParameterDeclaration(modifiers, dotDotDotToken, name, createQuestionToken(questionToken), type, initializer)\n}\n\nexport function createJSDoc({ comments }: { comments: string[] }) {\n  if (!comments.length) {\n    return null\n  }\n  return factory.createJSDocComment(\n    factory.createNodeArray(\n      comments.map((comment, i) => {\n        if (i === comments.length - 1) {\n          return factory.createJSDocText(comment)\n        }\n\n        return factory.createJSDocText(`${comment}\\n`)\n      }),\n    ),\n  )\n}\n\n/**\n * @link https://github.com/microsoft/TypeScript/issues/44151\n */\nexport function appendJSDocToNode<TNode extends ts.Node>({\n  node,\n  comments,\n}: {\n  node: TNode\n  comments: Array<string | undefined>\n}) {\n  const filteredComments = comments.filter(Boolean)\n\n  if (!filteredComments.length) {\n    return node\n  }\n\n  const text = filteredComments.reduce((acc = '', comment = '') => {\n    return `${acc}\\n * ${comment}`\n  }, '*')\n\n  // node: {...node}, with that ts.addSyntheticLeadingComment is appending\n  return ts.addSyntheticLeadingComment({ ...node }, ts.SyntaxKind.MultiLineCommentTrivia, `${text || '*'}\\n`, true)\n}\n\nexport function createIndexSignature(\n  type: ts.TypeNode,\n  {\n    modifiers,\n    indexName = 'key',\n    indexType = factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),\n  }: {\n    indexName?: string\n    indexType?: ts.TypeNode\n    decorators?: Array<ts.Decorator>\n    modifiers?: Array<ts.Modifier>\n  } = {},\n) {\n  return factory.createIndexSignature(modifiers, [createParameterSignature(indexName, { type: indexType })], type)\n}\n\nexport function createTypeAliasDeclaration({\n  modifiers,\n  name,\n  typeParameters,\n  type,\n}: {\n  modifiers?: Array<ts.Modifier>\n  name: string | ts.Identifier\n  typeParameters?: Array<ts.TypeParameterDeclaration>\n  type: ts.TypeNode\n}) {\n  return factory.createTypeAliasDeclaration(modifiers, name, typeParameters, type)\n}\n\nexport function createNamespaceDeclaration({\n  statements,\n  name,\n}: {\n  name: string\n  statements: ts.Statement[]\n}) {\n  return factory.createModuleDeclaration(\n    [factory.createToken(ts.SyntaxKind.ExportKeyword)],\n    factory.createIdentifier(name),\n    factory.createModuleBlock(statements),\n    ts.NodeFlags.Namespace,\n  )\n}\n\n/**\n * In { propertyName: string; name?: string } is `name` being used to make the type more unique when multiple same names are used.\n * @example `import { Pet as Cat } from './Pet'`\n */\nexport function createImportDeclaration({\n  name,\n  path,\n  isTypeOnly = false,\n  isNameSpace = false,\n}: {\n  name: string | Array<string | { propertyName: string; name?: string }>\n  path: string\n  isTypeOnly?: boolean\n  isNameSpace?: boolean\n}) {\n  if (!Array.isArray(name)) {\n    let importPropertyName: ts.Identifier | undefined = factory.createIdentifier(name)\n    let importName: ts.NamedImportBindings | undefined = undefined\n\n    if (isNameSpace) {\n      importPropertyName = undefined\n      importName = factory.createNamespaceImport(factory.createIdentifier(name))\n    }\n\n    return factory.createImportDeclaration(\n      undefined,\n      factory.createImportClause(isTypeOnly, importPropertyName, importName),\n      factory.createStringLiteral(path),\n      undefined,\n    )\n  }\n\n  return factory.createImportDeclaration(\n    undefined,\n    factory.createImportClause(\n      isTypeOnly,\n      undefined,\n      factory.createNamedImports(\n        name.map((item) => {\n          if (typeof item === 'object') {\n            const obj = item as { propertyName: string; name?: string }\n            if (obj.name) {\n              return factory.createImportSpecifier(false, factory.createIdentifier(obj.propertyName), factory.createIdentifier(obj.name))\n            }\n\n            return factory.createImportSpecifier(false, undefined, factory.createIdentifier(obj.propertyName))\n          }\n\n          return factory.createImportSpecifier(false, undefined, factory.createIdentifier(item))\n        }),\n      ),\n    ),\n    factory.createStringLiteral(path),\n    undefined,\n  )\n}\n\nexport function createExportDeclaration({\n  path,\n  asAlias,\n  isTypeOnly = false,\n  name,\n}: {\n  path: string\n  asAlias?: boolean\n  isTypeOnly?: boolean\n  name?: string | Array<ts.Identifier | string>\n}) {\n  if (name && !Array.isArray(name) && !asAlias) {\n    throw new Error('When using `name` as string, `asAlias` should be true')\n  }\n\n  if (!Array.isArray(name)) {\n    const parsedName = name?.match(/^\\d/) ? `_${name?.slice(1)}` : name\n\n    return factory.createExportDeclaration(\n      undefined,\n      isTypeOnly,\n      asAlias && parsedName ? factory.createNamespaceExport(factory.createIdentifier(parsedName)) : undefined,\n      factory.createStringLiteral(path),\n      undefined,\n    )\n  }\n\n  return factory.createExportDeclaration(\n    undefined,\n    isTypeOnly,\n    factory.createNamedExports(\n      name.map((propertyName) => {\n        return factory.createExportSpecifier(false, undefined, typeof propertyName === 'string' ? factory.createIdentifier(propertyName) : propertyName)\n      }),\n    ),\n    factory.createStringLiteral(path),\n    undefined,\n  )\n}\n\nexport function createEnumDeclaration({\n  type = 'enum',\n  name,\n  typeName,\n  enums,\n}: {\n  /**\n   * @default `'enum'`\n   */\n  type?: 'enum' | 'asConst' | 'asPascalConst' | 'constEnum' | 'literal'\n  /**\n   * Enum name in camelCase.\n   */\n  name: string\n  /**\n   * Enum name in PascalCase.\n   */\n  typeName: string\n  enums: [key: string | number, value: string | number | boolean][]\n}) {\n  if (type === 'literal') {\n    return [\n      factory.createTypeAliasDeclaration(\n        [factory.createToken(ts.SyntaxKind.ExportKeyword)],\n        factory.createIdentifier(typeName),\n        undefined,\n        factory.createUnionTypeNode(\n          enums\n            .map(([_key, value]) => {\n              if (isNumber(value)) {\n                return factory.createLiteralTypeNode(factory.createNumericLiteral(value?.toString()))\n              }\n\n              if (typeof value === 'boolean') {\n                return factory.createLiteralTypeNode(value ? factory.createTrue() : factory.createFalse())\n              }\n              if (value) {\n                return factory.createLiteralTypeNode(factory.createStringLiteral(value.toString()))\n              }\n\n              return undefined\n            })\n            .filter(Boolean),\n        ),\n      ),\n    ]\n  }\n\n  if (type === 'enum' || type === 'constEnum') {\n    return [\n      factory.createEnumDeclaration(\n        [factory.createToken(ts.SyntaxKind.ExportKeyword), type === 'constEnum' ? factory.createToken(ts.SyntaxKind.ConstKeyword) : undefined].filter(Boolean),\n        factory.createIdentifier(typeName),\n        enums\n          .map(([key, value]) => {\n            let initializer: ts.Expression = factory.createStringLiteral(value?.toString())\n\n            if (isNumber(Number.parseInt(value.toString()))) {\n              initializer = factory.createNumericLiteral(value as number)\n            }\n            if (typeof value === 'boolean') {\n              initializer = value ? factory.createTrue() : factory.createFalse()\n            }\n\n            if (isNumber(Number.parseInt(key.toString()))) {\n              return factory.createEnumMember(factory.createStringLiteral(`${typeName}_${key}`), initializer)\n            }\n\n            if (key) {\n              return factory.createEnumMember(factory.createStringLiteral(`${key}`), initializer)\n            }\n\n            return undefined\n          })\n          .filter(Boolean),\n      ),\n    ]\n  }\n\n  // used when using `as const` instead of an TypeScript enum.\n  const identifierName = type === 'asPascalConst' ? typeName : name\n\n  return [\n    factory.createVariableStatement(\n      [factory.createToken(ts.SyntaxKind.ExportKeyword)],\n      factory.createVariableDeclarationList(\n        [\n          factory.createVariableDeclaration(\n            factory.createIdentifier(identifierName),\n            undefined,\n            undefined,\n            factory.createAsExpression(\n              factory.createObjectLiteralExpression(\n                enums\n                  .map(([key, value]) => {\n                    let initializer: ts.Expression = factory.createStringLiteral(`${value?.toString()}`)\n\n                    if (isNumber(value)) {\n                      // Error: Negative numbers should be created in combination with createPrefixUnaryExpression factory.\n                      // The method createNumericLiteral only accepts positive numbers\n                      // or those combined with createPrefixUnaryExpression.\n                      // Therefore, we need to ensure that the number is not negative.\n                      if (value < 0) {\n                        initializer = factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(value)))\n                      } else {\n                        initializer = factory.createNumericLiteral(value)\n                      }\n                    }\n\n                    if (typeof value === 'boolean') {\n                      initializer = value ? factory.createTrue() : factory.createFalse()\n                    }\n\n                    if (key) {\n                      return factory.createPropertyAssignment(factory.createStringLiteral(`${key}`), initializer)\n                    }\n\n                    return undefined\n                  })\n                  .filter(Boolean),\n                true,\n              ),\n              factory.createTypeReferenceNode(factory.createIdentifier('const'), undefined),\n            ),\n          ),\n        ],\n        ts.NodeFlags.Const,\n      ),\n    ),\n    factory.createTypeAliasDeclaration(\n      [factory.createToken(ts.SyntaxKind.ExportKeyword)],\n      factory.createIdentifier(typeName),\n      undefined,\n      factory.createIndexedAccessTypeNode(\n        factory.createParenthesizedType(factory.createTypeQueryNode(factory.createIdentifier(identifierName), undefined)),\n        factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, factory.createTypeQueryNode(factory.createIdentifier(identifierName), undefined)),\n      ),\n    ),\n  ]\n}\n\nexport function createOmitDeclaration({\n  keys,\n  type,\n  nonNullable,\n}: {\n  keys: Array<string> | string\n  type: ts.TypeNode\n  nonNullable?: boolean\n}) {\n  const node = nonNullable ? factory.createTypeReferenceNode(factory.createIdentifier('NonNullable'), [type]) : type\n\n  if (Array.isArray(keys)) {\n    return factory.createTypeReferenceNode(factory.createIdentifier('Omit'), [\n      node,\n      factory.createUnionTypeNode(\n        keys.map((key) => {\n          return factory.createLiteralTypeNode(factory.createStringLiteral(key))\n        }),\n      ),\n    ])\n  }\n\n  return factory.createTypeReferenceNode(factory.createIdentifier('Omit'), [node, factory.createLiteralTypeNode(factory.createStringLiteral(keys))])\n}\n\nexport const keywordTypeNodes = {\n  any: factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword),\n  unknown: factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword),\n  number: factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),\n  integer: factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),\n  object: factory.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword),\n  string: factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),\n  boolean: factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword),\n  undefined: factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword),\n  null: factory.createLiteralTypeNode(factory.createToken(ts.SyntaxKind.NullKeyword)),\n} as const\n\nexport const createTypeLiteralNode = factory.createTypeLiteralNode\n\nexport const createTypeReferenceNode = factory.createTypeReferenceNode\nexport const createNumericLiteral = factory.createNumericLiteral\nexport const createStringLiteral = factory.createStringLiteral\n\nexport const createArrayTypeNode = factory.createArrayTypeNode\n\nexport const createLiteralTypeNode = factory.createLiteralTypeNode\nexport const createNull = factory.createNull\nexport const createIdentifier = factory.createIdentifier\n\nexport const createTupleTypeNode = factory.createTupleTypeNode\n"]}