Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
17b5369
feature: first version of flow dsl completer for ace editor
norberttech Nov 4, 2025
4c7d87d
feature: added scalar_function_chain:bool property to dsl.json
norberttech Nov 4, 2025
67115dd
fix: broken default values in plauground autocompleter
norberttech Nov 5, 2025
7436606
feature: extend build:docs by dumping methods of api classes
norberttech Nov 5, 2025
90b6121
feature: added commands to generate ace editor completers code
norberttech Nov 6, 2025
b233213
refactoring: migrated from ace editor to coddemirror
norberttech Nov 6, 2025
ba24bf1
fix: sharing playground code after migration to code mirror
norberttech Nov 6, 2025
4ecae8d
feature: added flow completer to playground
norberttech Nov 6, 2025
fac8f72
feature: added dsl completer to playground
norberttech Nov 6, 2025
e3a4231
feature: added dataframe completer to playground
norberttech Nov 6, 2025
0e32f18
feature: added scalar function chain completer to playground
norberttech Nov 6, 2025
cb36ae8
fix: dsl autocompleter not creating functions with full namespace
norberttech Nov 6, 2025
5c8e646
fix: tab button now put tabs in editor instead of jumping to another …
norberttech Nov 6, 2025
343af76
feature: added playground storage to keep most recent code in browser…
norberttech Nov 6, 2025
804108b
Fixed autocompletion on fluent interface
norberttech Nov 6, 2025
4956917
feature: allow to lazy load files to wasm filesystem
norberttech Nov 7, 2025
e1e17c4
feature: added status to code editor that showes from where the code …
norberttech Nov 7, 2025
4fa9e57
feature: added file browser to flow playground
norberttech Nov 7, 2025
741a26a
feature: move all playground code to /workspace folder in wasm filesy…
norberttech Nov 7, 2025
b3afb8a
feature: added format action to playground
norberttech Nov 7, 2025
0f99920
feature: allow users to upload their own local files to playground
norberttech Nov 7, 2025
e3c3f98
refactoring: moved away from hardcoded svg icons in playground editor
norberttech Nov 7, 2025
3686e77
feature: move all notification to editor output console
norberttech Nov 7, 2025
75de86d
feature: added help to playground editor
norberttech Nov 7, 2025
d5d8984
feature: added more content to help section
norberttech Nov 7, 2025
15b2da1
feature: added file preview
norberttech Nov 7, 2025
4fe33cb
fix: comands generating code completers for playground were missing i…
norberttech Nov 7, 2025
6c830e9
fix: removed timestamp from completers templates to avoid creating em…
norberttech Nov 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
__DIR__ . '/src/lib/**/tests',
__DIR__ . '/src/tools/**/src',
__DIR__ . '/src/tools/**/tests',
__DIR__ . '/web/**/src',
__DIR__ . '/web/**/tests',
__DIR__ . '/web/landing/src',
__DIR__ . '/web/landing/tests',
__DIR__ . '/web/landing/bin',
__DIR__ . '/examples',
__DIR__ . '/tools/rector/src',
])
Expand Down
45 changes: 44 additions & 1 deletion bin/docs.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

declare(strict_types=1);

use Flow\Documentation\{FunctionCollector, FunctionsExtractor};
use Flow\Documentation\{FunctionCollector, FunctionsExtractor, MethodCollector, MethodsExtractor};
use Flow\ETL\Attribute\Module;
use Flow\ETL\DataFrame\GroupedDataFrame;
use Flow\ETL\{DataFrame, Flow};
use Flow\ETL\Function\ScalarFunctionChain;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\{InputArgument, InputInterface};
Expand Down Expand Up @@ -81,4 +84,44 @@ public function execute(InputInterface $input, OutputInterface $output) : int
}
});

$application->add(new class extends Command {
public function configure() : void
{
$this
->setName('api:dump')
->setDescription('Dump API methods from classes into json file.')
->addArgument('output', InputArgument::REQUIRED, 'Where to dump methods.');
}

public function execute(InputInterface $input, OutputInterface $output) : int
{
$repositoryRootPath = dirname(__DIR__) . '/';

$classes = [
ScalarFunctionChain::class,
Flow::class,
DataFrame::class,
GroupedDataFrame::class,
];

$normalizedMethods = [];

foreach ($classes as $className) {
$extractor = new MethodsExtractor(
$repositoryRootPath,
$className,
new MethodCollector()
);

foreach ($extractor->extract() as $method) {
$normalizedMethods[] = $method->normalize();
}
}

\file_put_contents(__DIR__ . '/../' . \ltrim((string) $input->getArgument('output'), '/'), \json_encode($normalizedMethods));

return Command::SUCCESS;
}
});

$application->run();
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -432,15 +432,16 @@
"build:phar": [
"composer update --working-dir=./src/cli",
"tools/box/vendor/bin/box compile --config ./src/cli/box.json",
"cp ./build/flow.phar ./web/landing/assets/wasm/flow.phar"
"cp ./build/flow.phar ./web/landing/assets/wasm/tools/flow.phar"
],
"build:wasm": [
"Composer\\Config::disableProcessTimeout",
"cd wasm && ./build.sh",
"@build:phar"
],
"build:docs": [
"bin/docs.php dsl:dump web/landing/resources/dsl.json"
"bin/docs.php dsl:dump web/landing/resources/dsl.json",
"bin/docs.php api:dump web/landing/resources/api.json"
],
"build:docs:api": [
"./tools/phpdocumentor/vendor/bin/phpdoc --config=./phpdoc/core.xml",
Expand Down
1 change: 1 addition & 0 deletions rector.src.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
__DIR__ . '/src/adapter/*/src',
__DIR__ . '/src/bridge/*/src',
__DIR__ . '/src/tools/*/src',
__DIR__ . '/web/landing/src',
])
->withSkip([
RemoveExtraParametersRector::class,
Expand Down
1 change: 1 addition & 0 deletions rector.tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
__DIR__ . '/src/adapter/*/*/tests',
__DIR__ . '/src/bridge/*/*/tests',
__DIR__ . '/src/tools/*/*/tests',
__DIR__ . '/web/landing/tests',
])
->withSets([
LevelSetList::UP_TO_PHP_82,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Flow\Documentation;

final class MethodCollector
{
/**
* @var array<string>
*/
public array $methods = [];

/**
* @param class-string $className
*/
public function collect(string $className) : void
{
$reflectionClass = new \ReflectionClass($className);
$methods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);

foreach ($methods as $method) {
if ($method->getDeclaringClass()->getName() !== $className) {
continue;
}

// Skip magic methods __construct and __destruct
if ($method->getName() === '__construct' || $method->getName() === '__destruct') {
continue;
}

$this->methods[] = $method->getName();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Flow\Documentation;

use Flow\Documentation\Models\MethodModel;

final readonly class MethodsExtractor
{
/**
* @param class-string $className
*/
public function __construct(
private string $repositoryRootPath,
private string $className,
private MethodCollector $methodCollector,
) {
}

/**
* @return \Generator<MethodModel>
*/
public function extract() : \Generator
{
$this->methodCollector->collect($this->className);

$reflectionClass = new \ReflectionClass($this->className);

foreach ($this->methodCollector->methods as $methodName) {
$reflectionMethod = $reflectionClass->getMethod($methodName);
$repositoryPath = \ltrim(\str_replace($this->repositoryRootPath, '', (string) $reflectionMethod->getFileName()), '/');

yield MethodModel::fromReflection(
$repositoryPath,
$reflectionMethod
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public static function fromArray(array $data) : self
);
}

public static function fromReflection(\ReflectionFunction $reflection) : self
public static function fromReflection(\ReflectionFunction|\ReflectionMethod $reflection) : self
{
return new self(
array_map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

namespace Flow\Documentation\Models;

use function Flow\Types\DSL\{type_array, type_integer, type_optional, type_string, type_structure};
use function Flow\Types\DSL\{type_array, type_boolean, type_integer, type_optional, type_string, type_structure};
use Cocur\Slugify\Slugify;
use Flow\ETL\Function\ScalarFunctionChain;

final readonly class FunctionModel
{
Expand All @@ -18,6 +19,7 @@ public function __construct(
public ParametersModel $parameters,
public TypesModel $returnType,
public AttributesModel $attributes,
public bool $scalarFunctionChain,
public ?string $docComment = null,
) {

Expand All @@ -37,6 +39,7 @@ public static function fromArray(array $data) : self
'parameters' => type_array(),
'return_type' => type_array(),
'attributes' => type_array(),
'scalar_function_chain' => type_boolean(),
'doc_comment' => type_optional(type_string()),
])->assert($data);

Expand All @@ -56,6 +59,7 @@ public static function fromArray(array $data) : self
ParametersModel::fromArray($parameters),
TypesModel::fromArray($returnType),
AttributesModel::fromArray($attributes),
$data['scalar_function_chain'],
$data['doc_comment']
);
}
Expand All @@ -77,6 +81,7 @@ public static function fromReflection(string $relativePath, \ReflectionFunction
ParametersModel::fromFunctionReflection($reflectionFunction),
TypesModel::fromReflection($returnTypeReflection),
AttributesModel::fromReflection($reflectionFunction),
self::isScalarFunctionChain($returnTypeReflection),
$reflectionFunction->getDocComment() ? \base64_encode($reflectionFunction->getDocComment()) : null,
);
}
Expand All @@ -95,7 +100,31 @@ public function normalize() : array
'parameters' => $this->parameters->normalize(),
'return_type' => $this->returnType->normalize(),
'attributes' => $this->attributes->normalize(),
'scalar_function_chain' => $this->scalarFunctionChain,
'doc_comment' => $this->docComment,
];
}

private static function isScalarFunctionChain(\ReflectionType $reflectionType) : bool
{
if ($reflectionType instanceof \ReflectionNamedType) {
$typeName = $reflectionType->getName();

if (!\class_exists($typeName)) {
return false;
}

return \is_a($typeName, ScalarFunctionChain::class, true);
}

if ($reflectionType instanceof \ReflectionUnionType || $reflectionType instanceof \ReflectionIntersectionType) {
foreach ($reflectionType->getTypes() as $type) {
if (self::isScalarFunctionChain($type)) {
return true;
}
}
}

return false;
}
}
Loading