Skip to content

Commit e79921b

Browse files
committed
Implement splitting types per file per namespace
1 parent 4e2a4d4 commit e79921b

8 files changed

+315
-21
lines changed

src/Actions/FormatTypeScriptAction.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ class FormatTypeScriptAction
88
{
99
protected TypeScriptTransformerConfig $config;
1010

11-
public function __construct(TypeScriptTransformerConfig $config)
12-
{
11+
public function __construct(
12+
TypeScriptTransformerConfig $config,
13+
protected string $outputFile
14+
) {
1315
$this->config = $config;
1416
}
1517

@@ -21,6 +23,6 @@ public function execute(): void
2123
return;
2224
}
2325

24-
$formatter->format($this->config->getOutputFile());
26+
$formatter->format($this->outputFile);
2527
}
2628
}

src/Actions/PersistTypesCollectionAction.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class PersistTypesCollectionAction
99
{
1010
protected TypeScriptTransformerConfig $config;
1111

12-
public function __construct(TypeScriptTransformerConfig $config)
12+
public function __construct(TypeScriptTransformerConfig $config, protected string $outputFile)
1313
{
1414
$this->config = $config;
1515
}
@@ -26,15 +26,15 @@ public function execute(TypesCollection $collection): void
2626
);
2727

2828
file_put_contents(
29-
$this->config->getOutputFile(),
29+
$this->outputFile,
3030
$writer->format($collection)
3131
);
3232
}
3333

3434
protected function ensureOutputFileExists(): void
3535
{
36-
if (! file_exists(pathinfo($this->config->getOutputFile(), PATHINFO_DIRNAME))) {
37-
mkdir(pathinfo($this->config->getOutputFile(), PATHINFO_DIRNAME), 0755, true);
36+
if (! file_exists(pathinfo($this->outputFile, PATHINFO_DIRNAME))) {
37+
mkdir(pathinfo($this->outputFile, PATHINFO_DIRNAME), 0755, true);
3838
}
3939
}
4040
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
namespace Spatie\TypeScriptTransformer\Actions;
4+
5+
use Exception;
6+
use Generator;
7+
use ReflectionClass;
8+
use Spatie\TypeScriptTransformer\Exceptions\NoAutoDiscoverTypesPathsDefined;
9+
use Spatie\TypeScriptTransformer\Structures\TransformedType;
10+
use Spatie\TypeScriptTransformer\Structures\TypesCollection;
11+
use Spatie\TypeScriptTransformer\TypeScriptTransformerConfig;
12+
use Symfony\Component\Finder\Finder;
13+
14+
class ResolveSplitTypesCollectionsAction
15+
{
16+
protected Finder $finder;
17+
18+
/** @var \Spatie\TypeScriptTransformer\Collectors\Collector[] */
19+
protected array $collectors;
20+
21+
protected TypeScriptTransformerConfig $config;
22+
23+
public function __construct(Finder $finder, TypeScriptTransformerConfig $config)
24+
{
25+
$this->finder = $finder;
26+
27+
$this->config = $config;
28+
29+
$this->collectors = $config->getCollectors();
30+
}
31+
32+
/**
33+
* @return TypesCollection[]
34+
* @throws NoAutoDiscoverTypesPathsDefined
35+
*/
36+
public function execute(): array
37+
{
38+
$collections = [];
39+
40+
$paths = $this->config->getAutoDiscoverTypesPaths();
41+
42+
if (empty($paths)) {
43+
throw NoAutoDiscoverTypesPathsDefined::create();
44+
}
45+
46+
foreach ($this->resolveIterator($paths) as $class) {
47+
$transformedType = $this->resolveTransformedType($class);
48+
49+
if ($transformedType === null) {
50+
continue;
51+
}
52+
$namespace = implode('/', $transformedType->getNamespaceSegments());
53+
if (!isset($collections[$namespace])) {
54+
$collections[$namespace] = new TypesCollection();
55+
}
56+
$collections[$namespace][] = $transformedType;
57+
}
58+
59+
return $collections;
60+
}
61+
62+
protected function resolveIterator(array $paths): Generator
63+
{
64+
$paths = array_map(
65+
fn (string $path) => is_dir($path) ? $path : dirname($path),
66+
$paths
67+
);
68+
69+
foreach ($this->finder->in($paths) as $fileInfo) {
70+
try {
71+
$classes = (new ResolveClassesInPhpFileAction())->execute($fileInfo);
72+
73+
foreach ($classes as $name) {
74+
yield $name => new ReflectionClass($name);
75+
}
76+
} catch (Exception $exception) {
77+
}
78+
}
79+
}
80+
81+
protected function resolveTransformedType(ReflectionClass $class): ?TransformedType
82+
{
83+
foreach ($this->collectors as $collector) {
84+
$transformedType = $collector->getTransformedType($class);
85+
86+
if ($transformedType !== null) {
87+
return $transformedType;
88+
}
89+
}
90+
91+
return null;
92+
}
93+
}

src/TypeScriptTransformer.php

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Spatie\TypeScriptTransformer;
44

5+
use Spatie\TemporaryDirectory\TemporaryDirectory;
56
use Spatie\TypeScriptTransformer\Actions\FormatTypeScriptAction;
67
use Spatie\TypeScriptTransformer\Actions\PersistTypesCollectionAction;
8+
use Spatie\TypeScriptTransformer\Actions\ResolveSplitTypesCollectionsAction;
79
use Spatie\TypeScriptTransformer\Actions\ResolveTypesCollectionAction;
810
use Spatie\TypeScriptTransformer\Structures\TypesCollection;
911
use Symfony\Component\Finder\Finder;
@@ -24,15 +26,44 @@ public function __construct(TypeScriptTransformerConfig $config)
2426

2527
public function transform(): TypesCollection
2628
{
27-
$typesCollection = (new ResolveTypesCollectionAction(
28-
new Finder(),
29-
$this->config,
30-
))->execute();
29+
if (($baseDir = $this->config->getSplitModulesBaseDir()) !== null) {
30+
(new TemporaryDirectory($baseDir))->delete();
3131

32-
(new PersistTypesCollectionAction($this->config))->execute($typesCollection);
32+
$sumCollection = new TypesCollection();
3333

34-
(new FormatTypeScriptAction($this->config))->execute();
34+
$typesCollections = (new ResolveSplitTypesCollectionsAction(
35+
new Finder(),
36+
$this->config,
37+
))->execute();
3538

36-
return $typesCollection;
39+
foreach ($typesCollections as $namespace => $typesCollection) {
40+
$outputFile = rtrim($baseDir, '/') . '/' . $namespace . '.ts';
41+
42+
(new PersistTypesCollectionAction(
43+
$this->config,
44+
$outputFile,
45+
))->execute($typesCollection);
46+
47+
(new FormatTypeScriptAction($this->config, $outputFile))->execute();
48+
49+
foreach ($typesCollection as $type) {
50+
$sumCollection[] = $type;
51+
}
52+
}
53+
54+
return $sumCollection;
55+
} else {
56+
$typesCollection = (new ResolveTypesCollectionAction(
57+
new Finder(),
58+
$this->config,
59+
))->execute();
60+
61+
(new PersistTypesCollectionAction($this->config, $this->config->getOutputFile()))->execute($typesCollection);
62+
63+
(new FormatTypeScriptAction($this->config, $this->config->getOutputFile()))->execute();
64+
65+
return $typesCollection;
66+
}
3767
}
68+
3869
}

src/TypeScriptTransformerConfig.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class TypeScriptTransformerConfig
3131

3232
private bool $nullToOptional = false;
3333

34+
private string|null $splitModulesBaseDir = null;
35+
3436
public static function create(): self
3537
{
3638
return new self();
@@ -99,6 +101,13 @@ public function nullToOptional(bool $nullToOptional = false): self
99101
return $this;
100102
}
101103

104+
public function splitModulesBaseDir(string|null $splitModules = null): self
105+
{
106+
$this->splitModulesBaseDir = $splitModules;
107+
108+
return $this;
109+
}
110+
102111
public function getAutoDiscoverTypesPaths(): array
103112
{
104113
return $this->autoDiscoverTypesPaths;
@@ -176,4 +185,9 @@ public function shouldConsiderNullAsOptional(): bool
176185
{
177186
return $this->nullToOptional;
178187
}
188+
189+
public function getSplitModulesBaseDir(): string|null
190+
{
191+
return $this->splitModulesBaseDir;
192+
}
179193
}

tests/Actions/FormatTypeScriptActionTest.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ public function format(string $file): void
2121
}
2222
};
2323

24-
$action = new FormatTypeScriptAction(
25-
TypeScriptTransformerConfig::create()
24+
$config = TypeScriptTransformerConfig::create()
2625
->formatter($formatter::class)
27-
->outputFile($this->outputFile)
26+
->outputFile($this->outputFile);
27+
28+
$action = new FormatTypeScriptAction(
29+
$config,
30+
$config->getOutputFile()
2831
);
2932

3033
file_put_contents(
@@ -38,8 +41,11 @@ public function format(string $file): void
3841
});
3942

4043
it('can disable formatting', function () {
44+
$config = TypeScriptTransformerConfig::create()->outputFile($this->outputFile);
45+
4146
$action = new FormatTypeScriptAction(
42-
TypeScriptTransformerConfig::create()->outputFile($this->outputFile)
47+
$config,
48+
$config->getOutputFile()
4349
);
4450

4551
file_put_contents(

tests/Actions/PersistTypesCollectionActionTest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
beforeEach(function () {
1212
$this->temporaryDirectory = (new TemporaryDirectory())->create();
1313

14-
$this->action = new PersistTypesCollectionAction(
15-
TypeScriptTransformerConfig::create()
14+
$config = TypeScriptTransformerConfig::create()
1615
->autoDiscoverTypes(__DIR__ . '/../FakeClasses')
1716
->transformers([MyclabsEnumTransformer::class])
18-
->outputFile($this->temporaryDirectory->path('types.d.ts'))
17+
->outputFile($this->temporaryDirectory->path('types.d.ts'));
18+
$this->action = new PersistTypesCollectionAction(
19+
$config,
20+
$config->getOutputFile()
1921
);
2022
});
2123

0 commit comments

Comments
 (0)