Compare commits
No commits in common. "10074797921606ad9573ed8d284a3727fadc09f1" and "a4beca5a4ce16e8fc481ddf5708e0461ddc05916" have entirely different histories.
1007479792
...
a4beca5a4c
103 changed files with 416 additions and 5185 deletions
|
@ -3,7 +3,6 @@ repository: https://github.com/protevus/platform
|
||||||
packages:
|
packages:
|
||||||
- apps/**
|
- apps/**
|
||||||
- packages/**
|
- packages/**
|
||||||
- helpers/tools/**
|
|
||||||
- examples/**
|
- examples/**
|
||||||
|
|
||||||
command:
|
command:
|
||||||
|
|
16
devbox.json
Normal file
16
devbox.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.11.0/.schema/devbox.schema.json",
|
||||||
|
"packages": [
|
||||||
|
"dart@latest"
|
||||||
|
],
|
||||||
|
"shell": {
|
||||||
|
"init_hook": [
|
||||||
|
"echo 'Welcome to Protevus!' > /dev/null"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": [
|
||||||
|
"echo \"Error: no test specified\" && exit 1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
devbox.lock
Normal file
53
devbox.lock
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"lockfile_version": "1",
|
||||||
|
"packages": {
|
||||||
|
"dart@latest": {
|
||||||
|
"last_modified": "2024-06-03T07:19:07Z",
|
||||||
|
"resolved": "github:NixOS/nixpkgs/4a4ecb0ab415c9fccfb005567a215e6a9564cdf5#dart",
|
||||||
|
"source": "devbox-search",
|
||||||
|
"version": "3.4.2",
|
||||||
|
"systems": {
|
||||||
|
"aarch64-darwin": {
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "out",
|
||||||
|
"path": "/nix/store/9piqr817cdsgmz31m8q723lxhcpgqsa4-dart-3.4.2",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"store_path": "/nix/store/9piqr817cdsgmz31m8q723lxhcpgqsa4-dart-3.4.2"
|
||||||
|
},
|
||||||
|
"aarch64-linux": {
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "out",
|
||||||
|
"path": "/nix/store/1j3h5yqxvgzakv5gir1ssg7wggwxhmsd-dart-3.4.2",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"store_path": "/nix/store/1j3h5yqxvgzakv5gir1ssg7wggwxhmsd-dart-3.4.2"
|
||||||
|
},
|
||||||
|
"x86_64-darwin": {
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "out",
|
||||||
|
"path": "/nix/store/k8a6gkss3s19p5dhbzgbdqqk5b8qzd7d-dart-3.4.2",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"store_path": "/nix/store/k8a6gkss3s19p5dhbzgbdqqk5b8qzd7d-dart-3.4.2"
|
||||||
|
},
|
||||||
|
"x86_64-linux": {
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "out",
|
||||||
|
"path": "/nix/store/wbj1csi5fk2w99aiglwgg1mv406pw4pn-dart-3.4.2",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"store_path": "/nix/store/wbj1csi5fk2w99aiglwgg1mv406pw4pn-dart-3.4.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,53 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Array of extensions to install
|
|
||||||
extensions=(
|
|
||||||
"nash.awesome-flutter-snippets" # Dart Data Class Generator
|
|
||||||
"robert-brunhage.flutter-riverpod-snippets" # Flutter Riverpod Snippets
|
|
||||||
"usernamehw.errorlens" # Error Lens
|
|
||||||
"aaron-bond.better-comments" # Better Comments
|
|
||||||
"plibither8.remove-comments" # Remove Comments
|
|
||||||
"patbenatar.advanced-new-file" # Advanced New File
|
|
||||||
"GitHub.copilot" # GitHub Copilot
|
|
||||||
"dracula-theme.theme-dracula" # Dracula Theme (optional)
|
|
||||||
"jsayol.firebase-explorer" # Firebase Explorer
|
|
||||||
"pflannery.vscode-versionlens" # Version Lens
|
|
||||||
"esentis.flutter-find-unused-assets-and-dart-files" # Find Unused Assets & Dart Files
|
|
||||||
"humao.rest-client" # REST Client
|
|
||||||
"rangav.vscode-thunder-client" # Thunder Client
|
|
||||||
"ritwickdey.liveserver" # Live Server
|
|
||||||
"Dart-Code.dart-code" # Dart SDK
|
|
||||||
"Dart-Code.flutter" # Flutter SDK
|
|
||||||
"ms-vscode.cpptools" # C/C++
|
|
||||||
"ms-vscode.cpptools-extension-pack" # C/C++ Extension Pack
|
|
||||||
"ms-vscode.cpptools-themes" # C/C++ Themes
|
|
||||||
"twxs.cmake " # CMake
|
|
||||||
"ms-vscode.cmake-tools" # CMake Tools
|
|
||||||
"ms-vscode.makefile-tools" # Makefile Tools
|
|
||||||
"saoudrizwan.claude-dev" # Claude Dev
|
|
||||||
"Continue.continue" # Continue
|
|
||||||
"DEVSENSE.phptools-vscode" # PHP Tools
|
|
||||||
"DEVSENSE.composer-php-vscode" # Composer PHP
|
|
||||||
"DEVSENSE.profiler-php-vscode" # Profiler PHP
|
|
||||||
"ms-vscode.remote-explorer" # Remote - Containers
|
|
||||||
"ms-vscode-remote.remote-ssh" # Remote - SSH
|
|
||||||
"ms-vscode-remote.remote-ssh-edit" # Remote - SSH: Edit
|
|
||||||
"ms-vscode-remote.remote-containers" # Remote - Containers
|
|
||||||
"eamodio.gitlens" # GitLens
|
|
||||||
"DEVSENSE.intelli-php-vscode" # IntelliPHP
|
|
||||||
"blaugold.melos-code" # Melos
|
|
||||||
"vscode-icons-team.vscode-icons" # VSCode Icons
|
|
||||||
"redhat.vscode-yaml" # YAML
|
|
||||||
"GitHub.vscode-github-actions" # GitHub Actions
|
|
||||||
"ms-azuretools.vscode-docker" # Docker
|
|
||||||
"ms-kubernetes-tools.vscode-kubernetes-tools" # Kubernetes
|
|
||||||
)
|
|
||||||
|
|
||||||
# Install each extension
|
|
||||||
echo "Installing VSCode extensions..."
|
|
||||||
for extension in "${extensions[@]}"; do
|
|
||||||
code --install-extension "$extension" --force
|
|
||||||
echo "Installed: $extension"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "All extensions have been installed successfully."
|
|
0
helpers/tools/.gitkeep
Normal file
0
helpers/tools/.gitkeep
Normal file
|
@ -1,156 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:args/args.dart';
|
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
import 'package:converter/src/extractors/base_extractor.dart';
|
|
||||||
import 'package:converter/src/extractors/php_extractor.dart';
|
|
||||||
|
|
||||||
/// Factory for creating language-specific extractors
|
|
||||||
class ExtractorFactory {
|
|
||||||
/// Create an appropriate extractor based on file extension
|
|
||||||
static LanguageExtractor? createExtractor(String extension) {
|
|
||||||
switch (extension.toLowerCase()) {
|
|
||||||
case '.php':
|
|
||||||
return PhpExtractor();
|
|
||||||
// TODO: Add more extractors as they're implemented
|
|
||||||
// case '.py':
|
|
||||||
// return PythonExtractor();
|
|
||||||
// case '.ts':
|
|
||||||
// case '.js':
|
|
||||||
// return TypeScriptExtractor();
|
|
||||||
// case '.java':
|
|
||||||
// return JavaExtractor();
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Main contract extractor CLI
|
|
||||||
class ContractExtractorCLI {
|
|
||||||
final String sourcePath;
|
|
||||||
final String outputPath;
|
|
||||||
final bool verbose;
|
|
||||||
|
|
||||||
ContractExtractorCLI({
|
|
||||||
required this.sourcePath,
|
|
||||||
required this.outputPath,
|
|
||||||
this.verbose = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Run the extraction process
|
|
||||||
Future<void> run() async {
|
|
||||||
try {
|
|
||||||
if (await FileSystemEntity.isDirectory(sourcePath)) {
|
|
||||||
await _processDirectory(sourcePath);
|
|
||||||
} else if (await FileSystemEntity.isFile(sourcePath)) {
|
|
||||||
await _processFile(sourcePath);
|
|
||||||
} else {
|
|
||||||
throw Exception('Source path does not exist: $sourcePath');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
print('Error: $e');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process a directory recursively
|
|
||||||
Future<void> _processDirectory(String dirPath) async {
|
|
||||||
final dir = Directory(dirPath);
|
|
||||||
await for (final entity in dir.list(recursive: true)) {
|
|
||||||
if (entity is File) {
|
|
||||||
await _processFile(entity.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process a single file
|
|
||||||
Future<void> _processFile(String filePath) async {
|
|
||||||
final extension = path.extension(filePath);
|
|
||||||
final extractor = ExtractorFactory.createExtractor(extension);
|
|
||||||
|
|
||||||
if (extractor == null) {
|
|
||||||
if (verbose) {
|
|
||||||
print('Skipping unsupported file type: $filePath');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Calculate relative path to maintain directory structure
|
|
||||||
final relativePath = path.relative(filePath, from: sourcePath);
|
|
||||||
final destDir = path.join(outputPath, path.dirname(relativePath));
|
|
||||||
|
|
||||||
// Create destination directory
|
|
||||||
await Directory(destDir).create(recursive: true);
|
|
||||||
|
|
||||||
// Extract contract
|
|
||||||
final contract = await extractor.parseFile(filePath);
|
|
||||||
final yamlContent = extractor.convertToYaml(contract);
|
|
||||||
|
|
||||||
// Write YAML contract
|
|
||||||
final yamlFile = File(path.join(
|
|
||||||
destDir,
|
|
||||||
'${path.basenameWithoutExtension(filePath)}.yaml',
|
|
||||||
));
|
|
||||||
await yamlFile.writeAsString(yamlContent);
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
print('Processed: $filePath');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
print('Error processing $filePath: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(List<String> arguments) async {
|
|
||||||
final parser = ArgParser()
|
|
||||||
..addOption(
|
|
||||||
'source',
|
|
||||||
abbr: 's',
|
|
||||||
help: 'Source file or directory path',
|
|
||||||
mandatory: true,
|
|
||||||
)
|
|
||||||
..addOption(
|
|
||||||
'output',
|
|
||||||
abbr: 'o',
|
|
||||||
help: 'Output directory for YAML contracts',
|
|
||||||
mandatory: true,
|
|
||||||
)
|
|
||||||
..addFlag(
|
|
||||||
'verbose',
|
|
||||||
abbr: 'v',
|
|
||||||
help: 'Enable verbose output',
|
|
||||||
defaultsTo: false,
|
|
||||||
)
|
|
||||||
..addFlag(
|
|
||||||
'help',
|
|
||||||
abbr: 'h',
|
|
||||||
help: 'Show this help message',
|
|
||||||
negatable: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
final results = parser.parse(arguments);
|
|
||||||
|
|
||||||
if (results['help'] as bool) {
|
|
||||||
print('Usage: dart extract_contracts.dart [options]');
|
|
||||||
print(parser.usage);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
final cli = ContractExtractorCLI(
|
|
||||||
sourcePath: results['source'] as String,
|
|
||||||
outputPath: results['output'] as String,
|
|
||||||
verbose: results['verbose'] as bool,
|
|
||||||
);
|
|
||||||
|
|
||||||
await cli.run();
|
|
||||||
print('Contract extraction completed successfully.');
|
|
||||||
} catch (e) {
|
|
||||||
print('Error: $e');
|
|
||||||
print('\nUsage: dart extract_contracts.dart [options]');
|
|
||||||
print(parser.usage);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,108 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
|
|
||||||
void main() async {
|
|
||||||
// Create a sample PHP file
|
|
||||||
final samplePhp = '''
|
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\\Models;
|
|
||||||
|
|
||||||
use Illuminate\\Database\\Eloquent\\Model;
|
|
||||||
use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
|
|
||||||
use App\\Interfaces\\UserInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User model class.
|
|
||||||
* Represents a user in the system.
|
|
||||||
*/
|
|
||||||
class User extends Model implements UserInterface {
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes that are mass assignable.
|
|
||||||
*
|
|
||||||
* @var array<string>
|
|
||||||
*/
|
|
||||||
protected array \$fillable = [
|
|
||||||
'name',
|
|
||||||
'email',
|
|
||||||
'password',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes that should be hidden for serialization.
|
|
||||||
*
|
|
||||||
* @var array<string>
|
|
||||||
*/
|
|
||||||
protected array \$hidden = [
|
|
||||||
'password',
|
|
||||||
'remember_token',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the user's full name.
|
|
||||||
*
|
|
||||||
* @param string \$title Optional title prefix
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getFullName(string \$title = ''): string {
|
|
||||||
return trim(\$title . ' ' . \$this->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the user's password.
|
|
||||||
*
|
|
||||||
* @param string \$value
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setPasswordAttribute(string \$value): void {
|
|
||||||
\$this->attributes['password'] = bcrypt(\$value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
|
|
||||||
// Create temporary directories
|
|
||||||
final tempDir = Directory.systemTemp.createTempSync('contract_example');
|
|
||||||
final sourceDir = Directory(path.join(tempDir.path, 'source'))..createSync();
|
|
||||||
final outputDir = Directory(path.join(tempDir.path, 'output'))..createSync();
|
|
||||||
|
|
||||||
// Write sample PHP file
|
|
||||||
final phpFile = File(path.join(sourceDir.path, 'User.php'));
|
|
||||||
await phpFile.writeAsString(samplePhp);
|
|
||||||
|
|
||||||
// Run the contract extractor
|
|
||||||
print('Extracting contracts from ${sourceDir.path}');
|
|
||||||
print('Output directory: ${outputDir.path}');
|
|
||||||
|
|
||||||
final result = await Process.run(
|
|
||||||
'dart',
|
|
||||||
[
|
|
||||||
'run',
|
|
||||||
'bin/extract_contracts.dart',
|
|
||||||
'--source',
|
|
||||||
sourceDir.path,
|
|
||||||
'--output',
|
|
||||||
outputDir.path,
|
|
||||||
'--verbose',
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.exitCode != 0) {
|
|
||||||
print('Error: ${result.stderr}');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read and display the generated YAML
|
|
||||||
final yamlFile = File(path.join(outputDir.path, 'User.yaml'));
|
|
||||||
if (await yamlFile.exists()) {
|
|
||||||
print('\nGenerated YAML contract:');
|
|
||||||
print('------------------------');
|
|
||||||
print(await yamlFile.readAsString());
|
|
||||||
} else {
|
|
||||||
print('Error: YAML file was not generated');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
tempDir.deleteSync(recursive: true);
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
import 'yaml_formatter.dart';
|
|
||||||
|
|
||||||
/// Base class for all language extractors
|
|
||||||
abstract class LanguageExtractor {
|
|
||||||
/// File extension this extractor handles (e.g., '.php', '.py')
|
|
||||||
String get fileExtension;
|
|
||||||
|
|
||||||
/// Parse a source file and extract its components
|
|
||||||
Future<Map<String, dynamic>> parseFile(String filePath);
|
|
||||||
|
|
||||||
/// Extract class-level documentation
|
|
||||||
String? extractClassComment(String content);
|
|
||||||
|
|
||||||
/// Extract dependencies (imports, use statements, etc.)
|
|
||||||
List<Map<String, String>> extractDependencies(String content);
|
|
||||||
|
|
||||||
/// Extract class properties/fields
|
|
||||||
List<Map<String, dynamic>> extractProperties(String content);
|
|
||||||
|
|
||||||
/// Extract class methods
|
|
||||||
List<Map<String, dynamic>> extractMethods(String content);
|
|
||||||
|
|
||||||
/// Extract implemented interfaces
|
|
||||||
List<String> extractInterfaces(String content);
|
|
||||||
|
|
||||||
/// Extract used traits/mixins
|
|
||||||
List<String> extractTraits(String content);
|
|
||||||
|
|
||||||
/// Convert extracted data to YAML format
|
|
||||||
String convertToYaml(Map<String, dynamic> data) {
|
|
||||||
return YamlFormatter.toYaml(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process a directory of source files
|
|
||||||
Future<void> processDirectory(String sourceDir, String destDir) async {
|
|
||||||
final sourceDirectory = Directory(sourceDir);
|
|
||||||
|
|
||||||
await for (final entity in sourceDirectory.list(recursive: true)) {
|
|
||||||
if (entity is! File || !entity.path.endsWith(fileExtension)) continue;
|
|
||||||
|
|
||||||
final relativePath = path.relative(entity.path, from: sourceDir);
|
|
||||||
final destPath = path.join(destDir, path.dirname(relativePath));
|
|
||||||
|
|
||||||
await Directory(destPath).create(recursive: true);
|
|
||||||
|
|
||||||
final data = await parseFile(entity.path);
|
|
||||||
final yamlContent = convertToYaml(data);
|
|
||||||
|
|
||||||
final yamlFile = File(path.join(
|
|
||||||
destPath, '${path.basenameWithoutExtension(entity.path)}.yaml'));
|
|
||||||
|
|
||||||
await yamlFile.writeAsString(yamlContent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse method parameters from a parameter string
|
|
||||||
List<Map<String, String>> parseParameters(String paramsStr) {
|
|
||||||
final params = <Map<String, String>>[];
|
|
||||||
if (paramsStr.trim().isEmpty) return params;
|
|
||||||
|
|
||||||
for (final param in paramsStr.split(',')) {
|
|
||||||
final parts = param.trim().split('=');
|
|
||||||
final paramInfo = <String, String>{
|
|
||||||
'name': parts[0].trim(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (parts.length > 1) {
|
|
||||||
paramInfo['default'] = parts[1].trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
params.add(paramInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Format a comment by removing common comment markers and whitespace
|
|
||||||
String? formatComment(String? comment) {
|
|
||||||
if (comment == null || comment.isEmpty) return null;
|
|
||||||
|
|
||||||
return comment
|
|
||||||
.split('\n')
|
|
||||||
.map((line) => line.trim())
|
|
||||||
.where((line) => line.isNotEmpty)
|
|
||||||
.map((line) {
|
|
||||||
// Remove common comment markers
|
|
||||||
line = line.replaceAll(RegExp(r'^/\*+|\*+/$'), '');
|
|
||||||
line = line.replaceAll(RegExp(r'^\s*\*\s*'), '');
|
|
||||||
line = line.replaceAll(RegExp(r'^//\s*'), '');
|
|
||||||
return line.trim();
|
|
||||||
})
|
|
||||||
.where((line) => line.isNotEmpty)
|
|
||||||
.join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extract type information from a type string
|
|
||||||
Map<String, dynamic> extractTypeInfo(String typeStr) {
|
|
||||||
// Handle nullable types
|
|
||||||
final isNullable = typeStr.endsWith('?');
|
|
||||||
if (isNullable) {
|
|
||||||
typeStr = typeStr.substring(0, typeStr.length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle generics
|
|
||||||
final genericMatch = RegExp(r'^([\w\d_]+)<(.+)>$').firstMatch(typeStr);
|
|
||||||
if (genericMatch != null) {
|
|
||||||
return {
|
|
||||||
'base_type': genericMatch.group(1),
|
|
||||||
'generic_params':
|
|
||||||
genericMatch.group(2)!.split(',').map((t) => t.trim()).toList(),
|
|
||||||
'nullable': isNullable,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
'type': typeStr,
|
|
||||||
'nullable': isNullable,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,157 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'base_extractor.dart';
|
|
||||||
|
|
||||||
/// Extracts contract information from PHP source files
|
|
||||||
class PhpExtractor extends LanguageExtractor {
|
|
||||||
@override
|
|
||||||
String get fileExtension => '.php';
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Map<String, dynamic>> parseFile(String filePath) async {
|
|
||||||
final file = File(filePath);
|
|
||||||
final content = await file.readAsString();
|
|
||||||
|
|
||||||
return {
|
|
||||||
'name': filePath.split('/').last.split('.').first,
|
|
||||||
'class_comment': extractClassComment(content),
|
|
||||||
'dependencies': extractDependencies(content),
|
|
||||||
'properties': extractProperties(content),
|
|
||||||
'methods': extractMethods(content),
|
|
||||||
'traits': extractTraits(content),
|
|
||||||
'interfaces': extractInterfaces(content),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? extractClassComment(String content) {
|
|
||||||
final regex =
|
|
||||||
RegExp(r'/\*\*(.*?)\*/\s*class', multiLine: true, dotAll: true);
|
|
||||||
final match = regex.firstMatch(content);
|
|
||||||
return formatComment(match?.group(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Map<String, String>> extractDependencies(String content) {
|
|
||||||
final regex = RegExp(r'use\s+([\w\\]+)(?:\s+as\s+(\w+))?;');
|
|
||||||
final matches = regex.allMatches(content);
|
|
||||||
|
|
||||||
return matches.map((match) {
|
|
||||||
final fullName = match.group(1)!;
|
|
||||||
final alias = match.group(2);
|
|
||||||
return {
|
|
||||||
'name': alias ?? fullName.split('\\').last,
|
|
||||||
'type': 'class', // Assuming class for now
|
|
||||||
'source': fullName,
|
|
||||||
};
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Map<String, dynamic>> extractProperties(String content) {
|
|
||||||
final regex = RegExp(
|
|
||||||
r'(?:/\*\*(.*?)\*/\s*)?(public|protected|private)\s+(?:readonly\s+)?(?:static\s+)?(?:[\w|]+\s+)?\$(\w+)(?:\s*=\s*[^;]+)?;',
|
|
||||||
multiLine: true,
|
|
||||||
dotAll: true,
|
|
||||||
);
|
|
||||||
final matches = regex.allMatches(content);
|
|
||||||
|
|
||||||
return matches.map((match) {
|
|
||||||
return {
|
|
||||||
'name': match.group(3), // Property name without $
|
|
||||||
'visibility': match.group(2),
|
|
||||||
'comment': formatComment(match.group(1)),
|
|
||||||
};
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Map<String, dynamic>> extractMethods(String content) {
|
|
||||||
final regex = RegExp(
|
|
||||||
r'(?:/\*\*(.*?)\*/\s*)?(public|protected|private)\s+(?:static\s+)?function\s+(\w+)\s*\((.*?)\)(?:\s*:\s*(?:[\w|\\]+))?\s*{',
|
|
||||||
multiLine: true,
|
|
||||||
dotAll: true,
|
|
||||||
);
|
|
||||||
final matches = regex.allMatches(content);
|
|
||||||
|
|
||||||
return matches.map((match) {
|
|
||||||
return {
|
|
||||||
'name': match.group(3),
|
|
||||||
'visibility': match.group(2),
|
|
||||||
'parameters': _parseMethodParameters(match.group(4) ?? ''),
|
|
||||||
'comment': formatComment(match.group(1)),
|
|
||||||
};
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Map<String, String>> _parseMethodParameters(String params) {
|
|
||||||
if (params.trim().isEmpty) return [];
|
|
||||||
|
|
||||||
final parameters = <Map<String, String>>[];
|
|
||||||
final paramList = params.split(',');
|
|
||||||
|
|
||||||
for (var param in paramList) {
|
|
||||||
param = param.trim();
|
|
||||||
if (param.isEmpty) continue;
|
|
||||||
|
|
||||||
final paramInfo = <String, String>{};
|
|
||||||
|
|
||||||
// Handle type declaration and parameter name
|
|
||||||
final typeAndName = param.split(RegExp(r'\$'));
|
|
||||||
if (typeAndName.length > 1) {
|
|
||||||
// Has type declaration
|
|
||||||
final type = typeAndName[0].trim();
|
|
||||||
if (type.isNotEmpty) {
|
|
||||||
paramInfo['type'] = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle parameter name and default value
|
|
||||||
final nameAndDefault = typeAndName[1].split('=');
|
|
||||||
paramInfo['name'] = nameAndDefault[0].trim();
|
|
||||||
|
|
||||||
if (nameAndDefault.length > 1) {
|
|
||||||
paramInfo['default'] = nameAndDefault[1].trim();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No type declaration, just name and possibly default value
|
|
||||||
final nameAndDefault = param.replaceAll(r'$', '').split('=');
|
|
||||||
paramInfo['name'] = nameAndDefault[0].trim();
|
|
||||||
|
|
||||||
if (nameAndDefault.length > 1) {
|
|
||||||
paramInfo['default'] = nameAndDefault[1].trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parameters.add(paramInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<String> extractTraits(String content) {
|
|
||||||
final regex = RegExp(r'use\s+([\w\\]+(?:\s*,\s*[\w\\]+)*)\s*;');
|
|
||||||
final matches = regex.allMatches(content);
|
|
||||||
final traits = <String>[];
|
|
||||||
|
|
||||||
for (final match in matches) {
|
|
||||||
final traitList = match.group(1)!.split(',');
|
|
||||||
traits.addAll(traitList.map((t) => t.trim()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return traits;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<String> extractInterfaces(String content) {
|
|
||||||
final regex = RegExp(r'implements\s+([\w\\]+(?:\s*,\s*[\w\\]+)*)');
|
|
||||||
final matches = regex.allMatches(content);
|
|
||||||
final interfaces = <String>[];
|
|
||||||
|
|
||||||
for (final match in matches) {
|
|
||||||
final interfaceList = match.group(1)!.split(',');
|
|
||||||
interfaces.addAll(interfaceList.map((i) => i.trim()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return interfaces;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,223 +0,0 @@
|
||||||
/// Handles YAML formatting with proper comment preservation
|
|
||||||
class YamlFormatter {
|
|
||||||
/// Format a value for YAML output
|
|
||||||
static String format(dynamic value, {int indent = 0}) {
|
|
||||||
if (value == null) return 'null';
|
|
||||||
|
|
||||||
final indentStr = ' ' * indent;
|
|
||||||
|
|
||||||
if (value is String) {
|
|
||||||
if (value.startsWith('#')) {
|
|
||||||
// Handle comments - preserve only actual comment content
|
|
||||||
return value
|
|
||||||
.split('\n')
|
|
||||||
.map((line) => line.trim())
|
|
||||||
.where((line) => line.isNotEmpty)
|
|
||||||
.map((line) => '$indentStr$line')
|
|
||||||
.join('\n');
|
|
||||||
}
|
|
||||||
// Escape special characters and handle multiline strings
|
|
||||||
if (value.contains('\n') || value.contains('"')) {
|
|
||||||
return '|\n${value.split('\n').map((line) => '$indentStr ${line.trim()}').join('\n')}';
|
|
||||||
}
|
|
||||||
return value.contains(' ') ? '"$value"' : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value is num || value is bool) {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value is List) {
|
|
||||||
if (value.isEmpty) return '[]';
|
|
||||||
final buffer = StringBuffer('\n');
|
|
||||||
for (final item in value) {
|
|
||||||
buffer.writeln(
|
|
||||||
'$indentStr- ${format(item, indent: indent + 2).trimLeft()}');
|
|
||||||
}
|
|
||||||
return buffer.toString().trimRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value is Map) {
|
|
||||||
if (value.isEmpty) return '{}';
|
|
||||||
final buffer = StringBuffer('\n');
|
|
||||||
value.forEach((key, val) {
|
|
||||||
if (val != null) {
|
|
||||||
final formattedValue = format(val, indent: indent + 2);
|
|
||||||
if (formattedValue.contains('\n')) {
|
|
||||||
buffer.writeln('$indentStr$key:$formattedValue');
|
|
||||||
} else {
|
|
||||||
buffer.writeln('$indentStr$key: $formattedValue');
|
|
||||||
}
|
|
||||||
// Add extra newline between top-level sections
|
|
||||||
if (indent == 0) {
|
|
||||||
buffer.writeln();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return buffer.toString().trimRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extract the actual documentation from a comment block
|
|
||||||
static String _extractDocumentation(String comment) {
|
|
||||||
return comment
|
|
||||||
.split('\n')
|
|
||||||
.map((line) => line.trim())
|
|
||||||
.where((line) => line.isNotEmpty)
|
|
||||||
.where(
|
|
||||||
(line) => !line.contains('class ') && !line.contains('function '))
|
|
||||||
.where((line) => !line.startsWith('@'))
|
|
||||||
.where((line) => !line.contains('use ') && !line.contains('protected '))
|
|
||||||
.where((line) => !line.contains('];') && !line.contains('['))
|
|
||||||
.where((line) => !line.contains("'"))
|
|
||||||
.where(
|
|
||||||
(line) => !line.contains('private ') && !line.contains('public '))
|
|
||||||
.where((line) => !line.contains('\$'))
|
|
||||||
.map((line) => line.trim())
|
|
||||||
.where((line) => line.isNotEmpty)
|
|
||||||
.join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Format method documentation
|
|
||||||
static String formatMethodDoc(Map<String, dynamic> method) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
|
|
||||||
// Add main comment
|
|
||||||
if (method['comment'] != null) {
|
|
||||||
final mainComment = _extractDocumentation(method['comment'].toString());
|
|
||||||
if (mainComment.isNotEmpty) {
|
|
||||||
buffer.writeln(
|
|
||||||
mainComment.split('\n').map((line) => '# $line').join('\n'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add parameter documentation
|
|
||||||
final params = method['parameters'] as List<Map<String, String>>?;
|
|
||||||
if (params != null && params.isNotEmpty) {
|
|
||||||
buffer.writeln('# Parameters:');
|
|
||||||
for (final param in params) {
|
|
||||||
final name = param['name'];
|
|
||||||
final type = param['type'] ?? 'mixed';
|
|
||||||
final defaultValue = param['default'];
|
|
||||||
if (defaultValue != null) {
|
|
||||||
buffer.writeln('# $name ($type = $defaultValue)');
|
|
||||||
} else {
|
|
||||||
buffer.writeln('# $name ($type)');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.toString().trimRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Format property documentation
|
|
||||||
static String formatPropertyDoc(Map<String, dynamic> property) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
|
|
||||||
// Add main comment
|
|
||||||
if (property['comment'] != null) {
|
|
||||||
final mainComment = _extractDocumentation(property['comment'].toString());
|
|
||||||
if (mainComment.isNotEmpty) {
|
|
||||||
buffer.writeln(
|
|
||||||
mainComment.split('\n').map((line) => '# $line').join('\n'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add visibility
|
|
||||||
if (property['visibility'] != null) {
|
|
||||||
buffer.writeln('# Visibility: ${property["visibility"]}');
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.toString().trimRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a contract to YAML format
|
|
||||||
static String toYaml(Map<String, dynamic> contract) {
|
|
||||||
final formatted = <String, dynamic>{};
|
|
||||||
|
|
||||||
// Format class documentation
|
|
||||||
if (contract['class_comment'] != null) {
|
|
||||||
final doc = _extractDocumentation(contract['class_comment'] as String);
|
|
||||||
if (doc.isNotEmpty) {
|
|
||||||
formatted['documentation'] =
|
|
||||||
doc.split('\n').map((line) => '# $line').join('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format dependencies (remove duplicates)
|
|
||||||
if (contract['dependencies'] != null) {
|
|
||||||
final deps = contract['dependencies'] as List;
|
|
||||||
final uniqueDeps = <String, Map<String, String>>{};
|
|
||||||
for (final dep in deps) {
|
|
||||||
final source = dep['source'] as String;
|
|
||||||
if (!uniqueDeps.containsKey(source)) {
|
|
||||||
uniqueDeps[source] = dep as Map<String, String>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
formatted['dependencies'] = uniqueDeps.values.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format properties with documentation
|
|
||||||
if (contract['properties'] != null) {
|
|
||||||
formatted['properties'] = (contract['properties'] as List).map((prop) {
|
|
||||||
final doc = formatPropertyDoc(prop as Map<String, dynamic>);
|
|
||||||
return {
|
|
||||||
'name': prop['name'],
|
|
||||||
'visibility': prop['visibility'],
|
|
||||||
'documentation': doc,
|
|
||||||
};
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format methods with documentation
|
|
||||||
if (contract['methods'] != null) {
|
|
||||||
formatted['methods'] = (contract['methods'] as List).map((method) {
|
|
||||||
final doc = formatMethodDoc(method as Map<String, dynamic>);
|
|
||||||
return {
|
|
||||||
'name': method['name'],
|
|
||||||
'visibility': method['visibility'],
|
|
||||||
'parameters': method['parameters'],
|
|
||||||
'documentation': doc,
|
|
||||||
};
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format interfaces (remove duplicates)
|
|
||||||
if (contract['interfaces'] != null) {
|
|
||||||
formatted['interfaces'] =
|
|
||||||
(contract['interfaces'] as List).toSet().toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format traits (remove duplicates and filter out interfaces)
|
|
||||||
if (contract['traits'] != null) {
|
|
||||||
final traits = (contract['traits'] as List)
|
|
||||||
.where((t) {
|
|
||||||
// Filter out duplicates from dependencies
|
|
||||||
if (contract['dependencies'] != null) {
|
|
||||||
final deps = contract['dependencies'] as List;
|
|
||||||
if (deps.any((d) => d['source'] == t)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Filter out interfaces
|
|
||||||
if (formatted['interfaces'] != null) {
|
|
||||||
final interfaces = formatted['interfaces'] as List;
|
|
||||||
if (interfaces.contains(t)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.toSet()
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if (traits.isNotEmpty) {
|
|
||||||
formatted['traits'] = traits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return format(formatted);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,168 +0,0 @@
|
||||||
import 'name_utils.dart';
|
|
||||||
import 'type_conversion_utils.dart';
|
|
||||||
|
|
||||||
/// Utility class for generating Dart class code
|
|
||||||
class ClassGeneratorUtils {
|
|
||||||
/// Generate a constructor for a class
|
|
||||||
static String generateConstructor(
|
|
||||||
String className, List<Map<String, dynamic>> properties) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
|
|
||||||
// Constructor signature
|
|
||||||
buffer.writeln(' $className({');
|
|
||||||
final params = <String>[];
|
|
||||||
for (final prop in properties) {
|
|
||||||
final propName = NameUtils.toDartName(prop['name'] as String);
|
|
||||||
final propType =
|
|
||||||
TypeConversionUtils.pythonToDartType(prop['type'] as String);
|
|
||||||
final hasDefault = prop['has_default'] == true;
|
|
||||||
|
|
||||||
if (hasDefault) {
|
|
||||||
params.add(' $propType? $propName,');
|
|
||||||
} else {
|
|
||||||
params.add(' required $propType $propName,');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer.writeln(params.join('\n'));
|
|
||||||
buffer.writeln(' }) {');
|
|
||||||
|
|
||||||
// Initialize properties in constructor body
|
|
||||||
for (final prop in properties) {
|
|
||||||
final propName = NameUtils.toDartName(prop['name'] as String);
|
|
||||||
final propType =
|
|
||||||
TypeConversionUtils.pythonToDartType(prop['type'] as String);
|
|
||||||
final hasDefault = prop['has_default'] == true;
|
|
||||||
|
|
||||||
if (hasDefault) {
|
|
||||||
final defaultValue = TypeConversionUtils.getDefaultValue(propType);
|
|
||||||
buffer.writeln(' _$propName = $propName ?? $defaultValue;');
|
|
||||||
} else {
|
|
||||||
buffer.writeln(' _$propName = $propName;');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer.writeln(' }');
|
|
||||||
buffer.writeln();
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate property declarations and accessors
|
|
||||||
static String generateProperties(List<Map<String, dynamic>> properties) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
|
|
||||||
for (final prop in properties) {
|
|
||||||
final propName = NameUtils.toDartName(prop['name'] as String);
|
|
||||||
final propType =
|
|
||||||
TypeConversionUtils.pythonToDartType(prop['type'] as String);
|
|
||||||
buffer.writeln(' late $propType _$propName;');
|
|
||||||
|
|
||||||
// Generate getter
|
|
||||||
buffer.writeln(' $propType get $propName => _$propName;');
|
|
||||||
|
|
||||||
// Generate setter if not readonly
|
|
||||||
final isReadonly = prop['is_readonly'];
|
|
||||||
if (isReadonly != null && !isReadonly) {
|
|
||||||
buffer.writeln(' set $propName($propType value) {');
|
|
||||||
buffer.writeln(' _$propName = value;');
|
|
||||||
buffer.writeln(' }');
|
|
||||||
}
|
|
||||||
buffer.writeln();
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate a method implementation
|
|
||||||
static String generateMethod(Map<String, dynamic> method) {
|
|
||||||
if (method['name'] == '__init__') return '';
|
|
||||||
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
final methodName = NameUtils.toDartName(method['name'] as String);
|
|
||||||
final returnType =
|
|
||||||
TypeConversionUtils.pythonToDartType(method['return_type'] as String);
|
|
||||||
final methodDoc = method['docstring'] as String?;
|
|
||||||
final isAsync = method['is_async'] == true;
|
|
||||||
|
|
||||||
if (methodDoc != null) {
|
|
||||||
buffer.writeln(' /// ${methodDoc.replaceAll('\n', '\n /// ')}');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method signature
|
|
||||||
if (isAsync) {
|
|
||||||
buffer.write(' Future<$returnType> $methodName(');
|
|
||||||
} else {
|
|
||||||
buffer.write(' $returnType $methodName(');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parameters
|
|
||||||
final params = method['arguments'] as List?;
|
|
||||||
if (params != null && params.isNotEmpty) {
|
|
||||||
final paramStrings = <String>[];
|
|
||||||
|
|
||||||
for (final param in params) {
|
|
||||||
final paramName = NameUtils.toDartName(param['name'] as String);
|
|
||||||
final paramType =
|
|
||||||
TypeConversionUtils.pythonToDartType(param['type'] as String);
|
|
||||||
final isOptional = param['is_optional'] == true;
|
|
||||||
|
|
||||||
if (isOptional) {
|
|
||||||
paramStrings.add('[$paramType $paramName]');
|
|
||||||
} else {
|
|
||||||
paramStrings.add('$paramType $paramName');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.write(paramStrings.join(', '));
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.write(')');
|
|
||||||
if (isAsync) buffer.write(' async');
|
|
||||||
buffer.writeln(' {');
|
|
||||||
buffer.writeln(' // TODO: Implement $methodName');
|
|
||||||
if (returnType == 'void') {
|
|
||||||
buffer.writeln(' throw UnimplementedError();');
|
|
||||||
} else {
|
|
||||||
buffer.writeln(' throw UnimplementedError();');
|
|
||||||
}
|
|
||||||
buffer.writeln(' }');
|
|
||||||
buffer.writeln();
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate required interface implementations
|
|
||||||
static String generateRequiredImplementations(
|
|
||||||
List<String> bases, Map<String, dynamic> classContract) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
|
|
||||||
// Generate BaseChain implementations
|
|
||||||
if (bases.contains('BaseChain')) {
|
|
||||||
buffer.writeln(' late Map<String, dynamic>? _memory;');
|
|
||||||
buffer.writeln(' Map<String, dynamic>? get memory => _memory;');
|
|
||||||
buffer.writeln();
|
|
||||||
buffer.writeln(' late bool _verbose;');
|
|
||||||
buffer.writeln(' bool get verbose => _verbose;');
|
|
||||||
buffer.writeln();
|
|
||||||
|
|
||||||
// Constructor with required properties
|
|
||||||
buffer.writeln(' ${classContract['name']}({');
|
|
||||||
buffer.writeln(' Map<String, dynamic>? memory,');
|
|
||||||
buffer.writeln(' bool? verbose,');
|
|
||||||
buffer.writeln(' }) {');
|
|
||||||
buffer.writeln(' _memory = memory ?? {};');
|
|
||||||
buffer.writeln(' _verbose = verbose ?? false;');
|
|
||||||
buffer.writeln(' }');
|
|
||||||
buffer.writeln();
|
|
||||||
|
|
||||||
// Required methods
|
|
||||||
buffer.writeln(' @override');
|
|
||||||
buffer.writeln(' void setMemory(Map<String, dynamic> memory) {');
|
|
||||||
buffer.writeln(' // TODO: Implement setMemory');
|
|
||||||
buffer.writeln(' throw UnimplementedError();');
|
|
||||||
buffer.writeln(' }');
|
|
||||||
buffer.writeln();
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
/// Utility functions for constructor generation
|
|
||||||
class ConstructorUtils {
|
|
||||||
/// Generate constructor parameter declarations
|
|
||||||
static String generateParameters(List<Map<String, dynamic>> properties) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
for (final prop in properties) {
|
|
||||||
final propName = prop['name'] as String;
|
|
||||||
final propType = prop['type'] as String;
|
|
||||||
final hasDefault = prop['has_default'] == true;
|
|
||||||
|
|
||||||
if (hasDefault) {
|
|
||||||
buffer.writeln(' $propType? $propName,');
|
|
||||||
} else {
|
|
||||||
buffer.writeln(' required $propType $propName,');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate constructor initialization statements
|
|
||||||
static String generateInitializers(List<Map<String, dynamic>> properties) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
for (final prop in properties) {
|
|
||||||
final propName = prop['name'] as String;
|
|
||||||
final hasDefault = prop['has_default'] == true;
|
|
||||||
if (hasDefault) {
|
|
||||||
buffer.writeln(
|
|
||||||
' _$propName = $propName ?? false;'); // TODO: Better default values
|
|
||||||
} else {
|
|
||||||
buffer.writeln(' _$propName = $propName;');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if a method is a constructor (__init__)
|
|
||||||
static bool isConstructor(Map<String, dynamic> method) {
|
|
||||||
return method['name'] == '__init__';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
/// Utility functions for name conversions
|
|
||||||
class NameUtils {
|
|
||||||
/// Convert Python method/property name to Dart style
|
|
||||||
static String toDartName(String pythonName) {
|
|
||||||
// Handle special Python method names
|
|
||||||
if (pythonName.startsWith('__') && pythonName.endsWith('__')) {
|
|
||||||
final name = pythonName.substring(2, pythonName.length - 2);
|
|
||||||
if (name == 'init') return 'new';
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert snake_case to camelCase
|
|
||||||
final parts = pythonName.split('_');
|
|
||||||
if (parts.isEmpty) return pythonName;
|
|
||||||
|
|
||||||
return parts.first +
|
|
||||||
parts
|
|
||||||
.skip(1)
|
|
||||||
.where((p) => p.isNotEmpty)
|
|
||||||
.map((p) => p[0].toUpperCase() + p.substring(1))
|
|
||||||
.join('');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
/// Utility class for converting Python types to Dart types
|
|
||||||
class TypeConversionUtils {
|
|
||||||
/// Convert a Python type string to its Dart equivalent
|
|
||||||
static String pythonToDartType(String pythonType) {
|
|
||||||
final typeMap = {
|
|
||||||
'str': 'String',
|
|
||||||
'int': 'int',
|
|
||||||
'float': 'double',
|
|
||||||
'bool': 'bool',
|
|
||||||
'List': 'List',
|
|
||||||
'Dict': 'Map',
|
|
||||||
'dict': 'Map<String, dynamic>',
|
|
||||||
'Any': 'dynamic',
|
|
||||||
'None': 'void',
|
|
||||||
'Optional': 'dynamic',
|
|
||||||
'Union': 'dynamic',
|
|
||||||
'Callable': 'Function',
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle generic types
|
|
||||||
if (pythonType.contains('[')) {
|
|
||||||
final match = RegExp(r'(\w+)\[(.*)\]').firstMatch(pythonType);
|
|
||||||
if (match != null) {
|
|
||||||
final baseType = match.group(1)!;
|
|
||||||
final genericType = match.group(2)!;
|
|
||||||
|
|
||||||
if (baseType == 'List') {
|
|
||||||
return 'List<${pythonToDartType(genericType)}>';
|
|
||||||
} else if (baseType == 'Dict' || baseType == 'dict') {
|
|
||||||
final types = genericType.split(',');
|
|
||||||
if (types.length == 2) {
|
|
||||||
return 'Map<${pythonToDartType(types[0].trim())}, ${pythonToDartType(types[1].trim())}>';
|
|
||||||
}
|
|
||||||
return 'Map<String, dynamic>';
|
|
||||||
} else if (baseType == 'Optional') {
|
|
||||||
final innerType = pythonToDartType(genericType);
|
|
||||||
if (innerType == 'Map<String, dynamic>') {
|
|
||||||
return 'Map<String, dynamic>?';
|
|
||||||
}
|
|
||||||
return '${innerType}?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle raw types
|
|
||||||
if (pythonType == 'dict') {
|
|
||||||
return 'Map<String, dynamic>';
|
|
||||||
} else if (pythonType == 'None') {
|
|
||||||
return 'void';
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeMap[pythonType] ?? pythonType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a default value for a Dart type
|
|
||||||
static String getDefaultValue(String dartType) {
|
|
||||||
switch (dartType) {
|
|
||||||
case 'bool':
|
|
||||||
case 'bool?':
|
|
||||||
return 'false';
|
|
||||||
case 'int':
|
|
||||||
case 'int?':
|
|
||||||
return '0';
|
|
||||||
case 'double':
|
|
||||||
case 'double?':
|
|
||||||
return '0.0';
|
|
||||||
case 'String':
|
|
||||||
case 'String?':
|
|
||||||
return "''";
|
|
||||||
case 'Map<String, dynamic>':
|
|
||||||
case 'Map<String, dynamic>?':
|
|
||||||
return '{}';
|
|
||||||
case 'List':
|
|
||||||
case 'List?':
|
|
||||||
return '[]';
|
|
||||||
default:
|
|
||||||
if (dartType.startsWith('List<')) {
|
|
||||||
return '[]';
|
|
||||||
} else if (dartType.startsWith('Map<')) {
|
|
||||||
return '{}';
|
|
||||||
} else if (dartType.endsWith('?')) {
|
|
||||||
return 'null';
|
|
||||||
}
|
|
||||||
return 'null';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
/// Utility functions for type casting
|
|
||||||
class TypeUtils {
|
|
||||||
/// Cast a List<dynamic> to List<Map<String, dynamic>>
|
|
||||||
static List<Map<String, dynamic>> castToMapList(List<dynamic>? list) {
|
|
||||||
if (list == null) return [];
|
|
||||||
return list.map((item) => item as Map<String, dynamic>).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cast a dynamic value to Map<String, dynamic>
|
|
||||||
static Map<String, dynamic> castToMap(dynamic value) {
|
|
||||||
if (value == null) return {};
|
|
||||||
return value as Map<String, dynamic>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cast a List<dynamic> to List<String>
|
|
||||||
static List<String> castToStringList(List<dynamic>? list) {
|
|
||||||
if (list == null) return [];
|
|
||||||
return list.map((item) => item.toString()).toList();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
import 'package:yaml/yaml.dart';
|
|
||||||
|
|
||||||
/// Utility class for handling YAML conversions
|
|
||||||
class YamlUtils {
|
|
||||||
/// Convert YamlMap to regular Map recursively
|
|
||||||
static Map<String, dynamic> convertYamlToMap(YamlMap yamlMap) {
|
|
||||||
return Map<String, dynamic>.fromEntries(
|
|
||||||
yamlMap.entries.map((entry) {
|
|
||||||
if (entry.value is YamlMap) {
|
|
||||||
return MapEntry(
|
|
||||||
entry.key.toString(),
|
|
||||||
convertYamlToMap(entry.value as YamlMap),
|
|
||||||
);
|
|
||||||
} else if (entry.value is YamlList) {
|
|
||||||
return MapEntry(
|
|
||||||
entry.key.toString(),
|
|
||||||
convertYamlList(entry.value as YamlList),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return MapEntry(entry.key.toString(), entry.value);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert YamlList to regular List recursively
|
|
||||||
static List<dynamic> convertYamlList(YamlList yamlList) {
|
|
||||||
return yamlList.map((item) {
|
|
||||||
if (item is YamlMap) {
|
|
||||||
return convertYamlToMap(item);
|
|
||||||
} else if (item is YamlList) {
|
|
||||||
return convertYamlList(item);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,402 +0,0 @@
|
||||||
# Generated by pub
|
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
|
||||||
packages:
|
|
||||||
_fe_analyzer_shared:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: _fe_analyzer_shared
|
|
||||||
sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "73.0.0"
|
|
||||||
_macros:
|
|
||||||
dependency: transitive
|
|
||||||
description: dart
|
|
||||||
source: sdk
|
|
||||||
version: "0.3.2"
|
|
||||||
analyzer:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: analyzer
|
|
||||||
sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "6.8.0"
|
|
||||||
args:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: args
|
|
||||||
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.6.0"
|
|
||||||
async:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: async
|
|
||||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.12.0"
|
|
||||||
boolean_selector:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: boolean_selector
|
|
||||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
collection:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: collection
|
|
||||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.19.1"
|
|
||||||
convert:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: convert
|
|
||||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.2"
|
|
||||||
coverage:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: coverage
|
|
||||||
sha256: "88b0fddbe4c92910fefc09cc0248f5e7f0cd23e450ded4c28f16ab8ee8f83268"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.10.0"
|
|
||||||
crypto:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: crypto
|
|
||||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.6"
|
|
||||||
file:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: file
|
|
||||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "7.0.1"
|
|
||||||
frontend_server_client:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: frontend_server_client
|
|
||||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.0.0"
|
|
||||||
glob:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: glob
|
|
||||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
http_multi_server:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: http_multi_server
|
|
||||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.2.1"
|
|
||||||
http_parser:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: http_parser
|
|
||||||
sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.1.1"
|
|
||||||
io:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: io
|
|
||||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.4"
|
|
||||||
js:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: js
|
|
||||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.7.1"
|
|
||||||
lints:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: lints
|
|
||||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.1"
|
|
||||||
logging:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: logging
|
|
||||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.0"
|
|
||||||
macros:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: macros
|
|
||||||
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.2-main.4"
|
|
||||||
matcher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: matcher
|
|
||||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.12.16+1"
|
|
||||||
meta:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: meta
|
|
||||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.16.0"
|
|
||||||
mime:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: mime
|
|
||||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
node_preamble:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: node_preamble
|
|
||||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.2"
|
|
||||||
package_config:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: package_config
|
|
||||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.0"
|
|
||||||
path:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: path
|
|
||||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.9.1"
|
|
||||||
pool:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pool
|
|
||||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.5.1"
|
|
||||||
pub_semver:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pub_semver
|
|
||||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.4"
|
|
||||||
shelf:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf
|
|
||||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.2"
|
|
||||||
shelf_packages_handler:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_packages_handler
|
|
||||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.2"
|
|
||||||
shelf_static:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_static
|
|
||||||
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.3"
|
|
||||||
shelf_web_socket:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_web_socket
|
|
||||||
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
source_map_stack_trace:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_map_stack_trace
|
|
||||||
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
source_maps:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_maps
|
|
||||||
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.10.12"
|
|
||||||
source_span:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_span
|
|
||||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.10.0"
|
|
||||||
stack_trace:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stack_trace
|
|
||||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.12.0"
|
|
||||||
stream_channel:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stream_channel
|
|
||||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
string_scanner:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: string_scanner
|
|
||||||
sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.0"
|
|
||||||
term_glyph:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: term_glyph
|
|
||||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.1"
|
|
||||||
test:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: test
|
|
||||||
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.25.8"
|
|
||||||
test_api:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test_api
|
|
||||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.7.3"
|
|
||||||
test_core:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test_core
|
|
||||||
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.6.5"
|
|
||||||
typed_data:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: typed_data
|
|
||||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.0"
|
|
||||||
vm_service:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: vm_service
|
|
||||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "14.3.1"
|
|
||||||
watcher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: watcher
|
|
||||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.0"
|
|
||||||
web:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: web
|
|
||||||
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.0"
|
|
||||||
web_socket:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: web_socket
|
|
||||||
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.6"
|
|
||||||
web_socket_channel:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: web_socket_channel
|
|
||||||
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.1"
|
|
||||||
webkit_inspection_protocol:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: webkit_inspection_protocol
|
|
||||||
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.1"
|
|
||||||
yaml:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: yaml
|
|
||||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.2"
|
|
||||||
sdks:
|
|
||||||
dart: ">=3.5.0 <4.0.0"
|
|
|
@ -1,15 +0,0 @@
|
||||||
name: converter
|
|
||||||
description: A Dart implementation of LangChain, providing tools and utilities for building applications powered by large language models (LLMs).
|
|
||||||
version: 0.1.0
|
|
||||||
|
|
||||||
environment:
|
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
yaml: ^3.1.2
|
|
||||||
path: ^1.8.3
|
|
||||||
args: ^2.4.2
|
|
||||||
|
|
||||||
dev_dependencies:
|
|
||||||
lints: ^2.1.1
|
|
||||||
test: ^1.24.6
|
|
|
@ -1,95 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../tools/generate_dart_code.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('Class Generation', () {
|
|
||||||
test('generates class with interface implementations', () {
|
|
||||||
final classContract = {
|
|
||||||
'name': 'SimpleChain',
|
|
||||||
'docstring': 'A simple implementation of a chain.',
|
|
||||||
'bases': ['BaseChain'],
|
|
||||||
'methods': [
|
|
||||||
{
|
|
||||||
'name': 'run',
|
|
||||||
'return_type': 'dict',
|
|
||||||
'arguments': [
|
|
||||||
{
|
|
||||||
'name': 'inputs',
|
|
||||||
'type': 'dict',
|
|
||||||
'is_optional': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'docstring': 'Execute the chain logic.',
|
|
||||||
}
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = generateClass(classContract);
|
|
||||||
|
|
||||||
// Should include BaseChain implementations
|
|
||||||
expect(code, contains('late Map<String, dynamic>? _memory;'));
|
|
||||||
expect(code, contains('Map<String, dynamic>? get memory => _memory;'));
|
|
||||||
expect(code, contains('late bool _verbose;'));
|
|
||||||
expect(code, contains('bool get verbose => _verbose;'));
|
|
||||||
|
|
||||||
// Should include constructor with required properties
|
|
||||||
expect(code, contains('SimpleChain({'));
|
|
||||||
expect(code, contains('Map<String, dynamic>? memory,'));
|
|
||||||
expect(code, contains('bool? verbose,'));
|
|
||||||
expect(code, contains('_memory = memory ?? {};'));
|
|
||||||
expect(code, contains('_verbose = verbose ?? false;'));
|
|
||||||
|
|
||||||
// Should include required method implementations
|
|
||||||
expect(code, contains('@override'));
|
|
||||||
expect(code, contains('void setMemory(Map<String, dynamic> memory)'));
|
|
||||||
|
|
||||||
// Should include additional methods
|
|
||||||
expect(code, contains('Map<String, dynamic> run('));
|
|
||||||
expect(code, contains('Map<String, dynamic> inputs'));
|
|
||||||
expect(code, contains('/// Execute the chain logic.'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('generates class with own properties and methods', () {
|
|
||||||
final classContract = {
|
|
||||||
'name': 'CustomClass',
|
|
||||||
'docstring': 'A custom class.',
|
|
||||||
'properties': [
|
|
||||||
{
|
|
||||||
'name': 'model_name',
|
|
||||||
'type': 'String',
|
|
||||||
'has_default': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'methods': [
|
|
||||||
{
|
|
||||||
'name': 'process',
|
|
||||||
'return_type': 'String',
|
|
||||||
'arguments': [
|
|
||||||
{
|
|
||||||
'name': 'input',
|
|
||||||
'type': 'String',
|
|
||||||
'is_optional': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'docstring': 'Process input.',
|
|
||||||
}
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = generateClass(classContract);
|
|
||||||
|
|
||||||
// Should include properties
|
|
||||||
expect(code, contains('late String _modelName;'));
|
|
||||||
expect(code, contains('String get modelName => _modelName;'));
|
|
||||||
|
|
||||||
// Should include constructor
|
|
||||||
expect(code, contains('CustomClass({'));
|
|
||||||
expect(code, contains('required String modelName'));
|
|
||||||
expect(code, contains('_modelName = modelName;'));
|
|
||||||
|
|
||||||
// Should include methods
|
|
||||||
expect(code, contains('String process(String input)'));
|
|
||||||
expect(code, contains('/// Process input.'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../tools/generate_dart_code.dart';
|
|
||||||
import '../lib/src/utils/class_generator_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('Code Generator Integration', () {
|
|
||||||
test('generates complete class with properties and methods', () {
|
|
||||||
final classContract = {
|
|
||||||
'name': 'TestModel',
|
|
||||||
'docstring': 'A test model implementation.',
|
|
||||||
'bases': ['BaseModel'],
|
|
||||||
'properties': [
|
|
||||||
{
|
|
||||||
'name': 'model_name',
|
|
||||||
'type': 'String',
|
|
||||||
'has_default': false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'is_loaded',
|
|
||||||
'type': 'bool',
|
|
||||||
'has_default': true,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'methods': [
|
|
||||||
{
|
|
||||||
'name': '__init__',
|
|
||||||
'return_type': 'None',
|
|
||||||
'arguments': [
|
|
||||||
{
|
|
||||||
'name': 'model_name',
|
|
||||||
'type': 'String',
|
|
||||||
'is_optional': false,
|
|
||||||
'has_default': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'docstring': 'Initialize the model.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'process_input',
|
|
||||||
'return_type': 'String',
|
|
||||||
'arguments': [
|
|
||||||
{
|
|
||||||
'name': 'input_text',
|
|
||||||
'type': 'String',
|
|
||||||
'is_optional': false,
|
|
||||||
'has_default': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'docstring': 'Process input text.',
|
|
||||||
'is_async': true,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = generateClass(classContract);
|
|
||||||
|
|
||||||
// Class definition
|
|
||||||
expect(code, contains('class TestModel implements BaseModel {'));
|
|
||||||
expect(code, contains('/// A test model implementation.'));
|
|
||||||
|
|
||||||
// Properties
|
|
||||||
expect(code, contains('late String _modelName;'));
|
|
||||||
expect(code, contains('String get modelName => _modelName;'));
|
|
||||||
expect(code, contains('late bool _isLoaded;'));
|
|
||||||
expect(code, contains('bool get isLoaded => _isLoaded;'));
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
expect(code, contains('TestModel({'));
|
|
||||||
expect(code, contains('required String modelName,'));
|
|
||||||
expect(code, contains('bool? isLoaded,'));
|
|
||||||
expect(code, contains('_modelName = modelName;'));
|
|
||||||
expect(code, contains('_isLoaded = isLoaded ?? false;'));
|
|
||||||
|
|
||||||
// Methods
|
|
||||||
expect(code,
|
|
||||||
contains('Future<String> processInput(String inputText) async {'));
|
|
||||||
expect(code, contains('/// Process input text.'));
|
|
||||||
|
|
||||||
// No __init__ method
|
|
||||||
expect(code, isNot(contains('__init__')));
|
|
||||||
expect(code, isNot(contains('void new(')));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../tools/generate_dart_code.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('Code Generator Name Handling', () {
|
|
||||||
test('converts Python method names to Dart style in interfaces', () {
|
|
||||||
final interface = {
|
|
||||||
'name': 'TestInterface',
|
|
||||||
'docstring': 'Test interface.',
|
|
||||||
'methods': [
|
|
||||||
{
|
|
||||||
'name': 'get_model_name',
|
|
||||||
'return_type': 'str',
|
|
||||||
'arguments': [],
|
|
||||||
'docstring': 'Get model name.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': '__init__',
|
|
||||||
'return_type': 'None',
|
|
||||||
'arguments': [
|
|
||||||
{
|
|
||||||
'name': 'model_path',
|
|
||||||
'type': 'str',
|
|
||||||
'is_optional': false,
|
|
||||||
'has_default': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'docstring': 'Initialize.',
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'properties': [],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = generateInterface(interface);
|
|
||||||
expect(code, contains('String getModelName();'));
|
|
||||||
expect(code, contains('void new(String modelPath);'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('converts Python property names to Dart style in classes', () {
|
|
||||||
final classContract = {
|
|
||||||
'name': 'TestClass',
|
|
||||||
'docstring': 'Test class.',
|
|
||||||
'properties': [
|
|
||||||
{
|
|
||||||
'name': 'model_name',
|
|
||||||
'type': 'str',
|
|
||||||
'has_default': false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'is_initialized',
|
|
||||||
'type': 'bool',
|
|
||||||
'has_default': true,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'methods': [],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = generateClass(classContract);
|
|
||||||
expect(code, contains('String get modelName'));
|
|
||||||
expect(code, contains('bool get isInitialized'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../tools/generate_dart_code.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('Code Generator', () {
|
|
||||||
test('generates constructor correctly', () {
|
|
||||||
final classContract = {
|
|
||||||
'name': 'TestClass',
|
|
||||||
'docstring': 'Test class.',
|
|
||||||
'properties': [
|
|
||||||
{
|
|
||||||
'name': 'name',
|
|
||||||
'type': 'String',
|
|
||||||
'has_default': false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'is_ready',
|
|
||||||
'type': 'bool',
|
|
||||||
'has_default': true,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = generateClass(classContract);
|
|
||||||
expect(code, contains('TestClass({'));
|
|
||||||
expect(code, contains('required String name,'));
|
|
||||||
expect(code, contains('bool? isReady,'));
|
|
||||||
expect(code, contains('_name = name;'));
|
|
||||||
expect(code, contains('_isReady = isReady ?? false;'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles async methods correctly', () {
|
|
||||||
final classContract = {
|
|
||||||
'name': 'TestClass',
|
|
||||||
'docstring': 'Test class.',
|
|
||||||
'methods': [
|
|
||||||
{
|
|
||||||
'name': 'process',
|
|
||||||
'return_type': 'String',
|
|
||||||
'arguments': [
|
|
||||||
{
|
|
||||||
'name': 'input',
|
|
||||||
'type': 'String',
|
|
||||||
'is_optional': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'docstring': 'Process input.',
|
|
||||||
'is_async': true,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = generateClass(classContract);
|
|
||||||
expect(code, contains('Future<String> process(String input) async {'));
|
|
||||||
expect(code, contains('/// Process input.'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('initializes properties in constructor', () {
|
|
||||||
final classContract = {
|
|
||||||
'name': 'TestClass',
|
|
||||||
'docstring': 'Test class.',
|
|
||||||
'properties': [
|
|
||||||
{
|
|
||||||
'name': 'name',
|
|
||||||
'type': 'String',
|
|
||||||
'has_default': false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'is_ready',
|
|
||||||
'type': 'bool',
|
|
||||||
'has_default': true,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = generateClass(classContract);
|
|
||||||
expect(code, contains('late String _name;'));
|
|
||||||
expect(code, contains('late bool _isReady;'));
|
|
||||||
expect(code, contains('_name = name;'));
|
|
||||||
expect(code, contains('_isReady = isReady ?? false;'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,181 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../../lib/src/extractors/php_extractor.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('PhpExtractor', () {
|
|
||||||
final extractor = PhpExtractor();
|
|
||||||
|
|
||||||
test('extracts class comment', () {
|
|
||||||
const phpCode = '''
|
|
||||||
/**
|
|
||||||
* User entity class.
|
|
||||||
* Represents a user in the system.
|
|
||||||
*/
|
|
||||||
class User {
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
final comment = extractor.extractClassComment(phpCode);
|
|
||||||
expect(comment, contains('User entity class'));
|
|
||||||
expect(comment, contains('Represents a user in the system'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('extracts dependencies', () {
|
|
||||||
const phpCode = '''
|
|
||||||
use App\\Models\\User;
|
|
||||||
use Illuminate\\Support\\Str as StringHelper;
|
|
||||||
use App\\Interfaces\\UserInterface;
|
|
||||||
''';
|
|
||||||
final deps = extractor.extractDependencies(phpCode);
|
|
||||||
expect(deps, hasLength(3));
|
|
||||||
expect(deps[0]['name'], equals('User'));
|
|
||||||
expect(deps[1]['name'], equals('StringHelper'));
|
|
||||||
expect(deps[2]['name'], equals('UserInterface'));
|
|
||||||
expect(deps[1]['source'], equals('Illuminate\\Support\\Str'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('extracts properties', () {
|
|
||||||
const phpCode = '''
|
|
||||||
class User {
|
|
||||||
/**
|
|
||||||
* The user's name.
|
|
||||||
*/
|
|
||||||
private string \$name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user's email.
|
|
||||||
*/
|
|
||||||
protected string \$email;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the user active?
|
|
||||||
*/
|
|
||||||
public bool \$isActive = false;
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
final props = extractor.extractProperties(phpCode);
|
|
||||||
expect(props, hasLength(3));
|
|
||||||
|
|
||||||
expect(props[0]['name'], equals('name'));
|
|
||||||
expect(props[0]['visibility'], equals('private'));
|
|
||||||
expect(props[0]['comment'], contains("The user's name"));
|
|
||||||
|
|
||||||
expect(props[1]['name'], equals('email'));
|
|
||||||
expect(props[1]['visibility'], equals('protected'));
|
|
||||||
|
|
||||||
expect(props[2]['name'], equals('isActive'));
|
|
||||||
expect(props[2]['visibility'], equals('public'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('extracts methods', () {
|
|
||||||
const phpCode = '''
|
|
||||||
class User {
|
|
||||||
/**
|
|
||||||
* Get the user's full name.
|
|
||||||
* @param string \$title Optional title
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getFullName(string \$title = '') {
|
|
||||||
return \$title . ' ' . \$this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the user's email address.
|
|
||||||
*/
|
|
||||||
protected function setEmail(string \$email) {
|
|
||||||
\$this->email = \$email;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
final methods = extractor.extractMethods(phpCode);
|
|
||||||
expect(methods, hasLength(2));
|
|
||||||
|
|
||||||
expect(methods[0]['name'], equals('getFullName'));
|
|
||||||
expect(methods[0]['visibility'], equals('public'));
|
|
||||||
expect(methods[0]['parameters'], hasLength(1));
|
|
||||||
expect(methods[0]['parameters'][0]['name'], equals('title'));
|
|
||||||
expect(methods[0]['parameters'][0]['default'], equals("''"));
|
|
||||||
expect(methods[0]['comment'], contains("Get the user's full name"));
|
|
||||||
|
|
||||||
expect(methods[1]['name'], equals('setEmail'));
|
|
||||||
expect(methods[1]['visibility'], equals('protected'));
|
|
||||||
expect(methods[1]['parameters'], hasLength(1));
|
|
||||||
expect(methods[1]['parameters'][0]['name'], equals('email'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('extracts interfaces', () {
|
|
||||||
const phpCode = '''
|
|
||||||
class User implements UserInterface, Authenticatable {
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
final interfaces = extractor.extractInterfaces(phpCode);
|
|
||||||
expect(interfaces, hasLength(2));
|
|
||||||
expect(interfaces[0], equals('UserInterface'));
|
|
||||||
expect(interfaces[1], equals('Authenticatable'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('extracts traits', () {
|
|
||||||
const phpCode = '''
|
|
||||||
class User {
|
|
||||||
use HasFactory, Notifiable;
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
final traits = extractor.extractTraits(phpCode);
|
|
||||||
expect(traits, hasLength(2));
|
|
||||||
expect(traits[0], equals('HasFactory'));
|
|
||||||
expect(traits[1], equals('Notifiable'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('generates valid YAML output', () {
|
|
||||||
const phpCode = '''
|
|
||||||
/**
|
|
||||||
* User entity class.
|
|
||||||
*/
|
|
||||||
class User implements UserInterface {
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user's name.
|
|
||||||
*/
|
|
||||||
private string \$name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the user's name.
|
|
||||||
*/
|
|
||||||
public function getName(): string {
|
|
||||||
return \$this->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
''';
|
|
||||||
final contract = {
|
|
||||||
'name': 'User',
|
|
||||||
'class_comment': extractor.extractClassComment(phpCode),
|
|
||||||
'dependencies': extractor.extractDependencies(phpCode),
|
|
||||||
'properties': extractor.extractProperties(phpCode),
|
|
||||||
'methods': extractor.extractMethods(phpCode),
|
|
||||||
'traits': extractor.extractTraits(phpCode),
|
|
||||||
'interfaces': extractor.extractInterfaces(phpCode),
|
|
||||||
};
|
|
||||||
|
|
||||||
final yaml = extractor.convertToYaml(contract);
|
|
||||||
|
|
||||||
// Check required sections
|
|
||||||
expect(yaml, contains('documentation:'));
|
|
||||||
expect(yaml, contains('properties:'));
|
|
||||||
expect(yaml, contains('methods:'));
|
|
||||||
expect(yaml, contains('interfaces:'));
|
|
||||||
|
|
||||||
// Check content
|
|
||||||
expect(yaml, contains('User entity class'));
|
|
||||||
expect(yaml, contains('name: name'));
|
|
||||||
expect(yaml, contains('visibility: private'));
|
|
||||||
expect(yaml, contains('name: getName'));
|
|
||||||
expect(yaml, contains('visibility: public'));
|
|
||||||
expect(yaml, contains('UserInterface'));
|
|
||||||
|
|
||||||
// Verify formatting
|
|
||||||
expect(yaml, isNot(contains('class User')));
|
|
||||||
expect(yaml, isNot(contains('function')));
|
|
||||||
expect(yaml, isNot(contains('private string')));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
112
helpers/tools/converter/test/fixtures/contracts.yaml
vendored
112
helpers/tools/converter/test/fixtures/contracts.yaml
vendored
|
@ -1,112 +0,0 @@
|
||||||
interfaces:
|
|
||||||
-
|
|
||||||
name: "LLMProtocol"
|
|
||||||
bases:
|
|
||||||
- Protocol
|
|
||||||
methods:
|
|
||||||
-
|
|
||||||
name: "generate"
|
|
||||||
arguments:
|
|
||||||
-
|
|
||||||
name: "prompts"
|
|
||||||
type: "List[str]"
|
|
||||||
is_optional: false
|
|
||||||
has_default: false
|
|
||||||
return_type: "List[str]"
|
|
||||||
docstring: "Generate completions for the prompts."
|
|
||||||
decorators:
|
|
||||||
-
|
|
||||||
name: "abstractmethod"
|
|
||||||
is_abstract: true
|
|
||||||
-
|
|
||||||
name: "model_name"
|
|
||||||
arguments:
|
|
||||||
return_type: "str"
|
|
||||||
docstring: "Get the model name."
|
|
||||||
decorators:
|
|
||||||
-
|
|
||||||
name: "property"
|
|
||||||
-
|
|
||||||
name: "abstractmethod"
|
|
||||||
is_abstract: true
|
|
||||||
properties:
|
|
||||||
docstring: "Protocol for language models."
|
|
||||||
decorators:
|
|
||||||
is_interface: true
|
|
||||||
classes:
|
|
||||||
-
|
|
||||||
name: "BaseChain"
|
|
||||||
bases:
|
|
||||||
- ABC
|
|
||||||
methods:
|
|
||||||
-
|
|
||||||
name: "run"
|
|
||||||
arguments:
|
|
||||||
-
|
|
||||||
name: "inputs"
|
|
||||||
type: "dict"
|
|
||||||
is_optional: false
|
|
||||||
has_default: false
|
|
||||||
return_type: "dict"
|
|
||||||
docstring: "Run the chain on the inputs."
|
|
||||||
decorators:
|
|
||||||
-
|
|
||||||
name: "abstractmethod"
|
|
||||||
is_abstract: true
|
|
||||||
-
|
|
||||||
name: "set_memory"
|
|
||||||
arguments:
|
|
||||||
-
|
|
||||||
name: "memory"
|
|
||||||
type: "dict"
|
|
||||||
is_optional: false
|
|
||||||
has_default: false
|
|
||||||
return_type: "None"
|
|
||||||
docstring: "Set the memory for the chain."
|
|
||||||
decorators:
|
|
||||||
is_abstract: false
|
|
||||||
properties:
|
|
||||||
-
|
|
||||||
name: "memory"
|
|
||||||
type: "Optional[dict]"
|
|
||||||
has_default: true
|
|
||||||
-
|
|
||||||
name: "verbose"
|
|
||||||
type: "bool"
|
|
||||||
has_default: true
|
|
||||||
docstring: "Base class for chains."
|
|
||||||
decorators:
|
|
||||||
is_interface: false
|
|
||||||
-
|
|
||||||
name: "SimpleChain"
|
|
||||||
bases:
|
|
||||||
- BaseChain
|
|
||||||
methods:
|
|
||||||
-
|
|
||||||
name: "__init__"
|
|
||||||
arguments:
|
|
||||||
-
|
|
||||||
name: "llm"
|
|
||||||
type: "LLMProtocol"
|
|
||||||
is_optional: false
|
|
||||||
has_default: false
|
|
||||||
return_type: "None"
|
|
||||||
docstring: "Initialize the chain."
|
|
||||||
decorators:
|
|
||||||
is_abstract: false
|
|
||||||
-
|
|
||||||
name: "run"
|
|
||||||
arguments:
|
|
||||||
-
|
|
||||||
name: "inputs"
|
|
||||||
type: "dict"
|
|
||||||
is_optional: false
|
|
||||||
has_default: false
|
|
||||||
return_type: "dict"
|
|
||||||
docstring: "Execute the chain logic."
|
|
||||||
decorators:
|
|
||||||
is_abstract: false
|
|
||||||
properties:
|
|
||||||
docstring: "A simple implementation of a chain."
|
|
||||||
decorators:
|
|
||||||
is_interface: false
|
|
46
helpers/tools/converter/test/fixtures/sample.py
vendored
46
helpers/tools/converter/test/fixtures/sample.py
vendored
|
@ -1,46 +0,0 @@
|
||||||
from typing import List, Optional, Protocol
|
|
||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
class LLMProtocol(Protocol):
|
|
||||||
"""Protocol for language models."""
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
async def generate(self, prompts: List[str], **kwargs) -> List[str]:
|
|
||||||
"""Generate completions for the prompts."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
def model_name(self) -> str:
|
|
||||||
"""Get the model name."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
class BaseChain(ABC):
|
|
||||||
"""Base class for chains."""
|
|
||||||
|
|
||||||
memory: Optional[dict] = None
|
|
||||||
verbose: bool = False
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
async def run(self, inputs: dict) -> dict:
|
|
||||||
"""Run the chain on the inputs."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def set_memory(self, memory: dict) -> None:
|
|
||||||
"""Set the memory for the chain."""
|
|
||||||
self.memory = memory
|
|
||||||
|
|
||||||
class SimpleChain(BaseChain):
|
|
||||||
"""A simple implementation of a chain."""
|
|
||||||
|
|
||||||
def __init__(self, llm: LLMProtocol):
|
|
||||||
"""Initialize the chain."""
|
|
||||||
self.llm = llm
|
|
||||||
self.history: List[str] = []
|
|
||||||
|
|
||||||
async def run(self, inputs: dict) -> dict:
|
|
||||||
"""Execute the chain logic."""
|
|
||||||
prompt = inputs.get("prompt", "")
|
|
||||||
result = await self.llm.generate([prompt])
|
|
||||||
self.history.append(result[0])
|
|
||||||
return {"output": result[0]}
|
|
|
@ -1,91 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../tools/python_parser.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('PythonParser', () {
|
|
||||||
test('parses interface correctly', () async {
|
|
||||||
final file = File('test/fixtures/sample.py');
|
|
||||||
final classes = await PythonParser.parseFile(file);
|
|
||||||
|
|
||||||
final interface = classes.firstWhere((c) => c.isInterface);
|
|
||||||
expect(interface.name, equals('LLMProtocol'));
|
|
||||||
expect(interface.docstring, equals('Protocol for language models.'));
|
|
||||||
|
|
||||||
// Test generate method
|
|
||||||
final generateMethod =
|
|
||||||
interface.methods.firstWhere((m) => m.name == 'generate');
|
|
||||||
expect(generateMethod.isAsync, isTrue);
|
|
||||||
expect(generateMethod.isAbstract, isTrue);
|
|
||||||
expect(generateMethod.docstring,
|
|
||||||
equals('Generate completions for the prompts.'));
|
|
||||||
expect(generateMethod.parameters.length, equals(1));
|
|
||||||
expect(generateMethod.parameters.first.name, equals('prompts'));
|
|
||||||
expect(generateMethod.parameters.first.type, equals('List[str]'));
|
|
||||||
expect(generateMethod.returnType, equals('List[str]'));
|
|
||||||
|
|
||||||
// Test model_name property
|
|
||||||
final modelNameMethod =
|
|
||||||
interface.methods.firstWhere((m) => m.name == 'model_name');
|
|
||||||
expect(modelNameMethod.isProperty, isTrue);
|
|
||||||
expect(modelNameMethod.isAbstract, isTrue);
|
|
||||||
expect(modelNameMethod.docstring, equals('Get the model name.'));
|
|
||||||
expect(modelNameMethod.parameters.isEmpty, isTrue);
|
|
||||||
expect(modelNameMethod.returnType, equals('str'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parses abstract class correctly', () async {
|
|
||||||
final file = File('test/fixtures/sample.py');
|
|
||||||
final classes = await PythonParser.parseFile(file);
|
|
||||||
|
|
||||||
final abstractClass = classes.firstWhere((c) => c.name == 'BaseChain');
|
|
||||||
expect(abstractClass.docstring, equals('Base class for chains.'));
|
|
||||||
|
|
||||||
// Test properties
|
|
||||||
expect(abstractClass.properties.length, equals(2));
|
|
||||||
final memoryProp =
|
|
||||||
abstractClass.properties.firstWhere((p) => p.name == 'memory');
|
|
||||||
expect(memoryProp.type, equals('Optional[dict]'));
|
|
||||||
expect(memoryProp.hasDefault, isTrue);
|
|
||||||
|
|
||||||
// Test run method
|
|
||||||
final runMethod =
|
|
||||||
abstractClass.methods.firstWhere((m) => m.name == 'run');
|
|
||||||
expect(runMethod.isAsync, isTrue);
|
|
||||||
expect(runMethod.isAbstract, isTrue);
|
|
||||||
expect(runMethod.docstring, equals('Run the chain on the inputs.'));
|
|
||||||
expect(runMethod.parameters.length, equals(1));
|
|
||||||
expect(runMethod.parameters.first.name, equals('inputs'));
|
|
||||||
expect(runMethod.parameters.first.type, equals('dict'));
|
|
||||||
expect(runMethod.returnType, equals('dict'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('parses concrete class correctly', () async {
|
|
||||||
final file = File('test/fixtures/sample.py');
|
|
||||||
final classes = await PythonParser.parseFile(file);
|
|
||||||
|
|
||||||
final concreteClass = classes.firstWhere((c) => c.name == 'SimpleChain');
|
|
||||||
expect(concreteClass.docstring,
|
|
||||||
equals('A simple implementation of a chain.'));
|
|
||||||
|
|
||||||
// Test constructor
|
|
||||||
final constructor =
|
|
||||||
concreteClass.methods.firstWhere((m) => m.name == '__init__');
|
|
||||||
expect(constructor.docstring, equals('Initialize the chain.'));
|
|
||||||
expect(constructor.parameters.length, equals(1));
|
|
||||||
expect(constructor.parameters.first.name, equals('llm'));
|
|
||||||
expect(constructor.parameters.first.type, equals('LLMProtocol'));
|
|
||||||
|
|
||||||
// Test run method
|
|
||||||
final runMethod =
|
|
||||||
concreteClass.methods.firstWhere((m) => m.name == 'run');
|
|
||||||
expect(runMethod.isAsync, isTrue);
|
|
||||||
expect(runMethod.isAbstract, isFalse);
|
|
||||||
expect(runMethod.docstring, equals('Execute the chain logic.'));
|
|
||||||
expect(runMethod.parameters.length, equals(1));
|
|
||||||
expect(runMethod.parameters.first.name, equals('inputs'));
|
|
||||||
expect(runMethod.parameters.first.type, equals('dict'));
|
|
||||||
expect(runMethod.returnType, equals('dict'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../../lib/src/utils/class_generator_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('ClassGeneratorUtils', () {
|
|
||||||
test('generates constructor with property initialization', () {
|
|
||||||
final properties = [
|
|
||||||
{
|
|
||||||
'name': 'model_name',
|
|
||||||
'type': 'String',
|
|
||||||
'has_default': false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'is_ready',
|
|
||||||
'type': 'bool',
|
|
||||||
'has_default': true,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
final code =
|
|
||||||
ClassGeneratorUtils.generateConstructor('TestClass', properties);
|
|
||||||
expect(code, contains('TestClass({'));
|
|
||||||
expect(code, contains('required String modelName,'));
|
|
||||||
expect(code, contains('bool? isReady,'));
|
|
||||||
expect(code, contains('_modelName = modelName;'));
|
|
||||||
expect(code, contains('_isReady = isReady ?? false;'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('generates properties with getters and setters', () {
|
|
||||||
final properties = [
|
|
||||||
{
|
|
||||||
'name': 'model_name',
|
|
||||||
'type': 'String',
|
|
||||||
'is_readonly': true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'is_ready',
|
|
||||||
'type': 'bool',
|
|
||||||
'is_readonly': false,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
final code = ClassGeneratorUtils.generateProperties(properties);
|
|
||||||
expect(code, contains('late String _modelName;'));
|
|
||||||
expect(code, contains('String get modelName => _modelName;'));
|
|
||||||
expect(code, contains('late bool _isReady;'));
|
|
||||||
expect(code, contains('bool get isReady => _isReady;'));
|
|
||||||
expect(code, contains('set isReady(bool value)'));
|
|
||||||
expect(code, isNot(contains('set modelName')));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('generates async method correctly', () {
|
|
||||||
final method = {
|
|
||||||
'name': 'process_input',
|
|
||||||
'return_type': 'String',
|
|
||||||
'arguments': [
|
|
||||||
{
|
|
||||||
'name': 'input',
|
|
||||||
'type': 'String',
|
|
||||||
'is_optional': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'docstring': 'Process the input.',
|
|
||||||
'is_async': true,
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = ClassGeneratorUtils.generateMethod(method);
|
|
||||||
expect(code, contains('Future<String> processInput('));
|
|
||||||
expect(code, contains('String input'));
|
|
||||||
expect(code, contains('async {'));
|
|
||||||
expect(code, contains('/// Process the input.'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('skips generating constructor method', () {
|
|
||||||
final method = {
|
|
||||||
'name': '__init__',
|
|
||||||
'return_type': 'void',
|
|
||||||
'arguments': [],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = ClassGeneratorUtils.generateMethod(method);
|
|
||||||
expect(code, isEmpty);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../../lib/src/utils/constructor_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('ConstructorUtils', () {
|
|
||||||
test('generates required parameters for non-default properties', () {
|
|
||||||
final properties = [
|
|
||||||
{
|
|
||||||
'name': 'model_name',
|
|
||||||
'type': 'String',
|
|
||||||
'has_default': false,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
final params = ConstructorUtils.generateParameters(properties);
|
|
||||||
expect(params, contains('required String model_name'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('generates optional parameters for default properties', () {
|
|
||||||
final properties = [
|
|
||||||
{
|
|
||||||
'name': 'is_ready',
|
|
||||||
'type': 'bool',
|
|
||||||
'has_default': true,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
final params = ConstructorUtils.generateParameters(properties);
|
|
||||||
expect(params, contains('bool? is_ready'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('generates property initializers', () {
|
|
||||||
final properties = [
|
|
||||||
{
|
|
||||||
'name': 'model_name',
|
|
||||||
'type': 'String',
|
|
||||||
'has_default': false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'is_ready',
|
|
||||||
'type': 'bool',
|
|
||||||
'has_default': true,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
final inits = ConstructorUtils.generateInitializers(properties);
|
|
||||||
expect(inits, contains('_model_name = model_name;'));
|
|
||||||
expect(inits, contains('_is_ready = is_ready ?? false;'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('identifies constructor methods', () {
|
|
||||||
final initMethod = {
|
|
||||||
'name': '__init__',
|
|
||||||
'return_type': 'None',
|
|
||||||
'arguments': [],
|
|
||||||
};
|
|
||||||
|
|
||||||
final regularMethod = {
|
|
||||||
'name': 'process',
|
|
||||||
'return_type': 'String',
|
|
||||||
'arguments': [],
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(ConstructorUtils.isConstructor(initMethod), isTrue);
|
|
||||||
expect(ConstructorUtils.isConstructor(regularMethod), isFalse);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../../lib/src/utils/class_generator_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('Interface Implementation Generation', () {
|
|
||||||
test('generates required BaseChain implementations', () {
|
|
||||||
final bases = ['BaseChain'];
|
|
||||||
final classContract = {
|
|
||||||
'name': 'SimpleChain',
|
|
||||||
'docstring': 'A simple implementation of a chain.',
|
|
||||||
'methods': [
|
|
||||||
{
|
|
||||||
'name': 'run',
|
|
||||||
'return_type': 'dict',
|
|
||||||
'arguments': [
|
|
||||||
{
|
|
||||||
'name': 'inputs',
|
|
||||||
'type': 'dict',
|
|
||||||
'is_optional': false,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'docstring': 'Execute the chain logic.',
|
|
||||||
}
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = ClassGeneratorUtils.generateRequiredImplementations(
|
|
||||||
bases, classContract);
|
|
||||||
|
|
||||||
// Should include memory property
|
|
||||||
expect(code, contains('late Map<String, dynamic>? _memory;'));
|
|
||||||
expect(code, contains('Map<String, dynamic>? get memory => _memory;'));
|
|
||||||
|
|
||||||
// Should include verbose property
|
|
||||||
expect(code, contains('late bool _verbose;'));
|
|
||||||
expect(code, contains('bool get verbose => _verbose;'));
|
|
||||||
|
|
||||||
// Should include constructor with required properties
|
|
||||||
expect(code, contains('SimpleChain({'));
|
|
||||||
expect(code, contains('Map<String, dynamic>? memory,'));
|
|
||||||
expect(code, contains('bool? verbose,'));
|
|
||||||
expect(code, contains('_memory = memory ?? {};'));
|
|
||||||
expect(code, contains('_verbose = verbose ?? false;'));
|
|
||||||
|
|
||||||
// Should include required method implementations
|
|
||||||
expect(code, contains('@override'));
|
|
||||||
expect(code, contains('void setMemory(Map<String, dynamic> memory)'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles multiple interface implementations', () {
|
|
||||||
final bases = ['BaseChain', 'Serializable'];
|
|
||||||
final classContract = {
|
|
||||||
'name': 'SimpleChain',
|
|
||||||
'docstring': 'A simple implementation of a chain.',
|
|
||||||
'methods': [],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = ClassGeneratorUtils.generateRequiredImplementations(
|
|
||||||
bases, classContract);
|
|
||||||
|
|
||||||
// Should include BaseChain implementations
|
|
||||||
expect(code, contains('Map<String, dynamic>? get memory'));
|
|
||||||
expect(code, contains('bool get verbose'));
|
|
||||||
|
|
||||||
// Should include constructor with all required properties
|
|
||||||
expect(code, contains('SimpleChain({'));
|
|
||||||
expect(code, contains('Map<String, dynamic>? memory,'));
|
|
||||||
expect(code, contains('bool? verbose,'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles no interface implementations', () {
|
|
||||||
final bases = <String>[];
|
|
||||||
final classContract = {
|
|
||||||
'name': 'SimpleClass',
|
|
||||||
'docstring': 'A simple class.',
|
|
||||||
'methods': [],
|
|
||||||
};
|
|
||||||
|
|
||||||
final code = ClassGeneratorUtils.generateRequiredImplementations(
|
|
||||||
bases, classContract);
|
|
||||||
expect(code, isEmpty);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../../lib/src/utils/name_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('NameUtils', () {
|
|
||||||
test('converts snake_case to camelCase', () {
|
|
||||||
expect(NameUtils.toDartName('hello_world'), equals('helloWorld'));
|
|
||||||
expect(NameUtils.toDartName('get_model_name'), equals('getModelName'));
|
|
||||||
expect(NameUtils.toDartName('set_memory'), equals('setMemory'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles single word correctly', () {
|
|
||||||
expect(NameUtils.toDartName('hello'), equals('hello'));
|
|
||||||
expect(NameUtils.toDartName('test'), equals('test'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('preserves existing camelCase', () {
|
|
||||||
expect(NameUtils.toDartName('helloWorld'), equals('helloWorld'));
|
|
||||||
expect(NameUtils.toDartName('getModelName'), equals('getModelName'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles empty string', () {
|
|
||||||
expect(NameUtils.toDartName(''), equals(''));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles special method names', () {
|
|
||||||
expect(NameUtils.toDartName('__init__'), equals('new'));
|
|
||||||
expect(NameUtils.toDartName('__str__'), equals('str'));
|
|
||||||
expect(NameUtils.toDartName('__repr__'), equals('repr'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles consecutive underscores', () {
|
|
||||||
expect(NameUtils.toDartName('hello__world'), equals('helloWorld'));
|
|
||||||
expect(NameUtils.toDartName('test___name'), equals('testName'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../../lib/src/utils/type_conversion_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('TypeConversionUtils', () {
|
|
||||||
group('pythonToDartType', () {
|
|
||||||
test('converts basic Python types to Dart types', () {
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('str'), equals('String'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('int'), equals('int'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('bool'), equals('bool'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('None'), equals('void'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('dict'),
|
|
||||||
equals('Map<String, dynamic>'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('converts List types correctly', () {
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('List[str]'),
|
|
||||||
equals('List<String>'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('List[int]'),
|
|
||||||
equals('List<int>'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('List[dict]'),
|
|
||||||
equals('List<Map<String, dynamic>>'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('converts Dict types correctly', () {
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('Dict[str, Any]'),
|
|
||||||
equals('Map<String, dynamic>'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('Dict[str, int]'),
|
|
||||||
equals('Map<String, int>'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('dict'),
|
|
||||||
equals('Map<String, dynamic>'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('converts Optional types correctly', () {
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('Optional[str]'),
|
|
||||||
equals('String?'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('Optional[int]'),
|
|
||||||
equals('int?'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('Optional[dict]'),
|
|
||||||
equals('Map<String, dynamic>?'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('Optional[List[str]]'),
|
|
||||||
equals('List<String>?'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles nested generic types', () {
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('List[Optional[str]]'),
|
|
||||||
equals('List<String?>'));
|
|
||||||
expect(TypeConversionUtils.pythonToDartType('Dict[str, List[int]]'),
|
|
||||||
equals('Map<String, List<int>>'));
|
|
||||||
expect(
|
|
||||||
TypeConversionUtils.pythonToDartType(
|
|
||||||
'Optional[Dict[str, List[int]]]'),
|
|
||||||
equals('Map<String, List<int>>?'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
group('getDefaultValue', () {
|
|
||||||
test('returns correct default values for basic types', () {
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('bool'), equals('false'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('int'), equals('0'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('double'), equals('0.0'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('String'), equals("''"));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns correct default values for nullable types', () {
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('bool?'), equals('false'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('int?'), equals('0'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('double?'), equals('0.0'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('String?'), equals("''"));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns correct default values for collection types', () {
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('List'), equals('[]'));
|
|
||||||
expect(
|
|
||||||
TypeConversionUtils.getDefaultValue('List<String>'), equals('[]'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('Map<String, dynamic>'),
|
|
||||||
equals('{}'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('Map<String, int>'),
|
|
||||||
equals('{}'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns null for unknown types', () {
|
|
||||||
expect(
|
|
||||||
TypeConversionUtils.getDefaultValue('CustomType'), equals('null'));
|
|
||||||
expect(TypeConversionUtils.getDefaultValue('UnknownType?'),
|
|
||||||
equals('null'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import '../../lib/src/utils/type_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('TypeUtils', () {
|
|
||||||
test('castToMapList handles null input', () {
|
|
||||||
expect(TypeUtils.castToMapList(null), isEmpty);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('castToMapList converts List<dynamic> to List<Map<String, dynamic>>',
|
|
||||||
() {
|
|
||||||
final input = [
|
|
||||||
{'name': 'test', 'value': 1},
|
|
||||||
{'type': 'string', 'optional': true}
|
|
||||||
];
|
|
||||||
final result = TypeUtils.castToMapList(input);
|
|
||||||
expect(result, isA<List<Map<String, dynamic>>>());
|
|
||||||
expect(result.first['name'], equals('test'));
|
|
||||||
expect(result.last['type'], equals('string'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('castToMap handles null input', () {
|
|
||||||
expect(TypeUtils.castToMap(null), isEmpty);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('castToMap converts dynamic to Map<String, dynamic>', () {
|
|
||||||
final input = {'name': 'test', 'value': 1};
|
|
||||||
final result = TypeUtils.castToMap(input);
|
|
||||||
expect(result, isA<Map<String, dynamic>>());
|
|
||||||
expect(result['name'], equals('test'));
|
|
||||||
expect(result['value'], equals(1));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('castToStringList handles null input', () {
|
|
||||||
expect(TypeUtils.castToStringList(null), isEmpty);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('castToStringList converts List<dynamic> to List<String>', () {
|
|
||||||
final input = ['test', 1, true];
|
|
||||||
final result = TypeUtils.castToStringList(input);
|
|
||||||
expect(result, isA<List<String>>());
|
|
||||||
expect(result, equals(['test', '1', 'true']));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import 'package:yaml/yaml.dart';
|
|
||||||
import '../lib/src/utils/yaml_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('YamlUtils', () {
|
|
||||||
test('converts simple YAML to Map correctly', () {
|
|
||||||
final yamlStr = '''
|
|
||||||
interfaces:
|
|
||||||
- name: TestInterface
|
|
||||||
methods:
|
|
||||||
- name: testMethod
|
|
||||||
arguments:
|
|
||||||
- name: arg1
|
|
||||||
type: str
|
|
||||||
return_type: str
|
|
||||||
''';
|
|
||||||
|
|
||||||
final yaml = loadYaml(yamlStr) as YamlMap;
|
|
||||||
final map = YamlUtils.convertYamlToMap(yaml);
|
|
||||||
|
|
||||||
expect(map, isA<Map<String, dynamic>>());
|
|
||||||
expect(map['interfaces'], isA<List>());
|
|
||||||
expect(map['interfaces'][0]['name'], equals('TestInterface'));
|
|
||||||
expect(map['interfaces'][0]['methods'][0]['arguments'][0]['type'],
|
|
||||||
equals('str'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('handles nested YAML structures', () {
|
|
||||||
final yamlStr = '''
|
|
||||||
interfaces:
|
|
||||||
- name: TestInterface
|
|
||||||
properties:
|
|
||||||
- name: prop1
|
|
||||||
type: List[str]
|
|
||||||
has_default: true
|
|
||||||
methods:
|
|
||||||
- name: testMethod
|
|
||||||
arguments:
|
|
||||||
- name: arg1
|
|
||||||
type: Dict[str, Any]
|
|
||||||
is_optional: true
|
|
||||||
return_type: Optional[int]
|
|
||||||
''';
|
|
||||||
|
|
||||||
final yaml = loadYaml(yamlStr) as YamlMap;
|
|
||||||
final map = YamlUtils.convertYamlToMap(yaml);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
map['interfaces'][0]['properties'][0]['type'], equals('List[str]'));
|
|
||||||
expect(map['interfaces'][0]['methods'][0]['arguments'][0]['type'],
|
|
||||||
equals('Dict[str, Any]'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test('converts actual contract YAML correctly', () {
|
|
||||||
final yamlStr = '''
|
|
||||||
interfaces:
|
|
||||||
- name: LLMProtocol
|
|
||||||
bases:
|
|
||||||
- Protocol
|
|
||||||
methods:
|
|
||||||
- name: generate
|
|
||||||
arguments:
|
|
||||||
- name: prompts
|
|
||||||
type: List[str]
|
|
||||||
is_optional: false
|
|
||||||
has_default: false
|
|
||||||
return_type: List[str]
|
|
||||||
docstring: Generate completions for the prompts.
|
|
||||||
decorators:
|
|
||||||
- name: abstractmethod
|
|
||||||
is_abstract: true
|
|
||||||
properties: []
|
|
||||||
docstring: Protocol for language models.
|
|
||||||
is_interface: true
|
|
||||||
''';
|
|
||||||
|
|
||||||
final yaml = loadYaml(yamlStr) as YamlMap;
|
|
||||||
final map = YamlUtils.convertYamlToMap(yaml);
|
|
||||||
|
|
||||||
expect(map['interfaces'][0]['name'], equals('LLMProtocol'));
|
|
||||||
expect(map['interfaces'][0]['bases'][0], equals('Protocol'));
|
|
||||||
expect(map['interfaces'][0]['methods'][0]['name'], equals('generate'));
|
|
||||||
expect(map['interfaces'][0]['methods'][0]['arguments'][0]['type'],
|
|
||||||
equals('List[str]'));
|
|
||||||
expect(map['interfaces'][0]['docstring'],
|
|
||||||
equals('Protocol for language models.'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
import 'package:test/test.dart';
|
|
||||||
import 'package:yaml/yaml.dart';
|
|
||||||
import '../lib/src/utils/yaml_utils.dart';
|
|
||||||
import '../lib/src/utils/type_utils.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group('YAML Type Casting', () {
|
|
||||||
test('converts YAML data to properly typed maps and lists', () {
|
|
||||||
final yamlStr = '''
|
|
||||||
classes:
|
|
||||||
- name: TestClass
|
|
||||||
properties:
|
|
||||||
- name: model_name
|
|
||||||
type: String
|
|
||||||
has_default: false
|
|
||||||
- name: is_ready
|
|
||||||
type: bool
|
|
||||||
has_default: true
|
|
||||||
methods:
|
|
||||||
- name: process
|
|
||||||
return_type: String
|
|
||||||
arguments:
|
|
||||||
- name: input
|
|
||||||
type: String
|
|
||||||
is_optional: false
|
|
||||||
''';
|
|
||||||
|
|
||||||
final yamlDoc = loadYaml(yamlStr) as YamlMap;
|
|
||||||
final data = YamlUtils.convertYamlToMap(yamlDoc);
|
|
||||||
|
|
||||||
final classes = data['classes'] as List;
|
|
||||||
final firstClass = classes.first as Map<String, dynamic>;
|
|
||||||
|
|
||||||
// Test properties casting
|
|
||||||
final properties =
|
|
||||||
TypeUtils.castToMapList(firstClass['properties'] as List?);
|
|
||||||
expect(properties, isA<List<Map<String, dynamic>>>());
|
|
||||||
expect(properties.first['name'], equals('model_name'));
|
|
||||||
expect(properties.first['type'], equals('String'));
|
|
||||||
expect(properties.first['has_default'], isFalse);
|
|
||||||
|
|
||||||
// Test methods casting
|
|
||||||
final methods = TypeUtils.castToMapList(firstClass['methods'] as List?);
|
|
||||||
expect(methods, isA<List<Map<String, dynamic>>>());
|
|
||||||
expect(methods.first['name'], equals('process'));
|
|
||||||
expect(methods.first['return_type'], equals('String'));
|
|
||||||
|
|
||||||
// Test nested arguments casting
|
|
||||||
final arguments =
|
|
||||||
TypeUtils.castToMapList(methods.first['arguments'] as List?);
|
|
||||||
expect(arguments, isA<List<Map<String, dynamic>>>());
|
|
||||||
expect(arguments.first['name'], equals('input'));
|
|
||||||
expect(arguments.first['type'], equals('String'));
|
|
||||||
expect(arguments.first['is_optional'], isFalse);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,255 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:args/args.dart';
|
|
||||||
import 'python_parser.dart';
|
|
||||||
|
|
||||||
/// Represents a Python class or interface contract
|
|
||||||
class ContractDefinition {
|
|
||||||
final String name;
|
|
||||||
final List<String> bases;
|
|
||||||
final List<MethodDefinition> methods;
|
|
||||||
final List<PropertyDefinition> properties;
|
|
||||||
final String? docstring;
|
|
||||||
final List<Map<String, dynamic>> decorators;
|
|
||||||
final bool isInterface;
|
|
||||||
|
|
||||||
ContractDefinition({
|
|
||||||
required this.name,
|
|
||||||
required this.bases,
|
|
||||||
required this.methods,
|
|
||||||
required this.properties,
|
|
||||||
this.docstring,
|
|
||||||
required this.decorators,
|
|
||||||
required this.isInterface,
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'name': name,
|
|
||||||
'bases': bases,
|
|
||||||
'methods': methods.map((m) => m.toJson()).toList(),
|
|
||||||
'properties': properties.map((p) => p.toJson()).toList(),
|
|
||||||
if (docstring != null) 'docstring': docstring,
|
|
||||||
'decorators': decorators,
|
|
||||||
'is_interface': isInterface,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Create ContractDefinition from PythonClass
|
|
||||||
factory ContractDefinition.fromPythonClass(PythonClass pythonClass) {
|
|
||||||
return ContractDefinition(
|
|
||||||
name: pythonClass.name,
|
|
||||||
bases: pythonClass.bases,
|
|
||||||
methods: pythonClass.methods
|
|
||||||
.map((m) => MethodDefinition(
|
|
||||||
name: m.name,
|
|
||||||
arguments: m.parameters
|
|
||||||
.map((p) => ArgumentDefinition(
|
|
||||||
name: p.name,
|
|
||||||
type: p.type,
|
|
||||||
isOptional: p.isOptional,
|
|
||||||
hasDefault: p.hasDefault,
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
returnType: m.returnType,
|
|
||||||
docstring: m.docstring,
|
|
||||||
decorators: m.decorators.map((d) => {'name': d}).toList(),
|
|
||||||
isAbstract: m.isAbstract,
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
properties: pythonClass.properties
|
|
||||||
.map((p) => PropertyDefinition(
|
|
||||||
name: p.name,
|
|
||||||
type: p.type,
|
|
||||||
hasDefault: p.hasDefault,
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
docstring: pythonClass.docstring,
|
|
||||||
decorators: pythonClass.decorators.map((d) => {'name': d}).toList(),
|
|
||||||
isInterface: pythonClass.isInterface,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a method in a contract
|
|
||||||
class MethodDefinition {
|
|
||||||
final String name;
|
|
||||||
final List<ArgumentDefinition> arguments;
|
|
||||||
final String returnType;
|
|
||||||
final String? docstring;
|
|
||||||
final List<Map<String, dynamic>> decorators;
|
|
||||||
final bool isAbstract;
|
|
||||||
|
|
||||||
MethodDefinition({
|
|
||||||
required this.name,
|
|
||||||
required this.arguments,
|
|
||||||
required this.returnType,
|
|
||||||
this.docstring,
|
|
||||||
required this.decorators,
|
|
||||||
required this.isAbstract,
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'name': name,
|
|
||||||
'arguments': arguments.map((a) => a.toJson()).toList(),
|
|
||||||
'return_type': returnType,
|
|
||||||
if (docstring != null) 'docstring': docstring,
|
|
||||||
'decorators': decorators,
|
|
||||||
'is_abstract': isAbstract,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a method argument
|
|
||||||
class ArgumentDefinition {
|
|
||||||
final String name;
|
|
||||||
final String type;
|
|
||||||
final bool isOptional;
|
|
||||||
final bool hasDefault;
|
|
||||||
|
|
||||||
ArgumentDefinition({
|
|
||||||
required this.name,
|
|
||||||
required this.type,
|
|
||||||
required this.isOptional,
|
|
||||||
required this.hasDefault,
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'name': name,
|
|
||||||
'type': type,
|
|
||||||
'is_optional': isOptional,
|
|
||||||
'has_default': hasDefault,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a class property
|
|
||||||
class PropertyDefinition {
|
|
||||||
final String name;
|
|
||||||
final String type;
|
|
||||||
final bool hasDefault;
|
|
||||||
|
|
||||||
PropertyDefinition({
|
|
||||||
required this.name,
|
|
||||||
required this.type,
|
|
||||||
required this.hasDefault,
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'name': name,
|
|
||||||
'type': type,
|
|
||||||
'has_default': hasDefault,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Main contract extractor class
|
|
||||||
class ContractExtractor {
|
|
||||||
final List<ContractDefinition> interfaces = [];
|
|
||||||
final List<ContractDefinition> classes = [];
|
|
||||||
|
|
||||||
/// Process a Python source file and extract contracts
|
|
||||||
Future<void> processFile(File file) async {
|
|
||||||
try {
|
|
||||||
final pythonClasses = await PythonParser.parseFile(file);
|
|
||||||
|
|
||||||
for (final pythonClass in pythonClasses) {
|
|
||||||
final contract = ContractDefinition.fromPythonClass(pythonClass);
|
|
||||||
if (pythonClass.isInterface) {
|
|
||||||
interfaces.add(contract);
|
|
||||||
} else {
|
|
||||||
classes.add(contract);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
print('Error processing file ${file.path}: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process all Python files in a directory recursively
|
|
||||||
Future<void> processDirectory(String dirPath) async {
|
|
||||||
final dir = Directory(dirPath);
|
|
||||||
await for (final entity in dir.list(recursive: true)) {
|
|
||||||
if (entity is File && entity.path.endsWith('.py')) {
|
|
||||||
await processFile(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate YAML output
|
|
||||||
Future<void> generateYaml(String outputPath) async {
|
|
||||||
final output = {
|
|
||||||
'interfaces': interfaces.map((i) => i.toJson()).toList(),
|
|
||||||
'classes': classes.map((c) => c.toJson()).toList(),
|
|
||||||
};
|
|
||||||
|
|
||||||
final yamlString = mapToYaml(output);
|
|
||||||
final file = File(outputPath);
|
|
||||||
await file.writeAsString(yamlString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a Map to YAML string with proper formatting
|
|
||||||
String mapToYaml(Map<String, dynamic> map, {int indent = 0}) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
final indentStr = ' ' * indent;
|
|
||||||
|
|
||||||
map.forEach((key, value) {
|
|
||||||
if (value is Map) {
|
|
||||||
buffer.writeln('$indentStr$key:');
|
|
||||||
buffer
|
|
||||||
.write(mapToYaml(value as Map<String, dynamic>, indent: indent + 2));
|
|
||||||
} else if (value is List) {
|
|
||||||
buffer.writeln('$indentStr$key:');
|
|
||||||
for (var item in value) {
|
|
||||||
if (item is Map) {
|
|
||||||
buffer.writeln('$indentStr- ');
|
|
||||||
buffer.write(
|
|
||||||
mapToYaml(item as Map<String, dynamic>, indent: indent + 4));
|
|
||||||
} else {
|
|
||||||
buffer.writeln('$indentStr- $item');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (value == null) {
|
|
||||||
buffer.writeln('$indentStr$key: null');
|
|
||||||
} else if (value is String) {
|
|
||||||
// Handle multi-line strings
|
|
||||||
if (value.contains('\n')) {
|
|
||||||
buffer.writeln('$indentStr$key: |');
|
|
||||||
value.split('\n').forEach((line) {
|
|
||||||
buffer.writeln('$indentStr $line');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
buffer.writeln('$indentStr$key: "$value"');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buffer.writeln('$indentStr$key: $value');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(List<String> arguments) async {
|
|
||||||
final parser = ArgParser()
|
|
||||||
..addOption('source',
|
|
||||||
abbr: 's',
|
|
||||||
help: 'Source directory containing Python LangChain implementation',
|
|
||||||
mandatory: true)
|
|
||||||
..addOption('output',
|
|
||||||
abbr: 'o', help: 'Output YAML file path', mandatory: true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
final results = parser.parse(arguments);
|
|
||||||
final sourceDir = results['source'] as String;
|
|
||||||
final outputFile = results['output'] as String;
|
|
||||||
|
|
||||||
final extractor = ContractExtractor();
|
|
||||||
await extractor.processDirectory(sourceDir);
|
|
||||||
await extractor.generateYaml(outputFile);
|
|
||||||
|
|
||||||
print('Contract extraction completed successfully.');
|
|
||||||
print('Interfaces found: ${extractor.interfaces.length}');
|
|
||||||
print('Classes found: ${extractor.classes.length}');
|
|
||||||
} catch (e) {
|
|
||||||
print('Error: $e');
|
|
||||||
print('Usage: dart extract_contracts.dart --source <dir> --output <file>');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,209 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:yaml/yaml.dart';
|
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
import 'package:args/args.dart';
|
|
||||||
import 'package:converter/src/utils/yaml_utils.dart';
|
|
||||||
import 'package:converter/src/utils/name_utils.dart';
|
|
||||||
import 'package:converter/src/utils/class_generator_utils.dart';
|
|
||||||
import 'package:converter/src/utils/type_utils.dart';
|
|
||||||
import 'package:converter/src/utils/type_conversion_utils.dart';
|
|
||||||
|
|
||||||
/// Generates a Dart interface from a contract
|
|
||||||
String generateInterface(Map<String, dynamic> interface) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
final name = interface['name'] as String;
|
|
||||||
final docstring = interface['docstring'] as String?;
|
|
||||||
|
|
||||||
// Add documentation
|
|
||||||
if (docstring != null) {
|
|
||||||
buffer.writeln('/// ${docstring.replaceAll('\n', '\n/// ')}');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Begin interface definition
|
|
||||||
buffer.writeln('abstract class $name {');
|
|
||||||
|
|
||||||
// Generate properties
|
|
||||||
final properties = interface['properties'] as List?;
|
|
||||||
if (properties != null) {
|
|
||||||
for (final prop in properties) {
|
|
||||||
final propName = NameUtils.toDartName(prop['name'] as String);
|
|
||||||
final propType =
|
|
||||||
TypeConversionUtils.pythonToDartType(prop['type'] as String);
|
|
||||||
buffer.writeln(' $propType get $propName;');
|
|
||||||
// Only generate setter if is_readonly is explicitly false
|
|
||||||
final isReadonly = prop['is_readonly'];
|
|
||||||
if (isReadonly != null && !isReadonly) {
|
|
||||||
buffer.writeln(' set $propName($propType value);');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (properties.isNotEmpty) buffer.writeln();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate methods
|
|
||||||
final methods = interface['methods'] as List?;
|
|
||||||
if (methods != null) {
|
|
||||||
for (final method in methods) {
|
|
||||||
final methodName = NameUtils.toDartName(method['name'] as String);
|
|
||||||
final returnType =
|
|
||||||
TypeConversionUtils.pythonToDartType(method['return_type'] as String);
|
|
||||||
final methodDoc = method['docstring'] as String?;
|
|
||||||
final decorators = TypeUtils.castToMapList(method['decorators'] as List?);
|
|
||||||
final isProperty = decorators.any((d) => d['name'] == 'property');
|
|
||||||
|
|
||||||
if (methodDoc != null) {
|
|
||||||
buffer.writeln(' /// ${methodDoc.replaceAll('\n', '\n /// ')}');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isProperty) {
|
|
||||||
// Generate as a getter
|
|
||||||
buffer.writeln(' $returnType get $methodName;');
|
|
||||||
} else {
|
|
||||||
// Generate as a method
|
|
||||||
final isAsync = method['is_async'] == true;
|
|
||||||
if (isAsync) {
|
|
||||||
buffer.write(' Future<$returnType> $methodName(');
|
|
||||||
} else {
|
|
||||||
buffer.write(' $returnType $methodName(');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate parameters
|
|
||||||
final params = method['arguments'] as List?;
|
|
||||||
if (params != null && params.isNotEmpty) {
|
|
||||||
final paramStrings = <String>[];
|
|
||||||
|
|
||||||
for (final param in params) {
|
|
||||||
final paramName = NameUtils.toDartName(param['name'] as String);
|
|
||||||
final paramType =
|
|
||||||
TypeConversionUtils.pythonToDartType(param['type'] as String);
|
|
||||||
final isOptional = param['is_optional'] == true;
|
|
||||||
|
|
||||||
if (isOptional) {
|
|
||||||
paramStrings.add('[$paramType $paramName]');
|
|
||||||
} else {
|
|
||||||
paramStrings.add('$paramType $paramName');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.write(paramStrings.join(', '));
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.writeln(');');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.writeln('}');
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates a Dart class implementation from a contract
|
|
||||||
String generateClass(Map<String, dynamic> classContract) {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
final name = classContract['name'] as String;
|
|
||||||
final bases = TypeUtils.castToStringList(classContract['bases'] as List?);
|
|
||||||
final docstring = classContract['docstring'] as String?;
|
|
||||||
|
|
||||||
// Add documentation
|
|
||||||
if (docstring != null) {
|
|
||||||
buffer.writeln('/// ${docstring.replaceAll('\n', '\n/// ')}');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Begin class definition
|
|
||||||
buffer.write('class $name');
|
|
||||||
if (bases.isNotEmpty) {
|
|
||||||
final implementsStr = bases.join(', ');
|
|
||||||
buffer.write(' implements $implementsStr');
|
|
||||||
}
|
|
||||||
buffer.writeln(' {');
|
|
||||||
|
|
||||||
// Generate required interface implementations first
|
|
||||||
if (bases.contains('BaseChain')) {
|
|
||||||
buffer.write(ClassGeneratorUtils.generateRequiredImplementations(
|
|
||||||
bases, classContract));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate properties from contract properties
|
|
||||||
final properties =
|
|
||||||
TypeUtils.castToMapList(classContract['properties'] as List?);
|
|
||||||
if (properties.isNotEmpty) {
|
|
||||||
buffer.write(ClassGeneratorUtils.generateProperties(properties));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate constructor
|
|
||||||
if (properties.isNotEmpty || bases.contains('BaseChain')) {
|
|
||||||
buffer.write(ClassGeneratorUtils.generateConstructor(name, properties));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate additional methods
|
|
||||||
final methods = TypeUtils.castToMapList(classContract['methods'] as List?);
|
|
||||||
if (methods.isNotEmpty) {
|
|
||||||
for (final method in methods) {
|
|
||||||
if (method['name'] != '__init__') {
|
|
||||||
buffer.write(ClassGeneratorUtils.generateMethod(method));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.writeln('}');
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Main code generator class
|
|
||||||
class DartCodeGenerator {
|
|
||||||
final String outputDir;
|
|
||||||
|
|
||||||
DartCodeGenerator(this.outputDir);
|
|
||||||
|
|
||||||
Future<void> generateFromYaml(String yamlPath) async {
|
|
||||||
final file = File(yamlPath);
|
|
||||||
final content = await file.readAsString();
|
|
||||||
final yamlDoc = loadYaml(content) as YamlMap;
|
|
||||||
final contracts = YamlUtils.convertYamlToMap(yamlDoc);
|
|
||||||
|
|
||||||
// Generate interfaces
|
|
||||||
for (final interface in contracts['interfaces'] ?? []) {
|
|
||||||
final code = generateInterface(interface as Map<String, dynamic>);
|
|
||||||
final fileName = '${interface['name'].toString().toLowerCase()}.dart';
|
|
||||||
final outputFile =
|
|
||||||
File(path.join(outputDir, 'lib', 'src', 'interfaces', fileName));
|
|
||||||
await outputFile.create(recursive: true);
|
|
||||||
await outputFile.writeAsString(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate classes
|
|
||||||
for (final classContract in contracts['classes'] ?? []) {
|
|
||||||
final code = generateClass(classContract as Map<String, dynamic>);
|
|
||||||
final fileName = '${classContract['name'].toString().toLowerCase()}.dart';
|
|
||||||
final outputFile =
|
|
||||||
File(path.join(outputDir, 'lib', 'src', 'implementations', fileName));
|
|
||||||
await outputFile.create(recursive: true);
|
|
||||||
await outputFile.writeAsString(code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(List<String> arguments) async {
|
|
||||||
final parser = ArgParser()
|
|
||||||
..addOption('contracts',
|
|
||||||
abbr: 'c', help: 'Path to the YAML contracts file', mandatory: true)
|
|
||||||
..addOption('output',
|
|
||||||
abbr: 'o',
|
|
||||||
help: 'Output directory for generated Dart code',
|
|
||||||
mandatory: true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
final results = parser.parse(arguments);
|
|
||||||
final contractsFile = results['contracts'] as String;
|
|
||||||
final outputDir = results['output'] as String;
|
|
||||||
|
|
||||||
final generator = DartCodeGenerator(outputDir);
|
|
||||||
await generator.generateFromYaml(contractsFile);
|
|
||||||
|
|
||||||
print('Code generation completed successfully.');
|
|
||||||
} catch (e) {
|
|
||||||
print('Error: $e');
|
|
||||||
print(
|
|
||||||
'Usage: dart generate_dart_code.dart --contracts <file> --output <dir>');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,443 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
/// Represents a Python method parameter
|
|
||||||
class Parameter {
|
|
||||||
final String name;
|
|
||||||
final String type;
|
|
||||||
final bool isOptional;
|
|
||||||
final bool hasDefault;
|
|
||||||
|
|
||||||
Parameter({
|
|
||||||
required this.name,
|
|
||||||
required this.type,
|
|
||||||
required this.isOptional,
|
|
||||||
required this.hasDefault,
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'name': name,
|
|
||||||
'type': type,
|
|
||||||
'is_optional': isOptional,
|
|
||||||
'has_default': hasDefault,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a Python method
|
|
||||||
class Method {
|
|
||||||
final String name;
|
|
||||||
final List<Parameter> parameters;
|
|
||||||
final String returnType;
|
|
||||||
final String? docstring;
|
|
||||||
final List<String> decorators;
|
|
||||||
final bool isAsync;
|
|
||||||
final bool isAbstract;
|
|
||||||
final bool isProperty;
|
|
||||||
|
|
||||||
Method({
|
|
||||||
required this.name,
|
|
||||||
required this.parameters,
|
|
||||||
required this.returnType,
|
|
||||||
this.docstring,
|
|
||||||
required this.decorators,
|
|
||||||
required this.isAsync,
|
|
||||||
required this.isAbstract,
|
|
||||||
required this.isProperty,
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'name': name,
|
|
||||||
'parameters': parameters.map((p) => p.toJson()).toList(),
|
|
||||||
'return_type': returnType,
|
|
||||||
if (docstring != null) 'docstring': docstring,
|
|
||||||
'decorators': decorators,
|
|
||||||
'is_async': isAsync,
|
|
||||||
'is_abstract': isAbstract,
|
|
||||||
'is_property': isProperty,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a Python class property
|
|
||||||
class Property {
|
|
||||||
final String name;
|
|
||||||
final String type;
|
|
||||||
final bool hasDefault;
|
|
||||||
final String? defaultValue;
|
|
||||||
|
|
||||||
Property({
|
|
||||||
required this.name,
|
|
||||||
required this.type,
|
|
||||||
required this.hasDefault,
|
|
||||||
this.defaultValue,
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'name': name,
|
|
||||||
'type': type,
|
|
||||||
'has_default': hasDefault,
|
|
||||||
if (defaultValue != null) 'default_value': defaultValue,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a Python class
|
|
||||||
class PythonClass {
|
|
||||||
final String name;
|
|
||||||
final List<String> bases;
|
|
||||||
final List<Method> methods;
|
|
||||||
final List<Property> properties;
|
|
||||||
final String? docstring;
|
|
||||||
final List<String> decorators;
|
|
||||||
final bool isInterface;
|
|
||||||
|
|
||||||
PythonClass({
|
|
||||||
required this.name,
|
|
||||||
required this.bases,
|
|
||||||
required this.methods,
|
|
||||||
required this.properties,
|
|
||||||
this.docstring,
|
|
||||||
required this.decorators,
|
|
||||||
required this.isInterface,
|
|
||||||
});
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
|
||||||
'name': name,
|
|
||||||
'bases': bases,
|
|
||||||
'methods': methods.map((m) => m.toJson()).toList(),
|
|
||||||
'properties': properties.map((p) => p.toJson()).toList(),
|
|
||||||
if (docstring != null) 'docstring': docstring,
|
|
||||||
'decorators': decorators,
|
|
||||||
'is_interface': isInterface,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parser for Python source code
|
|
||||||
class PythonParser {
|
|
||||||
/// Check if a line looks like code
|
|
||||||
static bool _isCodeLine(String line) {
|
|
||||||
return line.startsWith('def ') ||
|
|
||||||
line.startsWith('@') ||
|
|
||||||
line.startsWith('class ') ||
|
|
||||||
line.contains(' = ') ||
|
|
||||||
line.contains('self.') ||
|
|
||||||
line.contains('return ') ||
|
|
||||||
line.contains('pass') ||
|
|
||||||
line.contains('raise ') ||
|
|
||||||
line.contains('yield ') ||
|
|
||||||
line.contains('async ') ||
|
|
||||||
line.contains('await ') ||
|
|
||||||
(line.contains(':') && !line.startsWith('Note:')) ||
|
|
||||||
line.trim().startsWith('"""') ||
|
|
||||||
line.trim().endsWith('"""');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a docstring from Python code lines
|
|
||||||
static String? _parseDocstring(
|
|
||||||
List<String> lines, int startIndex, int baseIndent) {
|
|
||||||
if (startIndex >= lines.length) return null;
|
|
||||||
|
|
||||||
final line = lines[startIndex].trim();
|
|
||||||
if (!line.startsWith('"""')) return null;
|
|
||||||
|
|
||||||
// Handle single-line docstring
|
|
||||||
if (line.endsWith('"""') && line.length > 6) {
|
|
||||||
return line.substring(3, line.length - 3).trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
final docLines = <String>[];
|
|
||||||
// Add first line content if it exists after the opening quotes
|
|
||||||
var firstLineContent = line.substring(3).trim();
|
|
||||||
if (firstLineContent.isNotEmpty && !_isCodeLine(firstLineContent)) {
|
|
||||||
docLines.add(firstLineContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = startIndex + 1;
|
|
||||||
while (i < lines.length) {
|
|
||||||
final currentLine = lines[i].trim();
|
|
||||||
|
|
||||||
// Stop at closing quotes
|
|
||||||
if (currentLine.endsWith('"""')) {
|
|
||||||
// Add the last line content if it exists before the closing quotes
|
|
||||||
var lastLineContent =
|
|
||||||
currentLine.substring(0, currentLine.length - 3).trim();
|
|
||||||
if (lastLineContent.isNotEmpty && !_isCodeLine(lastLineContent)) {
|
|
||||||
docLines.add(lastLineContent);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only add non-code lines
|
|
||||||
if (currentLine.isNotEmpty && !_isCodeLine(currentLine)) {
|
|
||||||
docLines.add(currentLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return docLines.isEmpty ? null : docLines.join('\n').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the indentation level of a line
|
|
||||||
static int _getIndentation(String line) {
|
|
||||||
return line.length - line.trimLeft().length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse method parameters from a parameter string
|
|
||||||
static List<Parameter> _parseParameters(String paramsStr) {
|
|
||||||
if (paramsStr.trim().isEmpty) return [];
|
|
||||||
|
|
||||||
final params = <Parameter>[];
|
|
||||||
var depth = 0;
|
|
||||||
var currentParam = StringBuffer();
|
|
||||||
|
|
||||||
// Handle nested brackets in parameter types
|
|
||||||
for (var i = 0; i < paramsStr.length; i++) {
|
|
||||||
final char = paramsStr[i];
|
|
||||||
if (char == '[') depth++;
|
|
||||||
if (char == ']') depth--;
|
|
||||||
if (char == ',' && depth == 0) {
|
|
||||||
final param = currentParam.toString().trim();
|
|
||||||
if (param.isNotEmpty && param != 'self' && !param.startsWith('**')) {
|
|
||||||
final paramObj = _parseParameter(param);
|
|
||||||
if (paramObj != null) {
|
|
||||||
params.add(paramObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentParam.clear();
|
|
||||||
} else {
|
|
||||||
currentParam.write(char);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final lastParam = currentParam.toString().trim();
|
|
||||||
if (lastParam.isNotEmpty &&
|
|
||||||
lastParam != 'self' &&
|
|
||||||
!lastParam.startsWith('**')) {
|
|
||||||
final paramObj = _parseParameter(lastParam);
|
|
||||||
if (paramObj != null) {
|
|
||||||
params.add(paramObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a single parameter
|
|
||||||
static Parameter? _parseParameter(String param) {
|
|
||||||
if (param.isEmpty) return null;
|
|
||||||
|
|
||||||
var name = param;
|
|
||||||
var type = 'Any';
|
|
||||||
var hasDefault = false;
|
|
||||||
var isOptional = false;
|
|
||||||
|
|
||||||
// Check for type annotation
|
|
||||||
if (param.contains(':')) {
|
|
||||||
final parts = param.split(':');
|
|
||||||
name = parts[0].trim();
|
|
||||||
var typeStr = parts[1];
|
|
||||||
|
|
||||||
// Handle default value
|
|
||||||
if (typeStr.contains('=')) {
|
|
||||||
final typeParts = typeStr.split('=');
|
|
||||||
typeStr = typeParts[0];
|
|
||||||
hasDefault = true;
|
|
||||||
isOptional = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = typeStr.trim();
|
|
||||||
|
|
||||||
// Handle Optional type
|
|
||||||
if (type.startsWith('Optional[')) {
|
|
||||||
type = type.substring(9, type.length - 1);
|
|
||||||
isOptional = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for default value without type annotation
|
|
||||||
if (param.contains('=')) {
|
|
||||||
hasDefault = true;
|
|
||||||
isOptional = true;
|
|
||||||
if (!param.contains(':')) {
|
|
||||||
name = param.split('=')[0].trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parameter(
|
|
||||||
name: name,
|
|
||||||
type: type,
|
|
||||||
isOptional: isOptional,
|
|
||||||
hasDefault: hasDefault,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a method definition
|
|
||||||
static Method? _parseMethod(
|
|
||||||
List<String> lines, int startIndex, List<String> decorators) {
|
|
||||||
final line = lines[startIndex].trim();
|
|
||||||
if (!line.startsWith('def ') && !line.startsWith('async def ')) return null;
|
|
||||||
|
|
||||||
final methodMatch =
|
|
||||||
RegExp(r'(?:async\s+)?def\s+(\w+)\s*\((.*?)\)(?:\s*->\s*(.+?))?\s*:')
|
|
||||||
.firstMatch(line);
|
|
||||||
if (methodMatch == null) return null;
|
|
||||||
|
|
||||||
final name = methodMatch.group(1)!;
|
|
||||||
final paramsStr = methodMatch.group(2) ?? '';
|
|
||||||
var returnType = methodMatch.group(3) ?? 'None';
|
|
||||||
returnType = returnType.trim();
|
|
||||||
|
|
||||||
final isAsync = line.contains('async ');
|
|
||||||
final isAbstract = decorators.contains('abstractmethod');
|
|
||||||
final isProperty = decorators.contains('property');
|
|
||||||
|
|
||||||
// Parse docstring if present
|
|
||||||
var i = startIndex + 1;
|
|
||||||
String? docstring;
|
|
||||||
if (i < lines.length) {
|
|
||||||
final nextLine = lines[i].trim();
|
|
||||||
if (nextLine.startsWith('"""')) {
|
|
||||||
docstring =
|
|
||||||
_parseDocstring(lines, i, _getIndentation(lines[startIndex]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Method(
|
|
||||||
name: name,
|
|
||||||
parameters: _parseParameters(paramsStr),
|
|
||||||
returnType: returnType,
|
|
||||||
docstring: docstring,
|
|
||||||
decorators: decorators,
|
|
||||||
isAsync: isAsync,
|
|
||||||
isAbstract: isAbstract,
|
|
||||||
isProperty: isProperty,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a property definition
|
|
||||||
static Property? _parseProperty(String line) {
|
|
||||||
if (!line.contains(':') || line.contains('def ')) return null;
|
|
||||||
|
|
||||||
final propertyMatch =
|
|
||||||
RegExp(r'(\w+)\s*:\s*(.+?)(?:\s*=\s*(.+))?$').firstMatch(line);
|
|
||||||
if (propertyMatch == null) return null;
|
|
||||||
|
|
||||||
final name = propertyMatch.group(1)!;
|
|
||||||
final type = propertyMatch.group(2)!;
|
|
||||||
final defaultValue = propertyMatch.group(3);
|
|
||||||
|
|
||||||
return Property(
|
|
||||||
name: name,
|
|
||||||
type: type.trim(),
|
|
||||||
hasDefault: defaultValue != null,
|
|
||||||
defaultValue: defaultValue?.trim(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse Python source code into a list of classes
|
|
||||||
static Future<List<PythonClass>> parseFile(File file) async {
|
|
||||||
final content = await file.readAsString();
|
|
||||||
final lines = content.split('\n');
|
|
||||||
final classes = <PythonClass>[];
|
|
||||||
|
|
||||||
for (var i = 0; i < lines.length; i++) {
|
|
||||||
final line = lines[i];
|
|
||||||
final trimmedLine = line.trim();
|
|
||||||
|
|
||||||
if (trimmedLine.startsWith('class ')) {
|
|
||||||
final classMatch =
|
|
||||||
RegExp(r'class\s+(\w+)(?:\((.*?)\))?:').firstMatch(trimmedLine);
|
|
||||||
if (classMatch != null) {
|
|
||||||
final className = classMatch.group(1)!;
|
|
||||||
final basesStr = classMatch.group(2);
|
|
||||||
final bases =
|
|
||||||
basesStr?.split(',').map((b) => b.trim()).toList() ?? [];
|
|
||||||
final isInterface = bases.any((b) => b.contains('Protocol'));
|
|
||||||
|
|
||||||
final classIndent = _getIndentation(line);
|
|
||||||
var currentDecorators = <String>[];
|
|
||||||
final methods = <Method>[];
|
|
||||||
final properties = <Property>[];
|
|
||||||
|
|
||||||
// Parse class docstring
|
|
||||||
var j = i + 1;
|
|
||||||
String? docstring;
|
|
||||||
if (j < lines.length && lines[j].trim().startsWith('"""')) {
|
|
||||||
docstring = _parseDocstring(lines, j, classIndent);
|
|
||||||
// Skip past docstring
|
|
||||||
while (j < lines.length && !lines[j].trim().endsWith('"""')) {
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse class body
|
|
||||||
while (j < lines.length) {
|
|
||||||
final currentLine = lines[j];
|
|
||||||
final currentIndent = _getIndentation(currentLine);
|
|
||||||
final trimmedCurrentLine = currentLine.trim();
|
|
||||||
|
|
||||||
// Check if we're still in the class
|
|
||||||
if (trimmedCurrentLine.isNotEmpty && currentIndent <= classIndent) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip empty lines
|
|
||||||
if (trimmedCurrentLine.isEmpty) {
|
|
||||||
j++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse decorators
|
|
||||||
if (trimmedCurrentLine.startsWith('@')) {
|
|
||||||
currentDecorators
|
|
||||||
.add(trimmedCurrentLine.substring(1).split('(')[0].trim());
|
|
||||||
j++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse methods
|
|
||||||
if (trimmedCurrentLine.startsWith('def ') ||
|
|
||||||
trimmedCurrentLine.startsWith('async def ')) {
|
|
||||||
final method =
|
|
||||||
_parseMethod(lines, j, List.from(currentDecorators));
|
|
||||||
if (method != null) {
|
|
||||||
methods.add(method);
|
|
||||||
currentDecorators = [];
|
|
||||||
// Skip past method body
|
|
||||||
while (j < lines.length - 1) {
|
|
||||||
final nextLine = lines[j + 1];
|
|
||||||
if (nextLine.trim().isEmpty ||
|
|
||||||
_getIndentation(nextLine) <= currentIndent) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse properties
|
|
||||||
final property = _parseProperty(trimmedCurrentLine);
|
|
||||||
if (property != null) {
|
|
||||||
properties.add(property);
|
|
||||||
}
|
|
||||||
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = j - 1;
|
|
||||||
|
|
||||||
classes.add(PythonClass(
|
|
||||||
name: className,
|
|
||||||
bases: bases,
|
|
||||||
methods: methods,
|
|
||||||
properties: properties,
|
|
||||||
docstring: docstring,
|
|
||||||
decorators: [],
|
|
||||||
isInterface: isInterface,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return classes;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,152 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Exit on error
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Script directory
|
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
PACKAGE_DIR="$(dirname "$SCRIPT_DIR")"
|
|
||||||
TEMP_DIR="$PACKAGE_DIR/temp"
|
|
||||||
CONTRACTS_FILE="$TEMP_DIR/contracts.yaml"
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Print step information
|
|
||||||
print_step() {
|
|
||||||
echo -e "${BLUE}=== $1 ===${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ensure required commands are available
|
|
||||||
check_requirements() {
|
|
||||||
print_step "Checking requirements"
|
|
||||||
|
|
||||||
commands=("git" "dart" "pub")
|
|
||||||
for cmd in "${commands[@]}"; do
|
|
||||||
if ! command -v $cmd &> /dev/null; then
|
|
||||||
echo "Error: $cmd is required but not installed."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create necessary directories
|
|
||||||
setup_directories() {
|
|
||||||
print_step "Setting up directories"
|
|
||||||
|
|
||||||
mkdir -p "$TEMP_DIR"
|
|
||||||
mkdir -p "$PACKAGE_DIR/lib/src/interfaces"
|
|
||||||
mkdir -p "$PACKAGE_DIR/lib/src/implementations"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Clone Python LangChain repository
|
|
||||||
clone_langchain() {
|
|
||||||
print_step "Cloning Python LangChain repository"
|
|
||||||
|
|
||||||
if [ -d "$TEMP_DIR/langchain" ]; then
|
|
||||||
echo "Updating existing LangChain repository..."
|
|
||||||
cd "$TEMP_DIR/langchain"
|
|
||||||
git pull
|
|
||||||
else
|
|
||||||
echo "Cloning LangChain repository..."
|
|
||||||
git clone https://github.com/langchain-ai/langchain.git "$TEMP_DIR/langchain"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Extract contracts from Python code
|
|
||||||
extract_contracts() {
|
|
||||||
print_step "Extracting contracts from Python code"
|
|
||||||
|
|
||||||
cd "$PACKAGE_DIR"
|
|
||||||
dart run "$SCRIPT_DIR/extract_contracts.dart" \
|
|
||||||
--source "$TEMP_DIR/langchain/langchain" \
|
|
||||||
--output "$CONTRACTS_FILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generate Dart code from contracts
|
|
||||||
generate_dart_code() {
|
|
||||||
print_step "Generating Dart code from contracts"
|
|
||||||
|
|
||||||
cd "$PACKAGE_DIR"
|
|
||||||
dart run "$SCRIPT_DIR/generate_dart_code.dart" \
|
|
||||||
--contracts "$CONTRACTS_FILE" \
|
|
||||||
--output "$PACKAGE_DIR"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Update package dependencies
|
|
||||||
update_dependencies() {
|
|
||||||
print_step "Updating package dependencies"
|
|
||||||
|
|
||||||
cd "$PACKAGE_DIR"
|
|
||||||
|
|
||||||
# Ensure required dependencies are in pubspec.yaml
|
|
||||||
if ! grep -q "yaml:" pubspec.yaml; then
|
|
||||||
echo "
|
|
||||||
dependencies:
|
|
||||||
yaml: ^3.1.0
|
|
||||||
path: ^1.8.0
|
|
||||||
args: ^2.3.0" >> pubspec.yaml
|
|
||||||
fi
|
|
||||||
|
|
||||||
dart pub get
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create package exports file
|
|
||||||
create_exports() {
|
|
||||||
print_step "Creating package exports"
|
|
||||||
|
|
||||||
cat > "$PACKAGE_DIR/lib/langchain.dart" << EOL
|
|
||||||
/// LangChain for Dart
|
|
||||||
///
|
|
||||||
/// This is a Dart implementation of LangChain, providing tools and utilities
|
|
||||||
/// for building applications powered by large language models (LLMs).
|
|
||||||
library langchain;
|
|
||||||
|
|
||||||
// Export interfaces
|
|
||||||
export 'src/interfaces/llm.dart';
|
|
||||||
export 'src/interfaces/chain.dart';
|
|
||||||
export 'src/interfaces/prompt.dart';
|
|
||||||
export 'src/interfaces/memory.dart';
|
|
||||||
export 'src/interfaces/embeddings.dart';
|
|
||||||
export 'src/interfaces/document.dart';
|
|
||||||
export 'src/interfaces/vectorstore.dart';
|
|
||||||
export 'src/interfaces/tool.dart';
|
|
||||||
export 'src/interfaces/agent.dart';
|
|
||||||
|
|
||||||
// Export implementations
|
|
||||||
export 'src/implementations/llm.dart';
|
|
||||||
export 'src/implementations/chain.dart';
|
|
||||||
export 'src/implementations/prompt.dart';
|
|
||||||
export 'src/implementations/memory.dart';
|
|
||||||
export 'src/implementations/embeddings.dart';
|
|
||||||
export 'src/implementations/document.dart';
|
|
||||||
export 'src/implementations/vectorstore.dart';
|
|
||||||
export 'src/implementations/tool.dart';
|
|
||||||
export 'src/implementations/agent.dart';
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main execution
|
|
||||||
main() {
|
|
||||||
print_step "Starting LangChain setup"
|
|
||||||
|
|
||||||
check_requirements
|
|
||||||
setup_directories
|
|
||||||
clone_langchain
|
|
||||||
extract_contracts
|
|
||||||
generate_dart_code
|
|
||||||
update_dependencies
|
|
||||||
create_exports
|
|
||||||
|
|
||||||
echo -e "${GREEN}Setup completed successfully!${NC}"
|
|
||||||
echo "Next steps:"
|
|
||||||
echo "1. Review generated code in lib/src/"
|
|
||||||
echo "2. Implement TODOs in the generated classes"
|
|
||||||
echo "3. Add tests for the implementations"
|
|
||||||
echo "4. Update the documentation"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Run main function
|
|
||||||
main
|
|
|
@ -1,53 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Array of extensions to uninstall
|
|
||||||
extensions=(
|
|
||||||
"nash.awesome-flutter-snippets" # Dart Data Class Generator
|
|
||||||
"robert-brunhage.flutter-riverpod-snippets" # Flutter Riverpod Snippets
|
|
||||||
"usernamehw.errorlens" # Error Lens
|
|
||||||
"aaron-bond.better-comments" # Better Comments
|
|
||||||
"styfle.remove-comments" # Remove Comments
|
|
||||||
"patbenatar.advanced-new-file" # Advanced New File
|
|
||||||
"GitHub.copilot" # GitHub Copilot
|
|
||||||
"dracula-theme.theme-dracula" # Dracula Theme (optional)
|
|
||||||
"firebase.vscode-firebase-explorer" # Firebase Explorer
|
|
||||||
"pflannery.vscode-versionlens" # Version Lens
|
|
||||||
"tgsup.find-unused-dart-files-and-assets" # Find Unused Dart Files & Assets
|
|
||||||
"humao.rest-client" # REST Client
|
|
||||||
"rangav.vscode-thunder-client" # Thunder Client
|
|
||||||
"ritwickdey.liveserver" # Live Server
|
|
||||||
"Dart-Code.dart-code" # Dart SDK
|
|
||||||
"Dart-Code.flutter" # Flutter SDK
|
|
||||||
"ms-vscode.cpptools" # C/C++
|
|
||||||
"ms-vscode.cpptools-extension-pack" # C/C++ Extension Pack
|
|
||||||
"ms-vscode.cpptools-themes" # C/C++ Themes
|
|
||||||
"twxs.cmake " # CMake
|
|
||||||
"ms-vscode.cmake-tools" # CMake Tools
|
|
||||||
"ms-vscode.makefile-tools" # Makefile Tools
|
|
||||||
"saoudrizwan.claude-dev" # Claude Dev
|
|
||||||
"Continue.continue" # Continue
|
|
||||||
"DEVSENSE.phptools-vscode" # PHP Tools
|
|
||||||
"DEVSENSE.composer-php-vscode" # Composer PHP
|
|
||||||
"DEVSENSE.profiler-php-vscode" # Profiler PHP
|
|
||||||
"ms-vscode.remote-explorer" # Remote - Containers
|
|
||||||
"ms-vscode-remote.remote-ssh" # Remote - SSH
|
|
||||||
"ms-vscode-remote.remote-ssh-edit" # Remote - SSH: Edit
|
|
||||||
"ms-vscode-remote.remote-containers" # Remote - Containers
|
|
||||||
"eamodio.gitlens" # GitLens
|
|
||||||
"DEVSENSE.intelli-php-vscode" # IntelliPHP
|
|
||||||
"blaugold.melos-code" # Melos
|
|
||||||
"vscode-icons-team.vscode-icons" # VSCode Icons
|
|
||||||
"redhat.vscode-yaml" # YAML
|
|
||||||
"GitHub.vscode-github-actions" # GitHub Actions
|
|
||||||
"ms-azuretools.vscode-docker" # Docker
|
|
||||||
"ms-kubernetes-tools.vscode-kubernetes-tools" # Kubernetes
|
|
||||||
)
|
|
||||||
|
|
||||||
# Uninstall each extension
|
|
||||||
echo "Uninstalling VSCode extensions..."
|
|
||||||
for extension in "${extensions[@]}"; do
|
|
||||||
code --uninstall-extension "$extension"
|
|
||||||
echo "Uninstalled: $extension"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "All specified extensions have been uninstalled successfully."
|
|
|
@ -13,7 +13,6 @@ repository: https://github.com/protevus/platform
|
||||||
packages:
|
packages:
|
||||||
- apps/**
|
- apps/**
|
||||||
- packages/**
|
- packages/**
|
||||||
- helpers/tools/**
|
|
||||||
- examples/**
|
- examples/**
|
||||||
|
|
||||||
command:
|
command:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/// An easily-extensible web server framework in Dart.
|
/// An easily-extensible web server framework in Dart.
|
||||||
library platform_core;
|
library platform_core;
|
||||||
|
|
||||||
export 'package:platform_support/exceptions.dart';
|
export 'package:platform_exceptions/http_exception.dart';
|
||||||
export 'package:platform_model/model.dart';
|
export 'package:platform_model/model.dart';
|
||||||
export 'package:platform_route/route.dart';
|
export 'package:platform_route/route.dart';
|
||||||
export 'src/core/core.dart';
|
export 'src/core/core.dart';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io' show Cookie;
|
import 'dart:io' show Cookie;
|
||||||
import 'package:platform_support/exceptions.dart';
|
import 'package:platform_exceptions/http_exception.dart';
|
||||||
import 'package:platform_route/route.dart';
|
import 'package:platform_route/route.dart';
|
||||||
import 'package:belatuk_combinator/belatuk_combinator.dart';
|
import 'package:belatuk_combinator/belatuk_combinator.dart';
|
||||||
import 'package:stack_trace/stack_trace.dart';
|
import 'package:stack_trace/stack_trace.dart';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:platform_support/exceptions.dart';
|
import 'package:platform_exceptions/http_exception.dart';
|
||||||
|
|
||||||
import 'service.dart';
|
import 'service.dart';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
library angel_framework.http.metadata;
|
library angel_framework.http.metadata;
|
||||||
|
|
||||||
import 'package:platform_support/exceptions.dart';
|
import 'package:platform_exceptions/http_exception.dart';
|
||||||
|
|
||||||
import 'hooked_service.dart' show HookedServiceEventListener;
|
import 'hooked_service.dart' show HookedServiceEventListener;
|
||||||
import 'request_context.dart';
|
import 'request_context.dart';
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'dart:async';
|
||||||
import 'dart:collection' show HashMap;
|
import 'dart:collection' show HashMap;
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:platform_container/container.dart';
|
import 'package:platform_container/container.dart';
|
||||||
import 'package:platform_support/exceptions.dart';
|
import 'package:platform_exceptions/http_exception.dart';
|
||||||
import 'package:platform_route/route.dart';
|
import 'package:platform_route/route.dart';
|
||||||
import 'package:belatuk_combinator/belatuk_combinator.dart';
|
import 'package:belatuk_combinator/belatuk_combinator.dart';
|
||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
library platform_core.http.service;
|
library platform_core.http.service;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:platform_support/exceptions.dart';
|
import 'package:platform_exceptions/http_exception.dart';
|
||||||
import 'package:belatuk_merge_map/belatuk_merge_map.dart';
|
import 'package:belatuk_merge_map/belatuk_merge_map.dart';
|
||||||
import 'package:quiver/core.dart';
|
import 'package:quiver/core.dart';
|
||||||
import '../util.dart';
|
import '../util.dart';
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'package:platform_container/container.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:collection/collection.dart' show IterableExtension;
|
import 'package:collection/collection.dart' show IterableExtension;
|
||||||
import 'package:http2/transport.dart';
|
import 'package:http2/transport.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
final RegExp _comma = RegExp(r',\s*');
|
final RegExp _comma = RegExp(r',\s*');
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'dart:io';
|
||||||
import 'package:platform_core/core.dart' hide Header;
|
import 'package:platform_core/core.dart' hide Header;
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:http2/transport.dart';
|
import 'package:http2/transport.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'http2_request_context.dart';
|
import 'http2_request_context.dart';
|
||||||
import 'http2_response_context.dart';
|
import 'http2_response_context.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
|
@ -389,6 +389,20 @@ packages:
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "9.0.0"
|
version: "9.0.0"
|
||||||
|
platform_exceptions:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "../exceptions"
|
||||||
|
relative: true
|
||||||
|
source: path
|
||||||
|
version: "9.0.0"
|
||||||
|
platform_mocking:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "../mocking"
|
||||||
|
relative: true
|
||||||
|
source: path
|
||||||
|
version: "9.0.0"
|
||||||
platform_model:
|
platform_model:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -403,20 +417,6 @@ packages:
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "9.0.0"
|
version: "9.0.0"
|
||||||
platform_support:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
path: "../support"
|
|
||||||
relative: true
|
|
||||||
source: path
|
|
||||||
version: "9.0.0"
|
|
||||||
platform_testing:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
path: "../testing"
|
|
||||||
relative: true
|
|
||||||
source: path
|
|
||||||
version: "9.0.0"
|
|
||||||
pool:
|
pool:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -8,10 +8,10 @@ environment:
|
||||||
sdk: '>=3.3.0 <4.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
platform_container: ^9.0.0
|
platform_container: ^9.0.0
|
||||||
|
platform_exceptions: ^9.0.0
|
||||||
platform_model: ^9.0.0
|
platform_model: ^9.0.0
|
||||||
platform_route: ^9.0.0
|
platform_route: ^9.0.0
|
||||||
platform_support: ^9.0.0
|
platform_mocking: ^9.0.0
|
||||||
platform_testing: ^9.0.0
|
|
||||||
belatuk_merge_map: ^5.1.0
|
belatuk_merge_map: ^5.1.0
|
||||||
belatuk_combinator: ^5.2.0
|
belatuk_combinator: ^5.2.0
|
||||||
belatuk_http_server: ^4.4.0
|
belatuk_http_server: ^4.4.0
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:io';
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
final Uri endpoint = Uri.parse('http://example.com/accept');
|
final Uri endpoint = Uri.parse('http://example.com/accept');
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
import 'common.dart';
|
import 'common.dart';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
import 'common.dart';
|
import 'common.dart';
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'dart:typed_data' show BytesBuilder;
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
Future<List<int>> getBody(MockHttpResponse rs) async {
|
Future<List<int>> getBody(MockHttpResponse rs) async {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:async';
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
final Uri endpoint = Uri.parse('http://example.com');
|
final Uri endpoint = Uri.parse('http://example.com');
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:convert';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'dart:convert';
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:convert';
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'dart:io' show stderr;
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'dart:convert';
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'dart:io';
|
||||||
import 'package:platform_container/mirrors.dart';
|
import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:platform_container/mirrors.dart';
|
||||||
import 'package:platform_core/core.dart';
|
import 'package:platform_core/core.dart';
|
||||||
import 'package:platform_core/http.dart';
|
import 'package:platform_core/http.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
|
71
packages/exceptions/.gitignore
vendored
Normal file
71
packages/exceptions/.gitignore
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# See https://www.dartlang.org/tools/private-files.html
|
||||||
|
|
||||||
|
# Files and directories created by pub
|
||||||
|
.dart_tool
|
||||||
|
.packages
|
||||||
|
.pub/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# If you're building an application, you may want to check-in your pubspec.lock
|
||||||
|
pubspec.lock
|
||||||
|
|
||||||
|
# Directory created by dartdoc
|
||||||
|
# If you don't generate documentation locally you can remove this line.
|
||||||
|
doc/api/
|
||||||
|
|
||||||
|
### Dart template
|
||||||
|
# See https://www.dartlang.org/tools/private-files.html
|
||||||
|
|
||||||
|
# Files and directories created by pub
|
||||||
|
|
||||||
|
# SDK 1.20 and later (no longer creates packages directories)
|
||||||
|
|
||||||
|
# Older SDK versions
|
||||||
|
# (Include if the minimum SDK version specified in pubsepc.yaml is earlier than 1.20)
|
||||||
|
.project
|
||||||
|
.buildlog
|
||||||
|
**/packages/
|
||||||
|
|
||||||
|
|
||||||
|
# Files created by dart2js
|
||||||
|
# (Most Dart developers will use pub build to compile Dart, use/modify these
|
||||||
|
# rules if you intend to use dart2js directly
|
||||||
|
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
|
||||||
|
# differentiate from explicit Javascript files)
|
||||||
|
*.dart.js
|
||||||
|
*.part.js
|
||||||
|
*.js.deps
|
||||||
|
*.js.map
|
||||||
|
*.info.json
|
||||||
|
|
||||||
|
# Directory created by dartdoc
|
||||||
|
|
||||||
|
# Don't commit pubspec lock file
|
||||||
|
# (Library packages only! Remove pattern if developing an application package)
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
|
||||||
|
## VsCode
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
.idea/
|
||||||
|
/out/
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
72
packages/exceptions/CHANGELOG.md
Normal file
72
packages/exceptions/CHANGELOG.md
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
# Change Log
|
||||||
|
|
||||||
|
## 8.1.1
|
||||||
|
|
||||||
|
* Updated repository link
|
||||||
|
|
||||||
|
## 8.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
|
||||||
|
## 8.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 7.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 2.17
|
||||||
|
|
||||||
|
## 6.0.1
|
||||||
|
|
||||||
|
* Updated README
|
||||||
|
|
||||||
|
## 6.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 2.16
|
||||||
|
* [**Breaking**] `error` for `HttpException` is no longer mandatory
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
* Skipped release
|
||||||
|
|
||||||
|
## 4.0.0
|
||||||
|
|
||||||
|
* Skipped release
|
||||||
|
|
||||||
|
## 3.1.0
|
||||||
|
|
||||||
|
* Upgraded to `lints` linter
|
||||||
|
|
||||||
|
## 3.0.2
|
||||||
|
|
||||||
|
* Updated LICENSE link
|
||||||
|
|
||||||
|
## 3.0.1
|
||||||
|
|
||||||
|
* Updated README
|
||||||
|
|
||||||
|
## 3.0.0
|
||||||
|
|
||||||
|
* Migrated to support Dart >= 2.12 NNBD
|
||||||
|
|
||||||
|
## 2.0.0
|
||||||
|
|
||||||
|
* Migrated to work with Dart >= 2.12 Non NNBD
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
* Emit `is_error` and `status_code` in `toJson()`.
|
||||||
|
* No more `camelCase` at all.
|
||||||
|
|
||||||
|
## 1.0.0+3
|
||||||
|
|
||||||
|
* Slightly relax the deserialization of `errors`.
|
||||||
|
|
||||||
|
## 1.0.0+2
|
||||||
|
|
||||||
|
* Added a backwards-compatible way to cast the `errors` List.
|
||||||
|
|
||||||
|
## 1.0.0+1
|
||||||
|
|
||||||
|
* Dart 2 updates.
|
8
packages/exceptions/README.md
Normal file
8
packages/exceptions/README.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Protevus Http Exception
|
||||||
|
|
||||||
|
![Pub Version (including pre-releases)](https://img.shields.io/pub/v/angel3_http_exception?include_prereleases)
|
||||||
|
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
||||||
|
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
||||||
|
[![License](https://img.shields.io/github/license/dart-backend/angel)](https://github.com/dart-backend/angel/tree/master/packages/http_exception/LICENSE)
|
||||||
|
|
||||||
|
Exception class that can be serialized to JSON and serialized to clients. Protevus's HTTP exception class.
|
1
packages/exceptions/analysis_options.yaml
Normal file
1
packages/exceptions/analysis_options.yaml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
include: package:lints/recommended.yaml
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:platform_support/src/exceptions/http_exception.dart';
|
import 'package:platform_exceptions/http_exception.dart';
|
||||||
|
|
||||||
void main() =>
|
void main() =>
|
||||||
throw PlatformHttpException.notFound(message: "Can't find that page!");
|
throw PlatformHttpException.notFound(message: "Can't find that page!");
|
11
packages/exceptions/pubspec.yaml
Normal file
11
packages/exceptions/pubspec.yaml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
name: platform_exceptions
|
||||||
|
version: 9.0.0
|
||||||
|
description: Protevus Platform Exception package
|
||||||
|
homepage: https://protevus.com
|
||||||
|
documentation: https://docs.protevus.com
|
||||||
|
repository: https://git.protevus.com/protevus/platform/src/branch/main/packages/exceptions
|
||||||
|
environment:
|
||||||
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
|
dev_dependencies:
|
||||||
|
lints: ^4.0.0
|
||||||
|
test: ^1.25.8
|
71
packages/mocking/.gitignore
vendored
Normal file
71
packages/mocking/.gitignore
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# See https://www.dartlang.org/tools/private-files.html
|
||||||
|
|
||||||
|
# Files and directories created by pub
|
||||||
|
.dart_tool
|
||||||
|
.packages
|
||||||
|
.pub/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# If you're building an application, you may want to check-in your pubspec.lock
|
||||||
|
pubspec.lock
|
||||||
|
|
||||||
|
# Directory created by dartdoc
|
||||||
|
# If you don't generate documentation locally you can remove this line.
|
||||||
|
doc/api/
|
||||||
|
|
||||||
|
### Dart template
|
||||||
|
# See https://www.dartlang.org/tools/private-files.html
|
||||||
|
|
||||||
|
# Files and directories created by pub
|
||||||
|
|
||||||
|
# SDK 1.20 and later (no longer creates packages directories)
|
||||||
|
|
||||||
|
# Older SDK versions
|
||||||
|
# (Include if the minimum SDK version specified in pubsepc.yaml is earlier than 1.20)
|
||||||
|
.project
|
||||||
|
.buildlog
|
||||||
|
**/packages/
|
||||||
|
|
||||||
|
|
||||||
|
# Files created by dart2js
|
||||||
|
# (Most Dart developers will use pub build to compile Dart, use/modify these
|
||||||
|
# rules if you intend to use dart2js directly
|
||||||
|
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
|
||||||
|
# differentiate from explicit Javascript files)
|
||||||
|
*.dart.js
|
||||||
|
*.part.js
|
||||||
|
*.js.deps
|
||||||
|
*.js.map
|
||||||
|
*.info.json
|
||||||
|
|
||||||
|
# Directory created by dartdoc
|
||||||
|
|
||||||
|
# Don't commit pubspec lock file
|
||||||
|
# (Library packages only! Remove pattern if developing an application package)
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
|
||||||
|
## VsCode
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
.idea/
|
||||||
|
/out/
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
12
packages/mocking/AUTHORS.md
Normal file
12
packages/mocking/AUTHORS.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Primary Authors
|
||||||
|
===============
|
||||||
|
|
||||||
|
* __[Thomas Hii](dukefirehawk.apps@gmail.com)__
|
||||||
|
|
||||||
|
Thomas is the current maintainer of the code base. He has refactored and migrated the
|
||||||
|
code base to support NNBD.
|
||||||
|
|
||||||
|
* __[Tobe O](thosakwe@gmail.com)__
|
||||||
|
|
||||||
|
Tobe has written much of the original code prior to NNBD migration. He has moved on and
|
||||||
|
is no longer involved with the project.
|
29
packages/mocking/LICENSE
Normal file
29
packages/mocking/LICENSE
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2021, dukefirehawk.com
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
1
packages/mocking/analysis_options.yaml
Normal file
1
packages/mocking/analysis_options.yaml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
include: package:lints/recommended.yaml
|
|
@ -1,5 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:platform_testing/http.dart';
|
import 'package:platform_mocking/mocking.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
var rq =
|
var rq =
|
6
packages/mocking/lib/mocking.dart
Normal file
6
packages/mocking/lib/mocking.dart
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export 'src/connection_info.dart';
|
||||||
|
export 'src/headers.dart';
|
||||||
|
export 'src/lockable_headers.dart';
|
||||||
|
export 'src/request.dart';
|
||||||
|
export 'src/response.dart';
|
||||||
|
export 'src/session.dart';
|
25
packages/mocking/pubspec.yaml
Normal file
25
packages/mocking/pubspec.yaml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
name: platform_mocking
|
||||||
|
version: 9.0.0
|
||||||
|
description: Protevus Platform Mocking for dart:io HttpRequests, HttpResponses, HttpHeaders, etc.
|
||||||
|
homepage: https://protevus.com
|
||||||
|
documentation: https://docs.protevus.com
|
||||||
|
repository: https://git.protevus.com/protevus/platform/src/branch/main/packages/mocking
|
||||||
|
environment:
|
||||||
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
|
dependencies:
|
||||||
|
charcode: ^1.3.1
|
||||||
|
dev_dependencies:
|
||||||
|
http: ^1.2.2
|
||||||
|
test: ^1.25.8
|
||||||
|
lints: ^4.0.0
|
||||||
|
# dependency_overrides:
|
||||||
|
# platform_core:
|
||||||
|
# path: ../framework
|
||||||
|
# platform_route:
|
||||||
|
# path: ../route
|
||||||
|
# platform_model:
|
||||||
|
# path: ../model
|
||||||
|
# platform_exceptions:
|
||||||
|
# path: ../exceptions
|
||||||
|
# platform_container:
|
||||||
|
# path: ../container/container
|
7
packages/support/.gitignore
vendored
7
packages/support/.gitignore
vendored
|
@ -1,7 +0,0 @@
|
||||||
# https://dart.dev/guides/libraries/private-files
|
|
||||||
# Created by `dart pub`
|
|
||||||
.dart_tool/
|
|
||||||
|
|
||||||
# Avoid committing pubspec.lock for library packages; see
|
|
||||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
|
||||||
pubspec.lock
|
|
|
@ -1,3 +0,0 @@
|
||||||
## 1.0.0
|
|
||||||
|
|
||||||
- Initial version.
|
|
|
@ -1,39 +0,0 @@
|
||||||
<!--
|
|
||||||
This README describes the package. If you publish this package to pub.dev,
|
|
||||||
this README's contents appear on the landing page for your package.
|
|
||||||
|
|
||||||
For information about how to write a good package README, see the guide for
|
|
||||||
[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
|
|
||||||
|
|
||||||
For general information about developing packages, see the Dart guide for
|
|
||||||
[creating packages](https://dart.dev/guides/libraries/create-packages)
|
|
||||||
and the Flutter guide for
|
|
||||||
[developing packages and plugins](https://flutter.dev/to/develop-packages).
|
|
||||||
-->
|
|
||||||
|
|
||||||
TODO: Put a short description of the package here that helps potential users
|
|
||||||
know whether this package might be useful for them.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
|
||||||
|
|
||||||
## Getting started
|
|
||||||
|
|
||||||
TODO: List prerequisites and provide or point to information on how to
|
|
||||||
start using the package.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
TODO: Include short and useful examples for package users. Add longer examples
|
|
||||||
to `/example` folder.
|
|
||||||
|
|
||||||
```dart
|
|
||||||
const like = 'sample';
|
|
||||||
```
|
|
||||||
|
|
||||||
## Additional information
|
|
||||||
|
|
||||||
TODO: Tell users more about the package: where to find more information, how to
|
|
||||||
contribute to the package, how to file issues, what response they can expect
|
|
||||||
from the package authors, and more.
|
|
|
@ -1,30 +0,0 @@
|
||||||
# This file configures the static analysis results for your project (errors,
|
|
||||||
# warnings, and lints).
|
|
||||||
#
|
|
||||||
# This enables the 'recommended' set of lints from `package:lints`.
|
|
||||||
# This set helps identify many issues that may lead to problems when running
|
|
||||||
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
|
||||||
# style and format.
|
|
||||||
#
|
|
||||||
# If you want a smaller set of lints you can change this to specify
|
|
||||||
# 'package:lints/core.yaml'. These are just the most critical lints
|
|
||||||
# (the recommended set includes the core lints).
|
|
||||||
# The core lints are also what is used by pub.dev for scoring packages.
|
|
||||||
|
|
||||||
include: package:lints/recommended.yaml
|
|
||||||
|
|
||||||
# Uncomment the following section to specify additional rules.
|
|
||||||
|
|
||||||
# linter:
|
|
||||||
# rules:
|
|
||||||
# - camel_case_types
|
|
||||||
|
|
||||||
# analyzer:
|
|
||||||
# exclude:
|
|
||||||
# - path/to/excluded/files/**
|
|
||||||
|
|
||||||
# For more information about the core and recommended set of lints, see
|
|
||||||
# https://dart.dev/go/core-lints
|
|
||||||
|
|
||||||
# For additional information about configuring this file, see
|
|
||||||
# https://dart.dev/guides/language/analysis-options
|
|
|
@ -1,8 +0,0 @@
|
||||||
/// Support for doing something awesome.
|
|
||||||
///
|
|
||||||
/// More dartdocs go here.
|
|
||||||
library;
|
|
||||||
|
|
||||||
export 'src/exceptions/http_exception.dart';
|
|
||||||
|
|
||||||
// TODO: Export any libraries intended for clients of this package.
|
|
|
@ -1,15 +0,0 @@
|
||||||
name: platform_support
|
|
||||||
description: Protevus Platform support package.
|
|
||||||
version: 9.0.0
|
|
||||||
# repository: https://github.com/my_org/my_repo
|
|
||||||
|
|
||||||
environment:
|
|
||||||
sdk: ^3.5.4
|
|
||||||
|
|
||||||
# Add regular dependencies here.
|
|
||||||
dependencies:
|
|
||||||
# path: ^1.8.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
|
||||||
lints: ^4.0.0
|
|
||||||
test: ^1.24.0
|
|
7
packages/testing/.gitignore
vendored
7
packages/testing/.gitignore
vendored
|
@ -1,7 +0,0 @@
|
||||||
# https://dart.dev/guides/libraries/private-files
|
|
||||||
# Created by `dart pub`
|
|
||||||
.dart_tool/
|
|
||||||
|
|
||||||
# Avoid committing pubspec.lock for library packages; see
|
|
||||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
|
||||||
pubspec.lock
|
|
|
@ -1,30 +0,0 @@
|
||||||
# This file configures the static analysis results for your project (errors,
|
|
||||||
# warnings, and lints).
|
|
||||||
#
|
|
||||||
# This enables the 'recommended' set of lints from `package:lints`.
|
|
||||||
# This set helps identify many issues that may lead to problems when running
|
|
||||||
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
|
||||||
# style and format.
|
|
||||||
#
|
|
||||||
# If you want a smaller set of lints you can change this to specify
|
|
||||||
# 'package:lints/core.yaml'. These are just the most critical lints
|
|
||||||
# (the recommended set includes the core lints).
|
|
||||||
# The core lints are also what is used by pub.dev for scoring packages.
|
|
||||||
|
|
||||||
include: package:lints/recommended.yaml
|
|
||||||
|
|
||||||
# Uncomment the following section to specify additional rules.
|
|
||||||
|
|
||||||
# linter:
|
|
||||||
# rules:
|
|
||||||
# - camel_case_types
|
|
||||||
|
|
||||||
# analyzer:
|
|
||||||
# exclude:
|
|
||||||
# - path/to/excluded/files/**
|
|
||||||
|
|
||||||
# For more information about the core and recommended set of lints, see
|
|
||||||
# https://dart.dev/go/core-lints
|
|
||||||
|
|
||||||
# For additional information about configuring this file, see
|
|
||||||
# https://dart.dev/guides/language/analysis-options
|
|
|
@ -1,6 +0,0 @@
|
||||||
export 'src/http/connection_info.dart';
|
|
||||||
export 'src/http/headers.dart';
|
|
||||||
export 'src/http/lockable_headers.dart';
|
|
||||||
export 'src/http/request.dart';
|
|
||||||
export 'src/http/response.dart';
|
|
||||||
export 'src/http/session.dart';
|
|
|
@ -1,15 +0,0 @@
|
||||||
name: platform_testing
|
|
||||||
description: Testing helper files for Protevus Platform.
|
|
||||||
version: 9.0.0
|
|
||||||
# repository: https://github.com/my_org/my_repo
|
|
||||||
|
|
||||||
environment:
|
|
||||||
sdk: ^3.5.4
|
|
||||||
|
|
||||||
# Add regular dependencies here.
|
|
||||||
dependencies:
|
|
||||||
charcode: ^1.3.1
|
|
||||||
|
|
||||||
dev_dependencies:
|
|
||||||
lints: ^4.0.0
|
|
||||||
test: ^1.24.0
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="160" height="40" viewBox="0 0 160 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<!-- P shape with gradient -->
|
|
||||||
<path d="M10 5h15c5.523 0 10 4.477 10 10s-4.477 10-10 10H20v10H10V5z" fill="url(#gradient)"/>
|
|
||||||
<path d="M20 15h5c2.761 0 5 2.239 5 5s-2.239 5-5 5h-5v-10z" fill="#ffffff"/>
|
|
||||||
|
|
||||||
<!-- Circular element representing technology/connectivity -->
|
|
||||||
<circle cx="45" cy="20" r="8" fill="url(#gradient)" opacity="0.8"/>
|
|
||||||
<circle cx="45" cy="20" r="4" fill="#ffffff"/>
|
|
||||||
|
|
||||||
<!-- Text "Protevus" -->
|
|
||||||
<text x="65" y="28" font-family="Arial, sans-serif" font-weight="bold" font-size="24" fill="currentColor">Protevus</text>
|
|
||||||
|
|
||||||
<!-- Gradient definition -->
|
|
||||||
<defs>
|
|
||||||
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
||||||
<stop offset="0%" style="stop-color:#512BD4"/>
|
|
||||||
<stop offset="100%" style="stop-color:#6742D9"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 995 B |
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue