createWebsocketCall function

List<Code> createWebsocketCall(
  1. ClientMethod method
)

Implementation

List<Code> createWebsocketCall(ClientMethod method) {
  final (body: _, query: queries, headers: _, cookies: _) =
      method.parameters.separate;

  final body = method.websocketBody;
  final bodyType = switch (body?.type) {
    ClientType(isStream: true, typeArguments: [final type]) => type,
    null => null,
    _ => throw Exception('Invalid body type'),
  };

  StringBuffer? queryBuffer;
  for (final param in queries) {
    queryBuffer ??= StringBuffer('?');

    queryBuffer.write('${param.name}=\${${param.name}}');
  }
  final query = queryBuffer?.toString() ?? '';

  final path = method.resolvedPath + query;

  return [
    declareFinal('baseUrl')
        .assign(
          createSwitchPattern(
            refer('_storage').index(literal('__BASE_URL__')).awaited,
            {
              declareFinal('url', type: refer((String).name)): refer('url')
                  .property('replaceAll')
                  .call([
                    refer((RegExp).name).newInstance([literal('^https?')]),
                    literal('ws'),
                  ]),
              const Code('_'): refer(
                'Exception',
              ).newInstance([literal('Base URL not set')]).thrown,
            },
          ),
        )
        .statement,
    const Code(''),
    declareFinal('channel')
        .assign(
          refer('_websocket').call([
            refer((Uri).name).newInstanceNamed('parse', [
              refer(
                r"'$baseUrl"
                "$path'",
              ),
            ]),
          ]),
        )
        .statement,
    refer('channel').property('ready').awaited.statement,
    const Code(''),
    if (method.returnType.isVoid case false) ...[
      if ((body, bodyType) case (final body?, final bodyType?)) ...[
        declareVar('hasClosed').assign(literalFalse).statement,
        payloadListener(bodyType, refer(body.name)),
        const Code(''),
      ],
      channel(
        method.returnType,
        includeHasClosed: (body, bodyType) != (null, null),
      ).code,
      const Code(''),
      if (body case Object()) ...[
        refer('payloadListener').property('cancel').call([]).awaited.statement,
      ],
    ],
  ];
}