Initial commit
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
/vendor/
 | 
			
		||||
/*.phar
 | 
			
		||||
							
								
								
									
										49
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
# ServerCtl - Services for Developers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Examples
 | 
			
		||||
 | 
			
		||||
Say you need a Mongodb instance for something. Try this:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
$ serverctl start mongo
 | 
			
		||||
Started mongo<default>
 | 
			
		||||
  Mongo client: 27017
 | 
			
		||||
$
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
What just happened? Well, the `start` command pulled and started a new container
 | 
			
		||||
from the latest docker image using sensible defaults from the service registry.
 | 
			
		||||
 | 
			
		||||
Let's start another one:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
$ serverctl start mongo --instance other --portoffset 1
 | 
			
		||||
Started mongo<other>
 | 
			
		||||
  Mongo client: 27018
 | 
			
		||||
$
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Check it out!
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
$ serverctl status
 | 
			
		||||
Service   Instance   Ports
 | 
			
		||||
mongo     default    27017
 | 
			
		||||
          other      27018
 | 
			
		||||
$ serverctl stop mongo --all
 | 
			
		||||
Stopped mongo<default>
 | 
			
		||||
Stopped mongo<other>
 | 
			
		||||
$
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## FAQ
 | 
			
		||||
 | 
			
		||||
### Where is the data stored?
 | 
			
		||||
 | 
			
		||||
* Data goes in `$HOME/.var/serverctl`
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								bin/serverctl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										9
									
								
								bin/serverctl
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
#!/usr/bin/env php
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
use NoccyLabs\Serverctl\ConsoleApplication;
 | 
			
		||||
 | 
			
		||||
require_once __DIR__."/../vendor/autoload.php";
 | 
			
		||||
 | 
			
		||||
$app = new ConsoleApplication();
 | 
			
		||||
$app->run();
 | 
			
		||||
							
								
								
									
										29
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "noccylabs/serverctl",
 | 
			
		||||
    "description": "Start and stop services for development",
 | 
			
		||||
    "type": "application",
 | 
			
		||||
    "license": "GPL-3.0-or-later",
 | 
			
		||||
    "autoload": {
 | 
			
		||||
        "psr-4": {
 | 
			
		||||
            "NoccyLabs\\Serverctl\\": "src/"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "authors": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "Christopher Vagnetoft",
 | 
			
		||||
            "email": "cvagnetoft@gmail.com"
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "require": {
 | 
			
		||||
        "symfony/console": "^6.1",
 | 
			
		||||
        "noccylabs/spinner": "^0.1.0"
 | 
			
		||||
    },
 | 
			
		||||
    "bin": [
 | 
			
		||||
        "bin/serverctl"
 | 
			
		||||
    ],
 | 
			
		||||
    "extra": {
 | 
			
		||||
        "phar": {
 | 
			
		||||
            "output": "serverctl.phar"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										761
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										761
									
								
								composer.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,761 @@
 | 
			
		||||
{
 | 
			
		||||
    "_readme": [
 | 
			
		||||
        "This file locks the dependencies of your project to a known state",
 | 
			
		||||
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
			
		||||
        "This file is @generated automatically"
 | 
			
		||||
    ],
 | 
			
		||||
    "content-hash": "21d444d8fc7b7dc1b673054b1a48432a",
 | 
			
		||||
    "packages": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "noccylabs/spinner",
 | 
			
		||||
            "version": "0.1.0",
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://dev.noccylabs.info/api/packages/noccy/composer/files/noccylabs%2Fspinner/0.1.0/noccylabs-spinner.0.1.0.zip",
 | 
			
		||||
                "shasum": "5be298051ee740bcb7fa6aac0fa57ae3bbf0771e"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "NoccyLabs\\Spinner\\": "src/"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "license": [
 | 
			
		||||
                "GPL-3.0-or-later"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Christopher Vagnetoft",
 | 
			
		||||
                    "email": "cvagnetoft@gmail.com"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Indicate activity in console applications",
 | 
			
		||||
            "time": "2022-09-22T00:11:39+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "psr/container",
 | 
			
		||||
            "version": "2.0.2",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/php-fig/container.git",
 | 
			
		||||
                "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
 | 
			
		||||
                "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=7.4.0"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-master": "2.0.x-dev"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Psr\\Container\\": "src/"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "PHP-FIG",
 | 
			
		||||
                    "homepage": "https://www.php-fig.org/"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Common Container Interface (PHP FIG PSR-11)",
 | 
			
		||||
            "homepage": "https://github.com/php-fig/container",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "PSR-11",
 | 
			
		||||
                "container",
 | 
			
		||||
                "container-interface",
 | 
			
		||||
                "container-interop",
 | 
			
		||||
                "psr"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "issues": "https://github.com/php-fig/container/issues",
 | 
			
		||||
                "source": "https://github.com/php-fig/container/tree/2.0.2"
 | 
			
		||||
            },
 | 
			
		||||
            "time": "2021-11-05T16:47:00+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/console",
 | 
			
		||||
            "version": "v6.1.4",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/console.git",
 | 
			
		||||
                "reference": "7fccea8728aa2d431a6725b02b3ce759049fc84d"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/console/zipball/7fccea8728aa2d431a6725b02b3ce759049fc84d",
 | 
			
		||||
                "reference": "7fccea8728aa2d431a6725b02b3ce759049fc84d",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=8.1",
 | 
			
		||||
                "symfony/deprecation-contracts": "^2.1|^3",
 | 
			
		||||
                "symfony/polyfill-mbstring": "~1.0",
 | 
			
		||||
                "symfony/service-contracts": "^1.1|^2|^3",
 | 
			
		||||
                "symfony/string": "^5.4|^6.0"
 | 
			
		||||
            },
 | 
			
		||||
            "conflict": {
 | 
			
		||||
                "symfony/dependency-injection": "<5.4",
 | 
			
		||||
                "symfony/dotenv": "<5.4",
 | 
			
		||||
                "symfony/event-dispatcher": "<5.4",
 | 
			
		||||
                "symfony/lock": "<5.4",
 | 
			
		||||
                "symfony/process": "<5.4"
 | 
			
		||||
            },
 | 
			
		||||
            "provide": {
 | 
			
		||||
                "psr/log-implementation": "1.0|2.0|3.0"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
                "psr/log": "^1|^2|^3",
 | 
			
		||||
                "symfony/config": "^5.4|^6.0",
 | 
			
		||||
                "symfony/dependency-injection": "^5.4|^6.0",
 | 
			
		||||
                "symfony/event-dispatcher": "^5.4|^6.0",
 | 
			
		||||
                "symfony/lock": "^5.4|^6.0",
 | 
			
		||||
                "symfony/process": "^5.4|^6.0",
 | 
			
		||||
                "symfony/var-dumper": "^5.4|^6.0"
 | 
			
		||||
            },
 | 
			
		||||
            "suggest": {
 | 
			
		||||
                "psr/log": "For using the console logger",
 | 
			
		||||
                "symfony/event-dispatcher": "",
 | 
			
		||||
                "symfony/lock": "",
 | 
			
		||||
                "symfony/process": ""
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Symfony\\Component\\Console\\": ""
 | 
			
		||||
                },
 | 
			
		||||
                "exclude-from-classmap": [
 | 
			
		||||
                    "/Tests/"
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Fabien Potencier",
 | 
			
		||||
                    "email": "fabien@symfony.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Eases the creation of beautiful and testable command line interfaces",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "cli",
 | 
			
		||||
                "command line",
 | 
			
		||||
                "console",
 | 
			
		||||
                "terminal"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/console/tree/v6.1.4"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-08-26T10:32:31+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/deprecation-contracts",
 | 
			
		||||
            "version": "v3.1.1",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/deprecation-contracts.git",
 | 
			
		||||
                "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918",
 | 
			
		||||
                "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=8.1"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-main": "3.1-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "thanks": {
 | 
			
		||||
                    "name": "symfony/contracts",
 | 
			
		||||
                    "url": "https://github.com/symfony/contracts"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "files": [
 | 
			
		||||
                    "function.php"
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Nicolas Grekas",
 | 
			
		||||
                    "email": "p@tchwork.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "A generic function and convention to trigger deprecation notices",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-02-25T11:15:52+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/polyfill-ctype",
 | 
			
		||||
            "version": "v1.26.0",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/polyfill-ctype.git",
 | 
			
		||||
                "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
 | 
			
		||||
                "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=7.1"
 | 
			
		||||
            },
 | 
			
		||||
            "provide": {
 | 
			
		||||
                "ext-ctype": "*"
 | 
			
		||||
            },
 | 
			
		||||
            "suggest": {
 | 
			
		||||
                "ext-ctype": "For best performance"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-main": "1.26-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "thanks": {
 | 
			
		||||
                    "name": "symfony/polyfill",
 | 
			
		||||
                    "url": "https://github.com/symfony/polyfill"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "files": [
 | 
			
		||||
                    "bootstrap.php"
 | 
			
		||||
                ],
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Symfony\\Polyfill\\Ctype\\": ""
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Gert de Pagter",
 | 
			
		||||
                    "email": "BackEndTea@gmail.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Symfony polyfill for ctype functions",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "compatibility",
 | 
			
		||||
                "ctype",
 | 
			
		||||
                "polyfill",
 | 
			
		||||
                "portable"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-05-24T11:49:31+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/polyfill-intl-grapheme",
 | 
			
		||||
            "version": "v1.26.0",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
 | 
			
		||||
                "reference": "433d05519ce6990bf3530fba6957499d327395c2"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
 | 
			
		||||
                "reference": "433d05519ce6990bf3530fba6957499d327395c2",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=7.1"
 | 
			
		||||
            },
 | 
			
		||||
            "suggest": {
 | 
			
		||||
                "ext-intl": "For best performance"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-main": "1.26-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "thanks": {
 | 
			
		||||
                    "name": "symfony/polyfill",
 | 
			
		||||
                    "url": "https://github.com/symfony/polyfill"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "files": [
 | 
			
		||||
                    "bootstrap.php"
 | 
			
		||||
                ],
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Nicolas Grekas",
 | 
			
		||||
                    "email": "p@tchwork.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Symfony polyfill for intl's grapheme_* functions",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "compatibility",
 | 
			
		||||
                "grapheme",
 | 
			
		||||
                "intl",
 | 
			
		||||
                "polyfill",
 | 
			
		||||
                "portable",
 | 
			
		||||
                "shim"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-05-24T11:49:31+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/polyfill-intl-normalizer",
 | 
			
		||||
            "version": "v1.26.0",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
 | 
			
		||||
                "reference": "219aa369ceff116e673852dce47c3a41794c14bd"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
 | 
			
		||||
                "reference": "219aa369ceff116e673852dce47c3a41794c14bd",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=7.1"
 | 
			
		||||
            },
 | 
			
		||||
            "suggest": {
 | 
			
		||||
                "ext-intl": "For best performance"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-main": "1.26-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "thanks": {
 | 
			
		||||
                    "name": "symfony/polyfill",
 | 
			
		||||
                    "url": "https://github.com/symfony/polyfill"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "files": [
 | 
			
		||||
                    "bootstrap.php"
 | 
			
		||||
                ],
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
 | 
			
		||||
                },
 | 
			
		||||
                "classmap": [
 | 
			
		||||
                    "Resources/stubs"
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Nicolas Grekas",
 | 
			
		||||
                    "email": "p@tchwork.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Symfony polyfill for intl's Normalizer class and related functions",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "compatibility",
 | 
			
		||||
                "intl",
 | 
			
		||||
                "normalizer",
 | 
			
		||||
                "polyfill",
 | 
			
		||||
                "portable",
 | 
			
		||||
                "shim"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-05-24T11:49:31+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/polyfill-mbstring",
 | 
			
		||||
            "version": "v1.26.0",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/polyfill-mbstring.git",
 | 
			
		||||
                "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
 | 
			
		||||
                "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=7.1"
 | 
			
		||||
            },
 | 
			
		||||
            "provide": {
 | 
			
		||||
                "ext-mbstring": "*"
 | 
			
		||||
            },
 | 
			
		||||
            "suggest": {
 | 
			
		||||
                "ext-mbstring": "For best performance"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-main": "1.26-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "thanks": {
 | 
			
		||||
                    "name": "symfony/polyfill",
 | 
			
		||||
                    "url": "https://github.com/symfony/polyfill"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "files": [
 | 
			
		||||
                    "bootstrap.php"
 | 
			
		||||
                ],
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Symfony\\Polyfill\\Mbstring\\": ""
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Nicolas Grekas",
 | 
			
		||||
                    "email": "p@tchwork.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Symfony polyfill for the Mbstring extension",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "compatibility",
 | 
			
		||||
                "mbstring",
 | 
			
		||||
                "polyfill",
 | 
			
		||||
                "portable",
 | 
			
		||||
                "shim"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-05-24T11:49:31+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/service-contracts",
 | 
			
		||||
            "version": "v3.1.1",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/service-contracts.git",
 | 
			
		||||
                "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239",
 | 
			
		||||
                "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=8.1",
 | 
			
		||||
                "psr/container": "^2.0"
 | 
			
		||||
            },
 | 
			
		||||
            "conflict": {
 | 
			
		||||
                "ext-psr": "<1.1|>=2"
 | 
			
		||||
            },
 | 
			
		||||
            "suggest": {
 | 
			
		||||
                "symfony/service-implementation": ""
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "extra": {
 | 
			
		||||
                "branch-alias": {
 | 
			
		||||
                    "dev-main": "3.1-dev"
 | 
			
		||||
                },
 | 
			
		||||
                "thanks": {
 | 
			
		||||
                    "name": "symfony/contracts",
 | 
			
		||||
                    "url": "https://github.com/symfony/contracts"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Symfony\\Contracts\\Service\\": ""
 | 
			
		||||
                },
 | 
			
		||||
                "exclude-from-classmap": [
 | 
			
		||||
                    "/Test/"
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Nicolas Grekas",
 | 
			
		||||
                    "email": "p@tchwork.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Generic abstractions related to writing services",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "abstractions",
 | 
			
		||||
                "contracts",
 | 
			
		||||
                "decoupling",
 | 
			
		||||
                "interfaces",
 | 
			
		||||
                "interoperability",
 | 
			
		||||
                "standards"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/service-contracts/tree/v3.1.1"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-05-30T19:18:58+00:00"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "symfony/string",
 | 
			
		||||
            "version": "v6.1.4",
 | 
			
		||||
            "source": {
 | 
			
		||||
                "type": "git",
 | 
			
		||||
                "url": "https://github.com/symfony/string.git",
 | 
			
		||||
                "reference": "290972cad7b364e3befaa74ba0ec729800fb161c"
 | 
			
		||||
            },
 | 
			
		||||
            "dist": {
 | 
			
		||||
                "type": "zip",
 | 
			
		||||
                "url": "https://api.github.com/repos/symfony/string/zipball/290972cad7b364e3befaa74ba0ec729800fb161c",
 | 
			
		||||
                "reference": "290972cad7b364e3befaa74ba0ec729800fb161c",
 | 
			
		||||
                "shasum": ""
 | 
			
		||||
            },
 | 
			
		||||
            "require": {
 | 
			
		||||
                "php": ">=8.1",
 | 
			
		||||
                "symfony/polyfill-ctype": "~1.8",
 | 
			
		||||
                "symfony/polyfill-intl-grapheme": "~1.0",
 | 
			
		||||
                "symfony/polyfill-intl-normalizer": "~1.0",
 | 
			
		||||
                "symfony/polyfill-mbstring": "~1.0"
 | 
			
		||||
            },
 | 
			
		||||
            "conflict": {
 | 
			
		||||
                "symfony/translation-contracts": "<2.0"
 | 
			
		||||
            },
 | 
			
		||||
            "require-dev": {
 | 
			
		||||
                "symfony/error-handler": "^5.4|^6.0",
 | 
			
		||||
                "symfony/http-client": "^5.4|^6.0",
 | 
			
		||||
                "symfony/translation-contracts": "^2.0|^3.0",
 | 
			
		||||
                "symfony/var-exporter": "^5.4|^6.0"
 | 
			
		||||
            },
 | 
			
		||||
            "type": "library",
 | 
			
		||||
            "autoload": {
 | 
			
		||||
                "files": [
 | 
			
		||||
                    "Resources/functions.php"
 | 
			
		||||
                ],
 | 
			
		||||
                "psr-4": {
 | 
			
		||||
                    "Symfony\\Component\\String\\": ""
 | 
			
		||||
                },
 | 
			
		||||
                "exclude-from-classmap": [
 | 
			
		||||
                    "/Tests/"
 | 
			
		||||
                ]
 | 
			
		||||
            },
 | 
			
		||||
            "notification-url": "https://packagist.org/downloads/",
 | 
			
		||||
            "license": [
 | 
			
		||||
                "MIT"
 | 
			
		||||
            ],
 | 
			
		||||
            "authors": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Nicolas Grekas",
 | 
			
		||||
                    "email": "p@tchwork.com"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Symfony Community",
 | 
			
		||||
                    "homepage": "https://symfony.com/contributors"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
 | 
			
		||||
            "homepage": "https://symfony.com",
 | 
			
		||||
            "keywords": [
 | 
			
		||||
                "grapheme",
 | 
			
		||||
                "i18n",
 | 
			
		||||
                "string",
 | 
			
		||||
                "unicode",
 | 
			
		||||
                "utf-8",
 | 
			
		||||
                "utf8"
 | 
			
		||||
            ],
 | 
			
		||||
            "support": {
 | 
			
		||||
                "source": "https://github.com/symfony/string/tree/v6.1.4"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": [
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://symfony.com/sponsor",
 | 
			
		||||
                    "type": "custom"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://github.com/fabpot",
 | 
			
		||||
                    "type": "github"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
 | 
			
		||||
                    "type": "tidelift"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "time": "2022-08-12T18:05:43+00:00"
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "packages-dev": [],
 | 
			
		||||
    "aliases": [],
 | 
			
		||||
    "minimum-stability": "stable",
 | 
			
		||||
    "stability-flags": [],
 | 
			
		||||
    "prefer-stable": false,
 | 
			
		||||
    "prefer-lowest": false,
 | 
			
		||||
    "platform": [],
 | 
			
		||||
    "platform-dev": [],
 | 
			
		||||
    "plugin-api-version": "2.3.0"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								registry/mariadb.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								registry/mariadb.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
{
 | 
			
		||||
  "$type": "service",
 | 
			
		||||
  "name": "mariadb",
 | 
			
		||||
  "description": "MariaDB (MySQL fork)",
 | 
			
		||||
  "author": null,
 | 
			
		||||
  "image": "mariadb",
 | 
			
		||||
  "ports": [ 
 | 
			
		||||
    { "port": 3306, "info": "MySQL client" }
 | 
			
		||||
  ],
 | 
			
		||||
  "environment": {
 | 
			
		||||
    "MARIADB_ROOT_PASSWORD": "toor"
 | 
			
		||||
  },
 | 
			
		||||
  "persistence": [
 | 
			
		||||
    { "path": "/data", "hint": "data" }
 | 
			
		||||
  ],
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "mongosh": {
 | 
			
		||||
      "info": "Open the mongo shell",
 | 
			
		||||
      "execute": "mongosh"
 | 
			
		||||
    },
 | 
			
		||||
    "export": {
 | 
			
		||||
      "info": "Export the database",
 | 
			
		||||
      "execute": "mysqldump "
 | 
			
		||||
    },
 | 
			
		||||
    "import": {
 | 
			
		||||
      "info": "Import the database",
 | 
			
		||||
      "execute": "mongoimport"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								registry/mongo.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								registry/mongo.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
{
 | 
			
		||||
  "$type": "service",
 | 
			
		||||
  "name": "mongo",
 | 
			
		||||
  "description": "MongoDB",
 | 
			
		||||
  "author": null,
 | 
			
		||||
  "image": "mongo",
 | 
			
		||||
  "ports": [ 
 | 
			
		||||
    { "port": 27017, "info": "Mongo client" }
 | 
			
		||||
  ],
 | 
			
		||||
  "persistence": [
 | 
			
		||||
    { "path": "/data/db", "hint": "data" }
 | 
			
		||||
  ],
 | 
			
		||||
  "environment": {
 | 
			
		||||
    "MONGO_INITDB_ROOT_PASSWORD": "toor",
 | 
			
		||||
    "MONGO_INITDB_ROOT_USERNAME": "root"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "shell": {
 | 
			
		||||
      "info": "Open the mongo shell",
 | 
			
		||||
      "execute": "mongosh"
 | 
			
		||||
    },
 | 
			
		||||
    "export": {
 | 
			
		||||
      "info": "Export the database",
 | 
			
		||||
      "execute": "mongodump"
 | 
			
		||||
    },
 | 
			
		||||
    "import": {
 | 
			
		||||
      "info": "Import the database",
 | 
			
		||||
      "execute": "mongoimport"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								registry/mysql.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								registry/mysql.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
{
 | 
			
		||||
  "$type": "service",
 | 
			
		||||
  "name": "mysql",
 | 
			
		||||
  "description": "MySQL",
 | 
			
		||||
  "author": null,
 | 
			
		||||
  "image": "mysql",
 | 
			
		||||
  "ports": [ 
 | 
			
		||||
    { "port": 3306, "info": "MySQL client" }
 | 
			
		||||
  ],
 | 
			
		||||
  "environment": {
 | 
			
		||||
    "MARIADB_ROOT_PASSWORD": "toor"
 | 
			
		||||
  },
 | 
			
		||||
  "persistence": [
 | 
			
		||||
    { "path": "/data", "hint": "data" }
 | 
			
		||||
  ],
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "shell": {
 | 
			
		||||
      "info": "Open the mongo shell",
 | 
			
		||||
      "execute": "mysql -uroot -p%{MARIADB_ROOT_PASSWORD}"
 | 
			
		||||
    },
 | 
			
		||||
    "export": {
 | 
			
		||||
      "info": "Export the database",
 | 
			
		||||
      "execute": "mysqldump -uroot -p%{MARIADB_ROOT_PASSWORD}"
 | 
			
		||||
    },
 | 
			
		||||
    "import": {
 | 
			
		||||
      "info": "Import the database",
 | 
			
		||||
      "execute": "mysql -uroot -p%{MARIADB_ROOT_PASSWORD}"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								registry/postgres.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								registry/postgres.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
{
 | 
			
		||||
  "$type": "service",
 | 
			
		||||
  "name": "postgres",
 | 
			
		||||
  "description": "Postgres SQL server",
 | 
			
		||||
  "author": null,
 | 
			
		||||
  "image": "postgres",
 | 
			
		||||
  "ports": [ 
 | 
			
		||||
    { "port": 5432, "info": "Postgres client" }
 | 
			
		||||
  ],
 | 
			
		||||
  "environment": {
 | 
			
		||||
    "POSTGRES_PASSWORD": "password"
 | 
			
		||||
  },
 | 
			
		||||
  "persistence": [
 | 
			
		||||
    { "path": "/data", "hint": "data" }
 | 
			
		||||
  ],
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "mongosh": {
 | 
			
		||||
      "info": "Open a pg shell",
 | 
			
		||||
      "execute": "psql --user postgres"
 | 
			
		||||
    },
 | 
			
		||||
    "export": {
 | 
			
		||||
      "info": "Export the database",
 | 
			
		||||
      "execute": "mysqldump "
 | 
			
		||||
    },
 | 
			
		||||
    "import": {
 | 
			
		||||
      "info": "Import the database",
 | 
			
		||||
      "execute": "mongoimport"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								src/Commands/Command.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Commands/Command.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl\Commands;
 | 
			
		||||
 | 
			
		||||
use NoccyLabs\Serverctl\ConsoleApplication;
 | 
			
		||||
use NoccyLabs\Serverctl\Container\ContainerManager;
 | 
			
		||||
use NoccyLabs\Serverctl\Registry\ServiceRegistry;
 | 
			
		||||
use Symfony\Component\Console\Command\Command as CommandCommand;
 | 
			
		||||
 | 
			
		||||
abstract class Command extends CommandCommand
 | 
			
		||||
{
 | 
			
		||||
    public function getApplication(): ?ConsoleApplication
 | 
			
		||||
    {
 | 
			
		||||
        return parent::getApplication();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getServiceRegistry(): ServiceRegistry
 | 
			
		||||
    {
 | 
			
		||||
        return $this->getApplication()->getServiceRegistry();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function getContainerManager(): ContainerManager
 | 
			
		||||
    {
 | 
			
		||||
        return $this->getApplication()->getContainerManager();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								src/Commands/ExecCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/Commands/ExecCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl\Commands;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Console\Attribute\AsCommand;
 | 
			
		||||
use Symfony\Component\Console\Input\InputArgument;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Input\InputOption;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
#[AsCommand(name:"exec", description:"Execute a shell command or script in the service")]
 | 
			
		||||
class ExecCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->addOption("instance", "I", InputOption::VALUE_REQUIRED, "Specify the instance name", "default");
 | 
			
		||||
        $this->addOption("script", "s", InputOption::VALUE_NONE, "The command is a script (use 'list' for list)");
 | 
			
		||||
        $this->addArgument("service", InputArgument::REQUIRED, "The service name");
 | 
			
		||||
        $this->addArgument("execute", InputArgument::REQUIRED, "The command or script to execute");
 | 
			
		||||
        $this->addArgument("arguments", InputArgument::IS_ARRAY, "Arguments");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $serviceRegistry = $this->getServiceRegistry();
 | 
			
		||||
        $containerManager = $this->getContainerManager();
 | 
			
		||||
        $instanceName = $input->getOption("instance");
 | 
			
		||||
 | 
			
		||||
        $serviceName = $input->getArgument("service");
 | 
			
		||||
        $command = $input->getArgument("execute");
 | 
			
		||||
 | 
			
		||||
        $serviceInfo = $serviceRegistry->findServiceByName($serviceName);
 | 
			
		||||
 | 
			
		||||
        if ($command == "list") {
 | 
			
		||||
            $scripts = (array)($serviceInfo['scripts']??[]);
 | 
			
		||||
            $output->writeln("Available scripts:");
 | 
			
		||||
            foreach ($scripts as $script=>$meta) {
 | 
			
		||||
                $output->writeln(sprintf("  <comment>%s</> - <info>%s</>", $script, $meta['info']??"?"));
 | 
			
		||||
            }
 | 
			
		||||
            return self::SUCCESS;
 | 
			
		||||
        } else {
 | 
			
		||||
            $cmdl = [ $input->getArgument("execute") ];
 | 
			
		||||
            array_push($cmdl, ...$input->getArgument("arguments"));
 | 
			
		||||
            $containerManager->execute($serviceInfo, $instanceName, $cmdl);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return self::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								src/Commands/FindCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/Commands/FindCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl\Commands;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Console\Attribute\AsCommand;
 | 
			
		||||
use Symfony\Component\Console\Input\InputArgument;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Input\InputOption;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
#[AsCommand(name:"find", description:"Find defined services")]
 | 
			
		||||
class FindCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->addArgument("service", InputArgument::OPTIONAL, "Search query");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $serviceRegistry = $this->getServiceRegistry();
 | 
			
		||||
 | 
			
		||||
        $services = $serviceRegistry->findAllServices();
 | 
			
		||||
 | 
			
		||||
        $output->writeln("Available services:");
 | 
			
		||||
        foreach ($services as $service) {
 | 
			
		||||
            $output->writeln(sprintf("  <comment>%s</> - <info>%s</>", $service['name'], $service['description']??"?"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return self::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								src/Commands/StartCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/Commands/StartCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl\Commands;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Console\Attribute\AsCommand;
 | 
			
		||||
use Symfony\Component\Console\Input\InputArgument;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Input\InputOption;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
#[AsCommand(name:"start", description:"Start a service")]
 | 
			
		||||
class StartCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->addOption("instance", "I", InputOption::VALUE_REQUIRED, "Specify the instance name", "default");
 | 
			
		||||
        $this->addOption("portoffset", "p", InputOption::VALUE_REQUIRED, "Offset port numbers by value", 0);
 | 
			
		||||
        $this->addArgument("service", InputArgument::REQUIRED, "The service name");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $serviceRegistry = $this->getServiceRegistry();
 | 
			
		||||
        $containerManager = $this->getContainerManager();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        $serviceName = $input->getArgument("service");
 | 
			
		||||
 | 
			
		||||
        $serviceInfo = $serviceRegistry->findServiceByName($serviceName);
 | 
			
		||||
        if (!$serviceInfo) {
 | 
			
		||||
            $output->writeln("<error>No such service in registry</>");
 | 
			
		||||
            return self::FAILURE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $options = [
 | 
			
		||||
            'name' => $input->getOption("instance"),
 | 
			
		||||
            'portoffset' => $input->getOption("portoffset")
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        $containerManager->startService($serviceInfo, $options);
 | 
			
		||||
 | 
			
		||||
        return self::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								src/Commands/StatusCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/Commands/StatusCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl\Commands;
 | 
			
		||||
 | 
			
		||||
use NoccyLabs\Spinner\Spinner;
 | 
			
		||||
use NoccyLabs\Spinner\Style\BrailleDotsStyle;
 | 
			
		||||
use Symfony\Component\Console\Attribute\AsCommand;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Input\InputOption;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
#[AsCommand(name:"status", description:"Show the running services")]
 | 
			
		||||
class StatusCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $spinner = new Spinner(style: BrailleDotsStyle::class, fps: 15);
 | 
			
		||||
 | 
			
		||||
        $output->write("    Getting status\r");
 | 
			
		||||
        for ($n = 0; $n < 250; $n++) {
 | 
			
		||||
            if ($output->isDecorated()) $output->write("({$spinner})\r");
 | 
			
		||||
            usleep(10000);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        return self::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								src/Commands/StopCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/Commands/StopCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl\Commands;
 | 
			
		||||
 | 
			
		||||
use Symfony\Component\Console\Attribute\AsCommand;
 | 
			
		||||
use Symfony\Component\Console\Input\InputArgument;
 | 
			
		||||
use Symfony\Component\Console\Input\InputInterface;
 | 
			
		||||
use Symfony\Component\Console\Input\InputOption;
 | 
			
		||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
			
		||||
 | 
			
		||||
#[AsCommand(name:"stop", description:"Stop a running service")]
 | 
			
		||||
class StopCommand extends Command
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    protected function configure()
 | 
			
		||||
    {
 | 
			
		||||
        $this->addOption("instance", "I", InputOption::VALUE_REQUIRED, "Specify the instance name", "default");
 | 
			
		||||
        $this->addArgument("service", InputArgument::REQUIRED, "The service name");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
			
		||||
    {
 | 
			
		||||
        $serviceRegistry = $this->getServiceRegistry();
 | 
			
		||||
        $containerManager = $this->getContainerManager();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        $serviceName = $input->getArgument("service");
 | 
			
		||||
 | 
			
		||||
        $serviceInfo = $serviceRegistry->findServiceByName($serviceName);
 | 
			
		||||
        if (!$serviceInfo) {
 | 
			
		||||
            $output->writeln("<error>No such service in registry</>");
 | 
			
		||||
            return self::FAILURE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $containerManager->stopService($serviceInfo, $input->getOption("instance"));
 | 
			
		||||
 | 
			
		||||
        return self::SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								src/ConsoleApplication.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/ConsoleApplication.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl;
 | 
			
		||||
 | 
			
		||||
use NoccyLabs\Serverctl\Container\ContainerManager;
 | 
			
		||||
use NoccyLabs\Serverctl\Registry\ServiceRegistry;
 | 
			
		||||
use Symfony\Component\Console\Application;
 | 
			
		||||
 | 
			
		||||
class ConsoleApplication extends Application
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    private ServiceRegistry $serviceRegistry;
 | 
			
		||||
 | 
			
		||||
    private ContainerManager $containerManager;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct("Development server utility", "0.1.0");
 | 
			
		||||
 | 
			
		||||
        $this->serviceRegistry = new ServiceRegistry(
 | 
			
		||||
            paths: [
 | 
			
		||||
                __DIR__."/../registry",
 | 
			
		||||
                dirname(realpath($GLOBALS['argv'][0]))."/registry",
 | 
			
		||||
                "/usr/share/serverctl/registry",
 | 
			
		||||
                getenv("HOME")."/.share/serverctl/registry"
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
        $this->containerManager = new ContainerManager(
 | 
			
		||||
            dataPath: null
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $this->add(new Commands\StartCommand());
 | 
			
		||||
        $this->add(new Commands\StopCommand());
 | 
			
		||||
        $this->add(new Commands\ExecCommand());
 | 
			
		||||
        $this->add(new Commands\FindCommand());
 | 
			
		||||
        $this->add(new Commands\StatusCommand());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getServiceRegistry(): ServiceRegistry
 | 
			
		||||
    {
 | 
			
		||||
        return $this->serviceRegistry;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function getContainerManager(): ContainerManager
 | 
			
		||||
    {
 | 
			
		||||
        return $this->containerManager;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										132
									
								
								src/Container/ContainerManager.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/Container/ContainerManager.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl\Container;
 | 
			
		||||
 | 
			
		||||
class ContainerManager
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    private string $dataPath;
 | 
			
		||||
 | 
			
		||||
    public function __construct(?string $dataPath=null)
 | 
			
		||||
    {
 | 
			
		||||
        $this->dataPath = $dataPath ?? (getenv("HOME")."/.var/serverctl");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start a service
 | 
			
		||||
     * 
 | 
			
		||||
     * Instance options:
 | 
			
		||||
     *   name: Instance name (default)
 | 
			
		||||
     *   portoffset: Port number offset (0)
 | 
			
		||||
     * 
 | 
			
		||||
     * @param array $service The service definition from the registry  
 | 
			
		||||
     * @param array $options Instance options
 | 
			
		||||
     */
 | 
			
		||||
    public function startService(array $service, array $options)
 | 
			
		||||
    {
 | 
			
		||||
        $args = [];
 | 
			
		||||
 | 
			
		||||
        $serviceName = $service['name'];
 | 
			
		||||
        $instanceName = $options['name']??'default';
 | 
			
		||||
 | 
			
		||||
        $containerName = "sm_".$serviceName."_".$instanceName;
 | 
			
		||||
 | 
			
		||||
        $args[] = 'run';
 | 
			
		||||
        $args[] = '--rm'; // remove container after run
 | 
			
		||||
        $args[] = '-d';
 | 
			
		||||
        $args[] = '--name';
 | 
			
		||||
        $args[] = $containerName;
 | 
			
		||||
 | 
			
		||||
        // Map the ports
 | 
			
		||||
        $ports = (array)($service['ports']??[]);
 | 
			
		||||
        foreach ($ports as $port) {
 | 
			
		||||
            $args[] = '-p';
 | 
			
		||||
            $args[] = $port['port'];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get the paths to persist
 | 
			
		||||
        $volumes = (array)($service['persistence']??[]);
 | 
			
		||||
        $volumePath = $this->getServiceDataPath($service)."/".$instanceName;
 | 
			
		||||
        foreach ($volumes as $volume) {
 | 
			
		||||
            // volume { path, hint }
 | 
			
		||||
            $path = $volume['path'];
 | 
			
		||||
            $hint = $volume['hint'] ?? crc32($path);
 | 
			
		||||
            $args[] = '-v'; // add volume
 | 
			
		||||
            $args[] = $volumePath."/".$hint.":".$path;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get environment
 | 
			
		||||
        $envs = (array)($service['environment']??[]);
 | 
			
		||||
        foreach ($envs as $env=>$value) {
 | 
			
		||||
            $args[] = '-e';
 | 
			
		||||
            // TODO: use environment if set (override)
 | 
			
		||||
            $args[] = sprintf("%s=%s", $env, $value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $args[] = $service['image'];
 | 
			
		||||
 | 
			
		||||
        $cmdl = 'docker '.join(' ',array_map('escapeshellarg', $args));
 | 
			
		||||
 | 
			
		||||
        // TODO: Write command line, env and meta to state file
 | 
			
		||||
        
 | 
			
		||||
        echo "$ {$cmdl}\n";
 | 
			
		||||
        passthru($cmdl);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Stop a service
 | 
			
		||||
     */
 | 
			
		||||
    public function stopService(array $service, string $instanceName)
 | 
			
		||||
    {
 | 
			
		||||
        $args = [];
 | 
			
		||||
 | 
			
		||||
        $serviceName = $service['name'];
 | 
			
		||||
        $instanceName = $options['name']??'default';
 | 
			
		||||
        $containerName = "sm_".$serviceName."_".$instanceName;
 | 
			
		||||
 | 
			
		||||
        $args[] = 'stop';
 | 
			
		||||
        $args[] = $containerName;
 | 
			
		||||
 | 
			
		||||
        $cmdl = 'docker '.join(' ',array_map('escapeshellarg', $args));
 | 
			
		||||
 | 
			
		||||
        echo "$ {$cmdl}\n";
 | 
			
		||||
        passthru($cmdl);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function execute(array $service, string $instanceName, array $command)
 | 
			
		||||
    {
 | 
			
		||||
        $args = [];
 | 
			
		||||
 | 
			
		||||
        $serviceName = $service['name'];
 | 
			
		||||
        $instanceName = $options['name']??'default';
 | 
			
		||||
        $containerName = "sm_".$serviceName."_".$instanceName;
 | 
			
		||||
 | 
			
		||||
        $args[] = 'exec';
 | 
			
		||||
        $args[] = '-it';
 | 
			
		||||
        $args[] = $containerName;
 | 
			
		||||
 | 
			
		||||
        array_push($args, ...$command);
 | 
			
		||||
 | 
			
		||||
        $cmdl = 'docker '.join(' ',array_map('escapeshellarg', $args));
 | 
			
		||||
 | 
			
		||||
        echo "$ {$cmdl}\n";
 | 
			
		||||
        passthru($cmdl);
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get running services
 | 
			
		||||
     */
 | 
			
		||||
    public function getRunningServices(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getServiceDataPath(array $service)
 | 
			
		||||
    {
 | 
			
		||||
        return $this->dataPath."/".$service['name'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								src/Registry/ServiceRegistry.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/Registry/ServiceRegistry.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Serverctl\Registry;
 | 
			
		||||
 | 
			
		||||
use RecursiveDirectoryIterator;
 | 
			
		||||
use RecursiveIteratorIterator;
 | 
			
		||||
use SplFileInfo;
 | 
			
		||||
 | 
			
		||||
class ServiceRegistry
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    private $services = [];
 | 
			
		||||
 | 
			
		||||
    public function __construct(array $paths)
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($paths as $path) {
 | 
			
		||||
            if (is_dir($path)) {
 | 
			
		||||
                $this->readPath($path);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function readPath(string $path)
 | 
			
		||||
    {
 | 
			
		||||
        $iter = new RecursiveIteratorIterator(
 | 
			
		||||
            new RecursiveDirectoryIterator(
 | 
			
		||||
                $path
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        /** @var SplFileInfo $iteminfo */
 | 
			
		||||
        foreach ($iter as $itempath=>$iteminfo) {
 | 
			
		||||
            if (!fnmatch("*.json", $itempath)) continue;
 | 
			
		||||
            $json = file_get_contents($itempath);
 | 
			
		||||
            $parsed = json_decode($json, true);
 | 
			
		||||
            $this->services[$itempath] = $parsed;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        usort($this->services, function ($a,$b) {
 | 
			
		||||
            return $a['name'] <=> $b['name'];
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function findServiceByName(string $name): ?array
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($this->services as $service) {
 | 
			
		||||
            if ($service['name'] === $name) return $service;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function findAllServices(): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->services;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user