createWebSocketHandler function

Expression createWebSocketHandler(
  1. MetaWebSocketMethod webSocket, {
  2. required ServerRoute route,
  3. required ServerReturnType returnType,
  4. required String classVarName,
})

Implementation

Expression createWebSocketHandler(
  MetaWebSocketMethod webSocket, {
  required ServerRoute route,
  required ServerReturnType returnType,
  required String classVarName,
}) {
  final trigger = <Code>[];

  final bodyAssignment = refer('context')
      .property('response')
      .property('body')
      .index(literalString('data'))
      .assign(refer('result'))
      .statement;

  final (:positioned, :named) = getParams(route.params);

  if (returnType.isStream) {
    final stream = refer(classVarName)
        .property(route.handlerName)
        .call(positioned, named)
        .property('asyncMap')
        .call([
      Method(
        (p) => p
          ..requiredParameters.add(Parameter((b) => b..name = 'result'))
          ..body = Block.of([bodyAssignment]),
      ).closure,
    ]).statement;

    trigger.addAll([
      const Code('yield*'),
      stream,
    ]);
  } else if (returnType.isVoid) {
    var invoke =
        refer(classVarName).property(route.handlerName).call(positioned, named);

    if (returnType.isFuture) {
      invoke = invoke.awaited;
    }

    trigger.add(invoke.statement);
  } else if (returnType.isFuture) {
    final futureResult = declareFinal('result')
        .assign(
          refer(classVarName)
              .property(route.handlerName)
              .call(positioned, named)
              .awaited,
        )
        .statement;

    trigger.addAll([
      futureResult,
      bodyAssignment,
      const Code('yield null;'),
    ]);
  } else {
    final result = declareFinal('result')
        .assign(
          refer(classVarName)
              .property(route.handlerName)
              .call(positioned, named),
        )
        .statement;

    trigger.addAll([
      result,
      bodyAssignment,
      const Code('yield null;'),
    ]);
  }
  final handler = Method(
    (p) => p
      ..modifier = MethodModifier.asyncStar
      ..body = Block.of(trigger),
  ).closure;

  return Method(
    (p) => p
      ..requiredParameters.add(Parameter((b) => b..name = 'context'))
      ..modifier = MethodModifier.async
      ..body = Block.of([
        refer((WebSocketHandler).name)
            .newInstance(
              [],
              {
                if (webSocket.triggerOnConnect || !webSocket.mode.canReceive)
                  'onConnect': handler,
                if (webSocket.mode.canReceive) 'onMessage': handler,
              },
            )
            .returned
            .statement,
      ]),
  ).closure;
}