Skip to content

Commit

Permalink
migrate license to AGPL v3, upgrade dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
roncodes committed Jul 5, 2024
1 parent a7c49d5 commit d07b8e3
Show file tree
Hide file tree
Showing 13 changed files with 919 additions and 20 deletions.
652 changes: 647 additions & 5 deletions LICENSE.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions addon/controllers/developers/extensions/new.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ export default class DevelopersExtensionsNewController extends Controller {
} catch (error) {
return this.notifications.warning(error.message);
}
return this.hostRouter.transitionTo('console.registry-bridge.developers.extensions.edit', this.extension);
return this.hostRouter.transitionTo('console.extensions.developers.extensions.edit', this.extension);
}

@action cancel() {
this.reset();
return this.hostRouter.transitionTo('console.registry-bridge.developers.extensions');
return this.hostRouter.transitionTo('console.extensions.developers.extensions');
}

reset() {
Expand Down
2 changes: 1 addition & 1 deletion addon/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class RegistryBridgeEngine extends Engine {
};
setupExtension = function (app, engine, universe) {
// Register menu item in header
universe.registerHeaderMenuItem('Extensions', 'console.registry-bridge', { icon: 'shapes', priority: 99 });
universe.registerHeaderMenuItem('Extensions', 'console.extensions', { icon: 'shapes', priority: 99 });
// Register admin controls
universe.registerAdminMenuPanel(
'Extensions Registry',
Expand Down
12 changes: 6 additions & 6 deletions addon/templates/application.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<EmberWormhole @to="sidebar-menu-items">
<Layout::Sidebar::Item @route="console.registry-bridge.installed" @icon="inbox">Installed</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.extensions.installed" @icon="inbox">Installed</Layout::Sidebar::Item>
<Layout::Sidebar::Panel @open={{true}} @title="Explore">
<Layout::Sidebar::Item @route="console.registry-bridge.explore.index" @icon="shapes">Explore All</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.extensions.explore.index" @icon="shapes">Explore All</Layout::Sidebar::Item>
{{#each this.categories as |category|}}
<LinkTo @route="explore.category" @model={{category}} class="next-nav-item">
<div class="next-nav-item-icon-container">
Expand All @@ -13,10 +13,10 @@
{{/each}}
</Layout::Sidebar::Panel>
<Layout::Sidebar::Panel @open={{true}} @title="Developers">
<Layout::Sidebar::Item @route="console.registry-bridge.developers.extensions" @icon="box-archive">Extensions</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.registry-bridge.developers.analytics" @icon="chart-simple">Analytics</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.registry-bridge.developers.payments" @icon="cash-register">Payments</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.registry-bridge.developers.credentials" @icon="key">Credentials</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.extensions.developers.extensions" @icon="box-archive">Extensions</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.extensions.developers.analytics" @icon="chart-simple">Analytics</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.extensions.developers.payments" @icon="cash-register">Payments</Layout::Sidebar::Item>
<Layout::Sidebar::Item @route="console.extensions.developers.credentials" @icon="key">Credentials</Layout::Sidebar::Item>
</Layout::Sidebar::Panel>
<Spacer @height="200px" />
</EmberWormhole>
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"fleetbase-registry-bridge",
"fleetbase"
],
"license": "MIT",
"license": "AGPL-3.0-or-later",
"authors": [
{
"name": "Fleetbase Pte Ltd.",
Expand All @@ -20,7 +20,7 @@
],
"require": {
"php": "^8.0",
"fleetbase/core-api": "^1.4.25",
"fleetbase/core-api": "^1.4.26",
"php-http/guzzle7-adapter": "^1.0",
"psr/http-factory-implementation": "*"
},
Expand Down
2 changes: 1 addition & 1 deletion extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.1",
"description": "Internal Bridge between Fleetbase API and Extensions Registry",
"repository": "https://github.com/fleetbase/registry-bridge",
"license": "MIT",
"license": "AGPL-3.0-or-later",
"author": "Fleetbase Pte Ltd <hello@fleetbase.io>",
"engine": "package.json",
"api": "composer.json"
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"name": "@fleetbase/registry-bridge-engine",
"version": "0.0.1",
"description": "Internal Bridge between Fleetbase API and Extensions Registry",
"fleetbase": {
"route": "extensions"
},
"keywords": [
"fleetbase-extension",
"fleetbase-registry-bridge",
Expand All @@ -10,7 +13,7 @@
"ember-engine"
],
"repository": "https://github.com/fleetbase/registry-bridge",
"license": "MIT",
"license": "AGPL-3.0-or-later",
"author": "Fleetbase Pte Ltd <hello@fleetbase.io>",
"directories": {
"app": "app",
Expand All @@ -36,7 +39,7 @@
},
"dependencies": {
"@fleetbase/ember-core": "^0.2.11",
"@fleetbase/ember-ui": "^0.2.16",
"@fleetbase/ember-ui": "^0.2.17",
"@babel/core": "^7.23.2",
"@fortawesome/ember-fontawesome": "^0.4.1",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
Expand Down
87 changes: 87 additions & 0 deletions server/src/Console/Commands/PostInstallExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace Fleetbase\RegistryBridge\Console\Commands;

use Fleetbase\RegistryBridge\Models\RegistryExtension;
use Illuminate\Console\Command;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;

class PostInstallExtension extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'extension:post-install {extensionId}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Post install an extension by running necessary commands';

/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$extensionId = $this->argument('extensionId');
$extension = RegistryExtension::disableCache()->where('public_id', $extensionId)->first();

if ($extension) {
$this->postInstallExtension($extension);
$this->info('Post install commands executed successfully.');
} else {
$this->error('Extension not found.');
}

return 0;
}

/**
* Post install extension commands.
*
* @param \Fleetbase\RegistryBridge\Models\RegistryExtension $extension
* @return void
*/
public function postInstallExtension(RegistryExtension $extension): void
{
if (isset($extension->currentBundle)) {
$composerJson = $extension->currentBundle->meta['composer.json'];
if ($composerJson) {
$extensionPath = base_path('vendor/' . $composerJson['name']);

$commands = [
'rm -rf /fleetbase/.pnpm-store',
'rm -rf node_modules',
'pnpm install',
'pnpm build'
];

$this->info('Running post install for: ' . $extension->name);
$this->info('Extension install path: ' . $extensionPath);
foreach ($commands as $command) {
$this->info('Running extension post install command: `' . $command . '`');
$process = Process::fromShellCommandline($command, $extensionPath);
$process->run(function ($type, $buffer) {
if (Process::ERR === $type) {
$this->error($buffer);
} else {
$this->info($buffer);
}
});

// Check if the process was successful
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public function install(InstallExtensionRequest $request)
*/
public function uninstall(InstallExtensionRequest $request)
{
set_time_limit(120);
$extension = RegistryExtension::where('public_id', $request->input('extension'))->first();
$uninstalled = false;

Expand Down
154 changes: 154 additions & 0 deletions server/src/Http/Controllers/Internal/v1/RegistryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Fleetbase\Http\Controllers\Controller;
use Fleetbase\Http\Resources\Category as CategoryResource;
use Fleetbase\Models\Category;
use Fleetbase\RegistryBridge\Models\RegistryExtension;

class RegistryController extends Controller
{
Expand All @@ -16,4 +17,157 @@ public function categories()

return CategoryResource::collection($categories);
}

public function loadInstalledEngines()
{
$installedExtensions = RegistryExtension::disableCache()->whereHas('installs', function ($query) {
$query->where('company_uuid', session('company'));
})->get()->mapWithKeys(function ($extension) {
return [$extension->public_id => $extension->currentBundle->meta['package.json'] ?? []];
});

return response()->json($installedExtensions);
}

public function loadEngineManifest(string $extensionId)
{
$extension = RegistryExtension::where('public_id', $extensionId)->first();
if (!$extension) {
return response()->json([]);
}

if (isset($extension->currentBundle)) {
$composerJson = $extension->currentBundle->meta['composer.json'];
$packageJson = $extension->currentBundle->meta['package.json'] ?? null;
if ($composerJson) {
$packageDistPath = base_path('vendor/' .$composerJson['name'] . '/dist');
$assetManifestPath = $packageDistPath . '/asset-manifest.json';
$assetManifest = json_decode(file_get_contents($assetManifestPath));

// Get bundles
$bundles = $assetManifest->bundles;

// Create consumable assets map
$output = [];
foreach ($bundles as $manifest) {
if (isset($manifest->assets) && is_array($manifest->assets)) {
foreach ($manifest->assets as $asset) {
$name = null;
$type = $asset->type;
$content = file_get_contents($packageDistPath . $asset->uri);
$syntax = $type === 'js' ? 'application/javascript' : 'text/css';
if ($type === 'js' && static::isES6Module($content)) {
$syntax = 'module';
}

// Check for config environments which should be injected as meta tags
if (static::containsConfigEnvironment($content)) {
// might need to make as additional $output[] element
$type = 'meta';
$name = static::extractModuleName($content);
$content = urlencode(static::extractConfigEnvironment($content));
$syntax = null;
}

$output[] = [
'name' => $name,
'type' => $type,
'content' => $content,
'syntax' => $syntax
];
}
}
}

return response()->json($output);
}
}

return response()->json([]);
}

private static function isES6Module(string $contents)
{
// Check for module-specific keywords like import or export
if (preg_match('/\bimport\s|\bexport\s/', $contents)) {
return true; // It should be a module
}

return false; // It should not be a module
}

private static function containsConfigEnvironment(string $contents): bool
{
// This regex checks if the string starts with define and includes a module name ending with "/config/environment"
return preg_match('/^define\("@[^"]+\/config\/environment",/', $contents);
}


private static function extractConfigEnvironment(string $contents)
{
// This regex extracts the JSON-like object from the define function's return statement
if (preg_match('/define\("@[^"]+\/config\/environment",.*?\(function\(\)\{return\{default:(\{.*?\})\}\}\)\)/s', $contents, $matches)) {
// Capture the object after "default:"
$configString = $matches[1];
// Correctly balance the curly braces to form a valid JSON object
$configString = self::balanceCurlyBraces($configString);
$configString = self::fixJsonFormat($configString);
// Convert the balanced string to an array
return $configString;
}

return null;
}

private static function fixJsonFormat($jsObject) {
// Add quotes around keys where they may be missing
$pattern = '/(?<=[{,])(\s*)([a-zA-Z0-9_]+)(\s*):/m';
$replacement = '$1"$2"$3:';
$jsonLikeString = preg_replace($pattern, $replacement, $jsObject);

// Replace single quotes with double quotes around string values
$pattern = "/:(\s*)'([^']*)'/";
$replacement = ':$1"$2"';
$jsonLikeString = preg_replace($pattern, $replacement, $jsonLikeString);

// Ensure booleans and null are properly formatted
$jsonLikeString = preg_replace('/:(\s*)(true|false|null)/i', ':$1$2', $jsonLikeString);

// Convert the inner single quotes encapsulated by double quotes back to single quotes
$pattern = '/"(.*?)"/s';
$callback = function ($matches) {
return '"' . str_replace('"', "'", $matches[1]) . '"';
};
$jsonLikeString = preg_replace_callback($pattern, $callback, $jsonLikeString);

return $jsonLikeString;
}

private static function balanceCurlyBraces($string)
{
// This function aims to balance curly braces if they are not properly closed in the extracted string
$count = 0;
$length = strlen($string);
for ($i = 0; $i < $length; $i++) {
if ($string[$i] === '{') {
$count++;
} elseif ($string[$i] === '}') {
$count--;
if ($count === 0) {
// Cut the string up to the last matching closing brace
return substr($string, 0, $i + 1);
}
}
}
return $string; // Return as is if braces are balanced
}

private static function extractModuleName(string $contents)
{
// This regex matches the module name part of the define function call
if (preg_match('/define\("([^"]+)"/', $contents, $matches)) {
return $matches[1];
}
return null;
}
}
2 changes: 1 addition & 1 deletion server/src/Models/RegistryExtensionBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ public function installEnginePackage(): void
dd($output);

if (!$process->isSuccessful()) {
throw new Exception('Engine install failed!');
throw new \Exception('Engine install failed!');
// $friendlyMessage = static::composerOutputFriendly($output);
// throw new InstallFailedException($friendlyMessage);
}
Expand Down
10 changes: 10 additions & 0 deletions server/src/Providers/RegistryBridgeServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ class RegistryBridgeServiceProvider extends CoreServiceProvider
*/
public $observers = [];

/**
* The console commands registered with the service provider.
*
* @var array
*/
public $commands = [
\Fleetbase\RegistryBridge\Console\Commands\PostInstallExtension::class
];

/**
* The middleware groups registered with the service provider.
*
Expand Down Expand Up @@ -61,6 +70,7 @@ public function register()
*/
public function boot()
{
$this->registerCommands();
$this->registerMiddleware();
$this->registerExpansionsFrom(__DIR__ . '/../Expansions');
$this->loadRoutesFrom(__DIR__ . '/../routes.php');
Expand Down
Loading

0 comments on commit d07b8e3

Please sign in to comment.