{"version":3,"sources":["../../../../../src/server/typescript/rules/server-boundary.ts"],"sourcesContent":["// This module provides intellisense for all exports from `\"use server\"` directive.\n\nimport { NEXT_TS_ERRORS } from '../constant'\nimport { getTs, getTypeChecker } from '../utils'\nimport type tsModule from 'typescript/lib/tsserverlibrary'\n\n// Check if the type is `Promise<T>`.\nfunction isPromiseType(type: tsModule.Type, typeChecker: tsModule.TypeChecker) {\n  const typeReferenceType = type as tsModule.TypeReference\n  if (!typeReferenceType.target) return false\n\n  // target should be Promise or Promise<...>\n  if (\n    !/^Promise(<.+>)?$/.test(typeChecker.typeToString(typeReferenceType.target))\n  ) {\n    return false\n  }\n\n  return true\n}\n\nfunction isFunctionReturningPromise(\n  node: tsModule.Node,\n  typeChecker: tsModule.TypeChecker,\n  ts: typeof tsModule\n) {\n  const type = typeChecker.getTypeAtLocation(node)\n  const signatures = typeChecker.getSignaturesOfType(\n    type,\n    ts.SignatureKind.Call\n  )\n\n  let isPromise = true\n  if (signatures.length) {\n    for (const signature of signatures) {\n      const returnType = signature.getReturnType()\n      if (returnType.isUnion()) {\n        for (const t of returnType.types) {\n          if (!isPromiseType(t, typeChecker)) {\n            isPromise = false\n            break\n          }\n        }\n      } else {\n        isPromise = isPromiseType(returnType, typeChecker)\n      }\n    }\n  } else {\n    isPromise = false\n  }\n\n  return isPromise\n}\n\nconst serverBoundary = {\n  getSemanticDiagnosticsForExportDeclaration(\n    source: tsModule.SourceFile,\n    node: tsModule.ExportDeclaration\n  ) {\n    const ts = getTs()\n    const typeChecker = getTypeChecker()\n    if (!typeChecker) return []\n\n    const diagnostics: tsModule.Diagnostic[] = []\n\n    const exportClause = node.exportClause\n    if (!node.isTypeOnly && exportClause && ts.isNamedExports(exportClause)) {\n      for (const e of exportClause.elements) {\n        if (e.isTypeOnly) {\n          continue\n        }\n        if (!isFunctionReturningPromise(e, typeChecker, ts)) {\n          diagnostics.push({\n            file: source,\n            category: ts.DiagnosticCategory.Error,\n            code: NEXT_TS_ERRORS.INVALID_SERVER_ENTRY_RETURN,\n            messageText: `The \"use server\" file can only export async functions.`,\n            start: e.getStart(),\n            length: e.getWidth(),\n          })\n        }\n      }\n    }\n\n    return diagnostics\n  },\n\n  getSemanticDiagnosticsForExportVariableStatement(\n    source: tsModule.SourceFile,\n    node: tsModule.VariableStatement\n  ) {\n    const ts = getTs()\n\n    const diagnostics: tsModule.Diagnostic[] = []\n\n    if (ts.isVariableDeclarationList(node.declarationList)) {\n      for (const declaration of node.declarationList.declarations) {\n        const initializer = declaration.initializer\n        if (\n          initializer &&\n          (ts.isArrowFunction(initializer) ||\n            ts.isFunctionDeclaration(initializer) ||\n            ts.isFunctionExpression(initializer) ||\n            ts.isCallExpression(initializer) ||\n            ts.isIdentifier(initializer))\n        ) {\n          diagnostics.push(\n            ...serverBoundary.getSemanticDiagnosticsForFunctionExport(\n              source,\n              initializer\n            )\n          )\n        } else {\n          diagnostics.push({\n            file: source,\n            category: ts.DiagnosticCategory.Error,\n            code: NEXT_TS_ERRORS.INVALID_SERVER_ENTRY_RETURN,\n            messageText: `The \"use server\" file can only export async functions.`,\n            start: declaration.getStart(),\n            length: declaration.getWidth(),\n          })\n        }\n      }\n    }\n\n    return diagnostics\n  },\n\n  getSemanticDiagnosticsForFunctionExport(\n    source: tsModule.SourceFile,\n    node:\n      | tsModule.FunctionDeclaration\n      | tsModule.ArrowFunction\n      | tsModule.FunctionExpression\n      | tsModule.CallExpression\n      | tsModule.Identifier\n  ) {\n    const ts = getTs()\n    const typeChecker = getTypeChecker()\n    if (!typeChecker) return []\n\n    const diagnostics: tsModule.Diagnostic[] = []\n\n    if (!isFunctionReturningPromise(node, typeChecker, ts)) {\n      diagnostics.push({\n        file: source,\n        category: ts.DiagnosticCategory.Error,\n        code: NEXT_TS_ERRORS.INVALID_SERVER_ENTRY_RETURN,\n        messageText: `The \"use server\" file can only export async functions. Add \"async\" to the function declaration or return a Promise.`,\n        start: node.getStart(),\n        length: node.getWidth(),\n      })\n    }\n\n    return diagnostics\n  },\n}\n\nexport default serverBoundary\n"],"names":["NEXT_TS_ERRORS","getTs","getTypeChecker","isPromiseType","type","typeChecker","typeReferenceType","target","test","typeToString","isFunctionReturningPromise","node","ts","getTypeAtLocation","signatures","getSignaturesOfType","SignatureKind","Call","isPromise","length","signature","returnType","getReturnType","isUnion","t","types","serverBoundary","getSemanticDiagnosticsForExportDeclaration","source","diagnostics","exportClause","isTypeOnly","isNamedExports","e","elements","push","file","category","DiagnosticCategory","Error","code","INVALID_SERVER_ENTRY_RETURN","messageText","start","getStart","getWidth","getSemanticDiagnosticsForExportVariableStatement","isVariableDeclarationList","declarationList","declaration","declarations","initializer","isArrowFunction","isFunctionDeclaration","isFunctionExpression","isCallExpression","isIdentifier","getSemanticDiagnosticsForFunctionExport"],"mappings":"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","ignoreList":[0]}