next
Version:
The React Framework
115 lines (114 loc) • 4.71 kB
JavaScript
// This module provides intellisense for all exports from `"use server"` directive.
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _constant = require("../constant");
const _utils = require("../utils");
// Check if the type is `Promise<T>`.
function isPromiseType(type, typeChecker) {
const typeReferenceType = type;
if (!typeReferenceType.target) return false;
// target should be Promise or Promise<...>
if (!/^Promise(<.+>)?$/.test(typeChecker.typeToString(typeReferenceType.target))) {
return false;
}
return true;
}
function isFunctionReturningPromise(node, typeChecker, ts) {
const type = typeChecker.getTypeAtLocation(node);
const signatures = typeChecker.getSignaturesOfType(type, ts.SignatureKind.Call);
let isPromise = true;
if (signatures.length) {
for (const signature of signatures){
const returnType = signature.getReturnType();
if (returnType.isUnion()) {
for (const t of returnType.types){
if (!isPromiseType(t, typeChecker)) {
isPromise = false;
break;
}
}
} else {
isPromise = isPromiseType(returnType, typeChecker);
}
}
} else {
isPromise = false;
}
return isPromise;
}
const serverBoundary = {
getSemanticDiagnosticsForExportDeclaration (source, node) {
const ts = (0, _utils.getTs)();
const typeChecker = (0, _utils.getTypeChecker)();
if (!typeChecker) return [];
const diagnostics = [];
const exportClause = node.exportClause;
if (!node.isTypeOnly && exportClause && ts.isNamedExports(exportClause)) {
for (const e of exportClause.elements){
if (e.isTypeOnly) {
continue;
}
if (!isFunctionReturningPromise(e, typeChecker, ts)) {
diagnostics.push({
file: source,
category: ts.DiagnosticCategory.Error,
code: _constant.NEXT_TS_ERRORS.INVALID_SERVER_ENTRY_RETURN,
messageText: `The "use server" file can only export async functions.`,
start: e.getStart(),
length: e.getWidth()
});
}
}
}
return diagnostics;
},
getSemanticDiagnosticsForExportVariableStatement (source, node) {
const ts = (0, _utils.getTs)();
const diagnostics = [];
if (ts.isVariableDeclarationList(node.declarationList)) {
for (const declaration of node.declarationList.declarations){
const initializer = declaration.initializer;
if (initializer && (ts.isArrowFunction(initializer) || ts.isFunctionDeclaration(initializer) || ts.isFunctionExpression(initializer) || ts.isCallExpression(initializer) || ts.isIdentifier(initializer))) {
diagnostics.push(...serverBoundary.getSemanticDiagnosticsForFunctionExport(source, initializer));
} else {
diagnostics.push({
file: source,
category: ts.DiagnosticCategory.Error,
code: _constant.NEXT_TS_ERRORS.INVALID_SERVER_ENTRY_RETURN,
messageText: `The "use server" file can only export async functions.`,
start: declaration.getStart(),
length: declaration.getWidth()
});
}
}
}
return diagnostics;
},
getSemanticDiagnosticsForFunctionExport (source, node) {
const ts = (0, _utils.getTs)();
const typeChecker = (0, _utils.getTypeChecker)();
if (!typeChecker) return [];
const diagnostics = [];
if (!isFunctionReturningPromise(node, typeChecker, ts)) {
diagnostics.push({
file: source,
category: ts.DiagnosticCategory.Error,
code: _constant.NEXT_TS_ERRORS.INVALID_SERVER_ENTRY_RETURN,
messageText: `The "use server" file can only export async functions. Add "async" to the function declaration or return a Promise.`,
start: node.getStart(),
length: node.getWidth()
});
}
return diagnostics;
}
};
const _default = serverBoundary;
//# sourceMappingURL=server-boundary.js.map