Skip to content

Commit 402ae85

Browse files
committed
JSON Lines server side support
1 parent 345ee00 commit 402ae85

File tree

3 files changed

+117
-10
lines changed

3 files changed

+117
-10
lines changed

src/DataObject/Common/ProblemDetail.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/**
88
* https://datatracker.ietf.org/doc/html/rfc9457#name-the-problem-details-json-ob
99
*/
10-
final class ProblemDetail
10+
final readonly class ProblemDetail
1111
{
1212
/**
1313
* @param non-empty-string|null $type https://datatracker.ietf.org/doc/html/rfc9457#name-type
@@ -17,11 +17,11 @@ final class ProblemDetail
1717
* @param non-empty-string|null $instance https://datatracker.ietf.org/doc/html/rfc9457#name-instance
1818
*/
1919
public function __construct(
20-
public readonly ?string $type,
21-
public readonly ?int $status,
22-
public readonly ?string $title,
23-
public readonly ?string $detail = null,
24-
public readonly ?string $instance = null
20+
public ?string $type,
21+
public ?int $status,
22+
public ?string $title,
23+
public ?string $detail = null,
24+
public ?string $instance = null
2525
) {
2626
}
2727
}

src/Factory/Server/ResponseFactory.php

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ final class ResponseFactory
2020
{
2121
/**
2222
* @template TBody
23-
* @param TBody|null $body will be encoded as json
23+
* @param TBody|null $body will be encoded as application/json object
2424
* @param Transformer<TBody>|null $transformer
2525
* @param int<100,505> $code
2626
* @param array<non-empty-string, string|array<string>> $headers
2727
*/
28-
public static function makeJson(mixed $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): ResponseInterface
28+
public static function makeObject(mixed $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): ResponseInterface
2929
{
3030
$headers['Content-Type'] = 'application/json';
3131
$factory = new HttpFactory();
@@ -39,6 +39,32 @@ public static function makeJson(mixed $body, ?Transformer $transformer = null, i
3939
}
4040

4141
/**
42+
* @deprecated use ResponseFactory::makeObject
43+
* @template TBody
44+
* @param TBody|null $body will be encoded as json
45+
* @param Transformer<TBody>|null $transformer
46+
* @param int<100,505> $code
47+
* @param array<non-empty-string, string|array<string>> $headers
48+
*/
49+
public static function makeJson(mixed $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): ResponseInterface
50+
{
51+
return self::makeObject($body, $transformer, $code, $headers);
52+
}
53+
54+
/**
55+
* @template TBody
56+
* @param \Iterator<TBody> $body will be encoded as application/json array
57+
* @param Transformer<TBody>|null $transformer
58+
* @param int<100,505> $code
59+
* @param array<non-empty-string, string|array<string>> $headers
60+
*/
61+
public static function makeArray(\Iterator $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): ResponseInterface
62+
{
63+
return self::makeJsonStream($body, $transformer, $code, $headers);
64+
}
65+
66+
/**
67+
* @deprecated use ResponseFactory::makeArray
4268
* @template TBody
4369
* @param \Iterator<TBody> $body will be encoded as json
4470
* @param Transformer<TBody>|null $transformer
@@ -87,12 +113,40 @@ public static function makeJsonStream(\Iterator $body, ?Transformer $transformer
87113
}));
88114
}
89115

116+
/**
117+
* @template TBody
118+
* @param \Iterator<TBody> $body will be encoded as application/jsonl https://jsonlines.org/
119+
* @param Transformer<TBody>|null $transformer
120+
* @param int<100,505> $code
121+
* @param array<non-empty-string, string|array<string>> $headers
122+
*/
123+
public static function makeStream(\Iterator $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): ResponseInterface
124+
{
125+
$headers['Content-Type'] = 'application/jsonl';
126+
$factory = new HttpFactory();
127+
$response = self::makeResponse($factory, $code, $headers);
128+
129+
return $response->withBody(new PumpStream(static function () use ($body, $transformer): ?string {
130+
if (! $body->valid()) {
131+
return null;
132+
}
133+
134+
$responseData = $body->current();
135+
$body->next();
136+
if ($transformer !== null) {
137+
$responseData = $transformer->toApi($responseData);
138+
}
139+
140+
return Utils::jsonEncode($responseData) . "\n";
141+
}));
142+
}
143+
90144
/**
91145
* @param array<non-empty-string, string|array<string>> $headers
92146
*/
93147
public static function makeWebhookResult(bool $stopDispatching = false, array $headers = []): ResponseInterface
94148
{
95-
return self::makeJson(new Result($stopDispatching), new ResultTransformer(), HttpCodes::HTTP_OK, $headers);
149+
return self::makeObject(new Result($stopDispatching), new ResultTransformer(), HttpCodes::HTTP_OK, $headers);
96150
}
97151

98152
/**

src/Factory/Symfony/ResponseFactory.php

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,20 @@
1515
final class ResponseFactory
1616
{
1717
/**
18+
* @template TBody
19+
* @param TBody|null $body will be encoded as application/json object
20+
* @param Transformer<TBody>|null $transformer
21+
* @param int<100,505> $code
22+
* @param array<non-empty-string, string|array<string>> $headers
23+
*/
24+
public static function makeObject(mixed $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): Response
25+
{
26+
$factory = new HttpFoundationFactory();
27+
return $factory->createResponse(\SimpleAsFuck\ApiToolkit\Factory\Server\ResponseFactory::makeObject($body, $transformer, $code, $headers));
28+
}
29+
30+
/**
31+
* @deprecated use ResponseFactory::makeObject
1832
* @template TBody
1933
* @param TBody|null $body will be encoded as json
2034
* @param Transformer<TBody>|null $transformer
@@ -24,10 +38,23 @@ final class ResponseFactory
2438
public static function makeJson(mixed $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): Response
2539
{
2640
$factory = new HttpFoundationFactory();
27-
return $factory->createResponse(\SimpleAsFuck\ApiToolkit\Factory\Server\ResponseFactory::makeJson($body, $transformer, $code, $headers));
41+
return $factory->createResponse(\SimpleAsFuck\ApiToolkit\Factory\Server\ResponseFactory::makeObject($body, $transformer, $code, $headers));
2842
}
2943

3044
/**
45+
* @template TBody
46+
* @param iterable<TBody> $body will be encoded as application/json array
47+
* @param Transformer<TBody>|null $transformer
48+
* @param int<100,505> $code
49+
* @param array<non-empty-string, string|array<string>> $headers
50+
*/
51+
public static function makeArray(iterable $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): StreamedResponse
52+
{
53+
return self::makeJsonStream($body, $transformer, $code, $headers);
54+
}
55+
56+
/**
57+
* @deprecated use ResponseFactory::makeArray
3158
* @template TBody
3259
* @param iterable<TBody> $body will be encoded as json
3360
* @param Transformer<TBody>|null $transformer
@@ -68,6 +95,32 @@ static function () use ($body, $transformer, $speedLimit) {
6895
}
6996

7097
/**
98+
* @template TBody
99+
* @param iterable<TBody> $body will be encoded as application/jsonl https://jsonlines.org/
100+
* @param Transformer<TBody>|null $transformer
101+
* @param int<100,505> $code
102+
* @param array<non-empty-string, string|array<string>> $headers
103+
*/
104+
public static function makeStream(iterable $body, ?Transformer $transformer = null, int $code = HttpCodes::HTTP_OK, array $headers = []): StreamedResponse
105+
{
106+
$headers['Content-Type'] = 'application/jsonl';
107+
return new StreamedResponse(
108+
static function () use ($body, $transformer): void {
109+
foreach ($body as $responseData) {
110+
if ($transformer !== null) {
111+
$responseData = $transformer->toApi($responseData);
112+
}
113+
114+
echo Utils::jsonEncode($responseData) . "\n";
115+
}
116+
},
117+
$code,
118+
$headers,
119+
);
120+
}
121+
122+
/**
123+
* @deprecated will be static
71124
* @param array<non-empty-string, string|array<string>> $headers
72125
*/
73126
public function makeWebhookResult(bool $stopDispatching = false, array $headers = []): Response

0 commit comments

Comments
 (0)