{"id":14976063,"url":"https://github.com/gatographql/extensionstarter","last_synced_at":"2025-10-27T18:30:22.232Z","repository":{"id":195481374,"uuid":"692977128","full_name":"GatoGraphQL/ExtensionStarter","owner":"GatoGraphQL","description":"GitHub template repository to develop and release your extensions for Gato GraphQL","archived":false,"fork":false,"pushed_at":"2024-10-25T03:06:00.000Z","size":2095,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-25T06:16:24.356Z","etag":null,"topics":["graphql","graphql-schema","graphql-server","php","starter","starter-project","starter-template","wordpress","wordpress-plugin"],"latest_commit_sha":null,"homepage":"https://gatographql.com","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GatoGraphQL.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-18T05:16:13.000Z","updated_at":"2024-10-25T03:06:03.000Z","dependencies_parsed_at":"2023-10-02T01:36:53.282Z","dependency_job_id":"8e73a2ce-a3d2-482c-ad24-035dacfba80c","html_url":"https://github.com/GatoGraphQL/ExtensionStarter","commit_stats":{"total_commits":1279,"total_committers":1,"mean_commits":1279.0,"dds":0.0,"last_synced_commit":"ae4401eb4960c6c10c65ccf0499a7866d8d6f268"},"previous_names":["gatographql/extensionstarter"],"tags_count":40,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GatoGraphQL%2FExtensionStarter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GatoGraphQL%2FExtensionStarter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GatoGraphQL%2FExtensionStarter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GatoGraphQL%2FExtensionStarter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GatoGraphQL","download_url":"https://codeload.github.com/GatoGraphQL/ExtensionStarter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238536054,"owners_count":19488643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","graphql-schema","graphql-server","php","starter","starter-project","starter-template","wordpress","wordpress-plugin"],"created_at":"2024-09-24T13:53:14.614Z","updated_at":"2025-10-27T18:30:22.225Z","avatar_url":"https://github.com/GatoGraphQL.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/GatoGraphQL/GatoGraphQL/master/assets/GatoGraphQL-logo.webp\"/\u003e\u003c/p\u003e\n\n![Unit tests](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/unit_tests.yml/badge.svg)\n![Downgrade PHP tests](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/downgrade_php_tests.yml/badge.svg)\n![Scoping tests](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/scoping_tests.yml/badge.svg)\n![Generate plugins](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/generate_plugins.yml/badge.svg)\n![PHPStan](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/phpstan.yml/badge.svg)\n\n\u003c!--\n@gatographql-project-info\n\nShow a badge for the integration tests against InstaWP\n\n@gatographql-project-action-maybe-required\n\nIf these tests are enabled, add the badge code:\n\n![Integration tests](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/integration_tests.yml/badge.svg)\n--\u003e\n\n# Gato GraphQL - Extension Starter\n\nGato GraphQL extensions add functionality and expand the GraphQL schema provided by [Gato GraphQL](https://github.com/GatoGraphQL/GatoGraphQL).\n\n**This template repository helps you kickstart a GitHub repo, to develop, test and release your own extensions for Gato GraphQL.**\n\n\u003c!-- To learn about the features provided by the multi-monorepo architecture on this starter project, visit [Multi-Monorepo (Architecture of the Extension Starter)](docs/Multi-Monorepo_Architecture.md). --\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eTrivia fact 🤔\u003c/summary\u003e\n\n_All extensions from [gatographql.com/extensions](https://gatographql.com/extensions/) are hosted on a monorepo created from `GatoGraphQL/ExtensionStarter` 🚀_\n\n\u003c/details\u003e\n\n## Requirements\n\n- PHP 8.1\n- [Lando](https://lando.dev/)\n- [Composer](https://getcomposer.org/)\n\n### Recommended to use\n\n- [XDebug](https://xdebug.org/) (integrated out of the box when using [VSCode](https://code.visualstudio.com/) and the [PHP Debug](https://marketplace.visualstudio.com/items?itemName=xdebug.php-debug) addon for VSCode)\n\n## Create your Extension Project\n\nFollow these steps:\n\n### Create your repo from this GitHub template\n\n- Click on `Use this template` → `Create a new repository`\n- Select the GitHub owner, and choose a proper name for your repository (eg: `my-account/GatoGraphQLExtensionsForMyCompany`)\n- Choose if to make it Public or Private\n- Click on `Create repository`\n\nAs a result, a copy of this template will have been created under your GitHub repo:\n\n![GitHub repo from template](assets/img/repo-from-template.webp)\n\n### Clone your repo locally\n\nClone your repository in your local drive using the `--recursive` option (needed to clone Git submodule `GatoGraphQL/GatoGraphQL`):\n\n```bash\ngit clone --recursive https://github.com/my-account/GatoGraphQLExtensionsForMyCompany\n```\n\n### Install Composer dependencies\n\nStep on the project's folder:\n\n```bash\ncd {project folder}\n```\n\nAnd then run:\n\n```bash\ncd submodules/GatoGraphQL \u0026\u0026 composer install \u0026\u0026 cd ../.. \u0026\u0026 composer install\n```\n\n### Initialize the Project\n\nThis step will replace all the initial placeholder strings in the extension starter with the values corresponding to your project.\n\nInput your values in the command below and run:\n\n```bash\ncomposer initialize-project -- \\\n  --php-namespace-owner=MyCompanyName \\\n  --my-company-name=\"My Company Name\" \\\n  --my-company-email=email@mycompany.com \\\n  --my-company-website=https://www.mycompany.com\n```\n\nThese arguments (and additional ones, see below) are optional. If any of them is not provided, a default value is computed from the configuration in Git and the GitHub repo.\n\n\u003cdetails\u003e\n\n\u003csummary\u003ePrint arguments and default values for \u003ccode\u003einitialize-project\u003c/code\u003e\u003c/summary\u003e\n\nTo see the default values for the arguments, run:\n\n```bash\ncomposer initialize-project -- --dry-run\n```\n\nTo print all the arguments for the `initialize-project` command, run:\n\n```bash\ncomposer initialize-project -- --help\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eView all \u003ccode\u003einitialize-project\u003c/code\u003e command arguments\u003c/summary\u003e\n\n| Option | Description |\n| --- | --- |\n| `--git-base-branch` | Base branch of the GitHub repository where this project is hosted. If not provided, this value is retrieved using `git` |\n| `--git-user-name` | Git user name, to \"split\" code and push it to a different repo when merging a PR. If not provided, this value is retrieved from the global `git` config |\n| `--git-user-email` | Git user email, to \"split\" code and push it to a different repo when merging a PR. If not provided, this value is retrieved from the global `git` config |\n| `--github-repo-owner` | Owner of the GitHub repository where this project is hosted (eg: \"GatoGraphQL\" in \"https://github.com/GatoGraphQL/ExtensionStarter\"). If not provided, this value is retrieved using `git` |\n| `--github-repo-name` | Name of the GitHub repository where this project is hosted (eg: \"ExtensionStarter\" in \"https://github.com/GatoGraphQL/ExtensionStarter\"). If not provided, this value is retrieved using `git` |\n| `--docs-git-base-branch` | Base branch of the (public) GitHub repository hosting the documentation for the extension, to access the images in PROD. If not provided, the value for option `git-base-branch` is used |\n| `--docs-github-repo-owner` | Owner of the (public) GitHub repository hosting the documentation for the extension, to access the images in PROD. If not provided, the value for option `github-repo-owner` is used |\n| `--docs-github-repo-name` | Name of the (public) GitHub repository hosting the documentation for the extension, to access the images in PROD. If not provided, the value for option `github-repo-name` is used |\n| `--php-namespace-owner` | PHP namespace owner to use in the codebase (eg: \"MyCompanyName\"). If not provided, the value from the \"github-repo-owner\" option is used |\n| `--composer-vendor` | Composer vendor to distribute the packages in the repo. If not provided, it is generated from the \"php-namespace-owner\" option |\n| `--my-company-name` | Name of the person or company owning the extension. If not provided, the value for option `git-user-name` is used |\n| `--my-company-email` | Email of the person or company owning the extension. If not provided, the value for option `git-user-email` is used |\n| `--my-company-website` | Website of the person or company owning the extension. If not provided, the GitHub repo for this project is used |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eBrowse documentation within the codebase\u003c/summary\u003e\n\nThe codebase contains snippets of documentation, to explain some feature or configuration.\n\nSearch for the following PHPDoc tags in the codebase:\n\n- `@gatographql-project-info`: Information on some aspect of the monorepo setup\n- `@gatographql-project-action-maybe-required`: Indicates if some feature can be enabled/disabled and how\n- `@gatographql-extension-info`: Information on some aspect of the extension setup\n- `@gatographql-example`: Provides an example from the upstream monorepo\n- `@gatographql-readonly-code`: Indicates that the code must not be changed, as it is automatically modified via some script\n\n\u003c/details\u003e\n\n### Review the License\n\nThe [license in the monorepo](LICENSE) is GPL v2.\n\nIf this this not your license, remove/replace this file.\n\n### Commit, Push and Tag the Initial Project\n\n\u003c!-- Review the changes applied to the codebase on the step above. If any value is not correct (eg: if the PHP namespace should be a different one), you can undo all changes (`git reset --hard HEAD`), and run `composer initialize-project` again providing the right values. --\u003e\n\nRun:\n\n```bash\ngit add . \u0026\u0026 git commit -m \"Initialized project\" \u0026\u0026 git push origin \u0026\u0026 git tag 0.0.0 \u0026\u0026 git push --tags\n```\n\nThis will commit the codebase to your GitHub repo, and tag it with version `0.0.0`. (This tag is needed to start incrementing the version automatically from now on.)\n\n## Run the webserver for DEV\n\n_(Instructions for running the webserver for PROD will be given further below.)_\n\nA Lando webserver is set-up and configured to develop the extensions in the monorepo.\n\n- Runs on PHP 8.1\n- It directly uses the source code on the repo\n- XDebug is enabled\n\nFollow these steps:\n\n### Build the Lando webserver for DEV\n\nRun (only the first time):\n\n```bash\ncomposer build-server\n```\n\nAfter a few minutes, the website will be available under `https://gatographql-{composer-vendor}-extensions.lndo.site`.\n\n(Or, if you have [Lando's proxy disabled](https://docs.lando.dev/core/v3/proxy.html#configuration), it will be available under `https://localhost:{randomPort}`.)\n\n\u003c!-- (`{composer-vendor}` is an argument to the `initialize-project` command above; its default value is generated from the `php-namespace-owner` option.) --\u003e\n\nThe URL is printed on the console under `APPSERVER URLS` (you will need to scroll up):\n\n![Lando webserver URL](assets/img/lando-webserver-url.webp)\n\nTo print the URL again, run:\n\n```bash\ncomposer server-info\n```\n\n_(This command also prints other useful data, including the port to connect to the MySql database, so you can visualize and edit the data in the DB using an external client, such as MySQLWorkbench.)_\n\n\u003cdetails\u003e\n\n\u003csummary\u003eWhat plugins are installed in the webserver? 🤔\u003c/summary\u003e\n\nAll plugins hosted on the \"upstream\" monorepo:\n\n- [Gato GraphQL](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/GatoGraphQLForWP/plugins/gatographql/gatographql.php)\n- [Gato GraphQL - Testing](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/GatoGraphQLForWP/phpunit-plugins/gatographql-testing/gatographql-testing.php)\n- [Gato GraphQL - Testing Schema](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/GatoGraphQLForWP/plugins/testing-schema/gatographql-testing-schema.php)\n\n(The last two are utilities to run integration tests for Gato GraphQL. Among others, they provide CPT \"dummy-cpt\" and custom taxonomies \"dummy-category\" and \"dummy-tag\").\n\nAll plugins hosted on this \"downstream\" starter monorepo:\n\n- [Gato GraphQL - Hello Dolly](https://github.com/GatoGraphQL/ExtensionStarter/blob/main/layers/GatoGraphQLForWP/plugins/hello-dolly/gatographql-hello-dolly.php)\n\nAll the WordPress integration plugins, required by the extensions\n\n- [Hello Dolly](https://wordpress.org/plugins/hello-dolly/)\n\nBesides, some initial configuration is applied to the Gato GraphQL plugin Settings. For instance, the single endpoint is enabled (it is disabled by default).\n\n\u003c/details\u003e\n\n### Log-in to the `wp-admin`\n\nCredentials for `https://gatographql-{composer-vendor}-extensions.lndo.site/wp-admin/`:\n\n- Username: `admin`\n- Password: `admin`\n\n### Open the Gato GraphQL plugin in the `wp-admin`\n\nClick on the Gato GraphQL link on the menu to open the GraphiQL client, and execute the following GraphQL query:\n\n```graphql\n{\n  helloDolly\n}\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eWhere does field \u003ccode\u003ehelloDolly\u003c/code\u003e come from? 🤔\u003c/summary\u003e\n\nField `Root.helloDolly` is added to the GraphQL schema by the \"Gato GraphQL - Hello Dolly\" demo extension hosted in this monorepo.\n\nThis field returns any quote from the Hello Dolly song. The following query:\n\n```graphql\n{\n  helloDolly\n}\n```\n\nwill return:\n\n```json\n{\n  \"data\": {\n    \"helloDolly\": \"Dolly, never go away again\"\n  }\n}\n```\n\n...or any of the other lines in that song.\n\n\u003c/details\u003e\n\nIf the installation of the starter was successful, you will receive a response:\n\n![\"Hello Dolly\" in the webserver](assets/img/graphiql-hello-dolly.webp)\n\n### Start the Lando webserver for DEV\n\nBuilding the webserver (above) is needed only the first time.\n\nFrom then on, run:\n\n```bash\ncomposer init-server\n```\n\n### Run Integration Tests for DEV\n\nRun:\n\n``` bash\ncomposer integration-test\n```\n\n## Create an Extension Plugin\n\nThis section explains all the steps needed to add an extension plugin to the monorepo.\n\n### Run command to create the extension\n\nRun:\n\n```bash\ncomposer create-extension -- \\\n  --extension-name=\"Extension name\"\n```\n\nIf the extension is an integration for some WordPress plugin, run:\n\n```bash\ncomposer create-extension -- \\\n  --integration-plugin-name=\"Plugin name\" \\\n  --integration-plugin-file=slug/file.php \\\n  --integration-plugin-version-constraint=\"...\"\n```\n\nFor instance, to build an integration for WooCommerce with version 8 or above, run:\n\n```bash\ncomposer create-extension -- \\\n  --integration-plugin-name=WooCommerce \\\n  --integration-plugin-file=woocommerce/woocommerce.php \\\n  --integration-plugin-version-constraint=\"^8\"\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003ePrint arguments for \u003ccode\u003ecreate-extension\u003c/code\u003e\u003c/summary\u003e\n\nTo print all the arguments for the `create-extension` command, run:\n\n```bash\ncomposer create-extension -- --help\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003eView all \u003ccode\u003ecreate-extension\u003c/code\u003e command arguments\u003c/summary\u003e\n\n| Option | Description |\n| --- | --- |\n| `--template` |  Template to use to create the extension plugin, from available options: \"basic\" [default: \"basic\"] |\n| `--integration-plugin-file` | Integration plugin file (eg: \"woocommerce/woocommerce.php\" for the WooCommerce plugin), if any |\n| `--integration-plugin-version-constraint` | Minimum required version of the integration plugin, in semver (eg: \"^8.1\"). If not provided, any version is accepted [default: \"*\"] |\n| `--integration-plugin-name` | Name of the integration plugin (eg: WooCommerce). If not provided, it is generated from the integration plugin slug |\n| `--extension-name` | Extension plugin name. If not provided, it is calculated from the integration plugin name |\n| `--extension-slug` | Slug of the extension plugin. If not provided, it is generated from the integration plugin's slug, or from the \"extension-name\" option |\n| `--extension-classname` | PHP classname to append to classes in the extension plugin. If not provided, it is generated from the \"extension-slug\" option |\n\n\u003c/details\u003e\n\n### Commit + Rebuild Lando webservers\n\nAfter running the command above, execute the following bash commands to complete the process:\n\n```bash\n# (Git commit/push the changes to the repo)\ngit add . \u0026\u0026 git commit -m \"Created new extension\" \u0026\u0026 git push origin\n\n# (Rebuild the Lando webserver for DEV)\ncomposer rebuild-app-and-server\n\n# (Install/activate the added plugins on the DEV webserver)\ncomposer activate-extension-plugins\n\n# (Install/activate the integration plugin on the PROD webserver) \u003c= if already created\ncomposer activate-extension-plugins-prod\n```\n\n## Complete the Extension Plugin\n\nThe new extension plugin created with the command above contains the comment `@gatographql-extension-todo` indicating that there are items to complete.\n\n### Documentation\n\nComplete the documentation for your module, under file:\n\n`layers/GatoGraphQLForWP/plugins/{extension-slug}/docs/modules/schema-{extension-slug}/en.md`.\n\n### Integration Tests for the Extension Schema\n\nTo test the schema elements added by the extension, complete the GraphQL document:\n\n`layers/GatoGraphQLForWP/plugins/{extension-slug}/tests/Integration/fixture-schema/extension-schema.gql`\n\n(and the JSON response, in the same folder).\n\n### Stubs for your integration plugin\n\nIf integrating with another WordPress plugin, you will need to complete the file with stubs for that plugin (to avoid errors with PHPStan/Rector), under:\n\n`stubs/wpackagist-plugin/{integration-plugin}/stubs.php`.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eWhat are stubs needed for? And how to generate them? 🤔\u003c/summary\u003e\n\nStubs are placeholders to \"load\" a functionality that is otherwise missing (because the plugin that contains it is not loaded when running unit tests and static analysis).\n\nStubs avoid PHPStan producing an error when analyzing packages which invoke classes, methods, constants, etc, from 3rd-party WordPress plugins. (Eg: [the stubs file for `hello-dolly`](stubs/wpackagist-plugin/hello-dolly/stubs.php) avoids an error from [calling `hello_dolly_get_lyric()` in the field resolver](layers/GatoGraphQLForWP/packages/hello-dolly-schema/src/FieldResolvers/ObjectType/RootObjectTypeFieldResolver.php)).\n\nIt also avoids Rector from producing errors when downgrading the code.\n\nStubs must be added for all the WordPress integration plugins for which there is an extension in the monorepo (eg: WooCommerce, Yoast SEO, etc).\n\nThe stub files, if not already available for that WordPress plugin, can be generated using [`php-stubs/generator`](https://github.com/php-stubs/generator) (check also [`php-stubs/wordpress-stubs`](https://github.com/php-stubs/wordpress-stubs)).\n\n\u003c/details\u003e\n\n\u003c!-- Point to a .gql test\nPoint to a .gql test when disabling the plugin\nPoint to a .gql test when disabling the module\n\nRun hello-dolly tests:\n  phpunit layers/GatoGraphQLForWP/plugins/hello-dolly/tests/Integration/SchemaFixtureWebserverRequestTest.php\n  phpunit layers/GatoGraphQLForWP/plugins/hello-dolly/tests/Integration/EnableDisablePluginFixtureWordPressAuthenticatedUserWebserverRequestTest.php\n  phpunit layers/GatoGraphQLForWP/plugins/hello-dolly/tests/Integration/FixtureThirdPartyPluginDependencyWordPressAuthenticatedUserWebserverRequestTest.php\nIndicate the \"enabled.json\" and \"only-one-enabled.json\" items fail because of the random nature of the test\n  But I kept them only for documentation, for your own tests\n  alternatively with regex, could use test:\n    submodules/GatoGraphQL/layers/GatoGraphQLForWP/phpunit-packages/gatographql/tests/Integration/AccessPrivatePersistedQuerySourceByAdminQueryExecutionFixtureWebserverRequestTest.php\nExplain what each of them does! --\u003e\n\n\u003c!--\n\n_Doing this process manually is tedious and error-prone. We are already [working on a `create-extension` command](https://github.com/GatoGraphQL/ExtensionStarter/issues/73) to automate this process._\n\n### Creating the extension manually\n\nThis starter project includes one fully-working extension plugin as demo: \"Gato GraphQL - Hello Dolly\", an integration for the [Hello Dolly](https://wordpress.org/plugins/hello-dolly/) plugin.\n\nYou will need to duplicate the files and folders for this extension, search for the `\"Hello Dolly\"` name (and variants `HelloDolly` and `hello-dolly`), and replace it with your extension's name (using `\"Your Extension\"` in the instructions below, replace this value with your own).\n\nDuplicate folders:\n\n- `layers/GatoGraphQLForWP/packages/hello-dolly-schema` into `layers/GatoGraphQLForWP/packages/your-extension-schema`\n- `layers/GatoGraphQLForWP/plugins/hello-dolly` into `layers/GatoGraphQLForWP/packages/your-extension`\n\nDuplicate files:\n\n- `config/rector/downgrade/plugins/hello-dolly/rector.php` into `config/rector/downgrade/your-extension/rector.php`\n- `src/Config/Rector/Downgrade/Configurators/HelloDollyContainerConfigurationService.php` into `src/Config/Rector/Downgrade/Configurators/YourExtensionContainerConfigurationService.php`\n\nWithin the duplicated folders and files above, search and replace all occurrences of:\n\n- `Hello Dolly` =\u003e `Your Extension`\n- `HelloDolly` =\u003e `YourExtension`\n- `hello-dolly` =\u003e `your-extension`\n- `HELLO_DOLLY` =\u003e `YOUR_EXTENSION`\n\nAlso rename the following files in a duplicate folder:\n\n- `layers/GatoGraphQLForWP/plugins/your-extension/gatographql-hello-dolly.php` into `layers/GatoGraphQLForWP/plugins/your-extension/gatographql-your-extension.php`\n- `layers/GatoGraphQLForWP/plugins/your-extension/languages/gatographql-hello-dolly.pot` into `layers/GatoGraphQLForWP/plugins/your-extension/languages/gatographql-your-extension.pot`\n\nEdit file `layers/GatoGraphQLForWP/plugins/your-extension/gatographql-your-extension.php`, and adapt this PHP code:\n\n```php\n$requiredPluginFile = 'your-extension/hello.php';\n$requiredPluginVersion = '^1.7';\n```\n\n...with the main file for the WordPress integration plugin, and the version constraint needed for that plugin.\n\nFor instance, for an extension for WooCommerce `v8` and above:\n\n```php\n$requiredPluginFile = 'woocommerce/woocommerce.php';\n$requiredPluginVersion = '^8';\n```\n\nEdit file `layers/GatoGraphQLForWP/plugins/your-extension/src/GatoGraphQLExtension.php`, and (similar to above) replace:\n\n```php\nreturn [\n  'your-extension/hello.php',\n];\n```\n\n...with your integration plugin's main file, such as:\n\n```php\nreturn [\n  'woocommerce/woocommerce.php'\n];\n```\n\nAnd likewise, edit file `layers/GatoGraphQLForWP/plugins/your-extension/src/ModuleResolvers/SchemaTypeModuleResolver.php` and adapt the main file and version constraint here:\n\n```php\nnew DependedOnActiveWordPressPlugin(\n  'Your Extension',\n  'your-extension/hello.php',\n  '^1.7',\n),\n```\n\nEdit files:\n\n- `layers/GatoGraphQLForWP/packages/your-extension-schema/composer.json`\n- `layers/GatoGraphQLForWP/plugins/your-extension/composer.json`\n\n...and update entry `\"wpackagist-plugin/your-extension\"` under `require-dev`:\n\n```json\n{\n  \"require-dev\": {\n    \"wpackagist-plugin/your-extension\": \"^1.7\"\n  }\n}\n```\n\n...like this:\n\n- Rename entry `\"wpackagist-plugin/your-extension\"` to `\"wpackagist-plugin/your-wordpress-integration-plugin\"`, where `your-wordpress-integration-plugin` is the slug of the WordPress integration plugin for the extension (eg: `woocommerce`, `wordpress-seo`, etc)\n- Replace the version constraint `\"^1.7\"` to the one needed for that integration plugin\n\nEdit file `layers/GatoGraphQLForWP/packages/your-extension-schema/phpstan.neon.dist`, replacing:\n\n```yaml\n- %currentWorkingDirectory%/stubs/wpackagist-plugin/your-extension/stubs.php\n```\n\n...with:\n\n```yaml\n- %currentWorkingDirectory%/stubs/wpackagist-plugin/your-wordpress-integration-plugin/stubs.php\n```\n\nEdit file `.vscode/launch.json` and, under entry `pathMappings` in the first item in `configurations`, add the following 2 lines (notice that `composer-vendor` will be the same value used when executing the `initialize-project` command):\n\n```json\n\"/app/wordpress/wp-content/plugins/gatographql-your-extension/vendor/composer-vendor/your-extension-schema\": \"${workspaceFolder}/layers/GatoGraphQLForWP/packages/your-extension-schema\",\n\"/app/wordpress/wp-content/plugins/gatographql-your-extension\": \"${workspaceFolder}/layers/GatoGraphQLForWP/plugins/your-extension\"\n```\n\ni.e. it will look like this:\n\n```json\n{\n  // ...\n  \"configurations\": [\n    {\n      \"name\": \"[Lando webserver] Listen for Xdebug\",\n      // ...\n      \"pathMappings\": {\n        \"/app/wordpress/wp-content/plugins/gatographql-hello-dolly/vendor/composer-vendor/hello-dolly-schema\": \"${workspaceFolder}/layers/GatoGraphQLForWP/packages/hello-dolly-schema\",\n        \"/app/wordpress/wp-content/plugins/gatographql-hello-dolly\": \"${workspaceFolder}/layers/GatoGraphQLForWP/plugins/hello-dolly\",\n\n        \"/app/wordpress/wp-content/plugins/gatographql-your-extension/vendor/composer-vendor/your-extension-schema\": \"${workspaceFolder}/layers/GatoGraphQLForWP/packages/your-extension-schema\",\n        \"/app/wordpress/wp-content/plugins/gatographql-your-extension\": \"${workspaceFolder}/layers/GatoGraphQLForWP/plugins/your-extension\"\n\n        // ...\n      }\n    }\n  ]\n}\n```\n\nCreate empty file `stubs/wpackagist-plugin/your-extension/stubs.php`, to be filled with stubs for all classes/functions/constants invoked on your WordPress integration plugin (eg: WooCommerce, Yoast SEO, etc).\n\nEdit file `src/Config/Symplify/MonorepoBuilder/DataSources/DataToAppendAndRemoveDataSource.php` and append the line of PHP code below, replacing `your-wordpress-integration-plugin` with the slug of the WordPress integration plugin for the extension (eg: `woocommerce`, `wordpress-seo`, etc):\n\n```php\n$dataToRemove['require-dev']['wpackagist-plugin/your-wordpress-integration-plugin'] = '*';\n```\n\ni.e. it will look like this:\n\n```php\npublic function getDataToRemove(): array\n{\n  $dataToRemove = parent::getDataToRemove();\n  $dataToRemove['require-dev']['wpackagist-plugin/hello-dolly'] = '*';\n  $dataToRemove['require-dev']['wpackagist-plugin/your-wordpress-integration-plugin'] = '*';\n  return $dataToRemove;\n}\n```\n\nEdit file `src/Config/Symplify/MonorepoBuilder/DataSources/PluginDataSource.php` and add a new entry under `$pluginConfigEntries` with the configuration for your extension:\n\n```php\n[\n  'path' =\u003e 'layers/GatoGraphQLForWP/plugins/your-extension',\n  'plugin_slug' =\u003e 'gatographql-your-extension',\n  'main_file' =\u003e 'gatographql-your-extension.php',\n  'rector_downgrade_config' =\u003e $this-\u003erootDir . '/config/rector/downgrade/your-extension/rector.php',\n  'exclude_files' =\u003e implode(' ', [\n      'docs/images/\\*',\n  ]),\n],\n```\n\nEdit file `webservers/gatographql-extensions/.lando.upstream.yml` and add the following lines:\n\n```yaml\n- ../../layers/GatoGraphQLForWP/plugins/your-extension:/app/wordpress/wp-content/plugins/gatographql-your-extension\n- ../../layers/GatoGraphQLForWP/packages/your-extension-schema:/app/wordpress/wp-content/plugins/gatographql-your-extension/vendor/composer-vendor/your-extension-schema\n```\n\ni.e. it will look like this:\n\n```yaml\nservices:\n  appserver:\n    overrides:\n      volumes:\n        - \u003e-\n          ../../layers/GatoGraphQLForWP/plugins/hello-dolly:/app/wordpress/wp-content/plugins/gatographql-hello-dolly\n        - \u003e-\n          ../../layers/GatoGraphQLForWP/packages/hello-dolly-schema:/app/wordpress/wp-content/plugins/gatographql-hello-dolly/vendor/composer-vendor/hello-dolly-schema\n        - \u003e-\n          ../../layers/GatoGraphQLForWP/plugins/your-extension:/app/wordpress/wp-content/plugins/gatographql-your-extension\n        - \u003e-\n          ../../layers/GatoGraphQLForWP/packages/your-extension-schema:/app/wordpress/wp-content/plugins/gatographql-your-extension/vendor/composer-vendor/your-extension-schema\n```\n\nEdit file `webservers/gatographql-extensions/composer.json` and add the following script `symlink-vendor-for-gatographql-your-extension-plugin` (which is a duplicate of script `symlink-vendor-for-gatographql-hello-dolly-plugin`):\n\n```json\n{\n  \"scripts\": {\n    // Add this entry:\n    \"symlink-vendor-for-gatographql-your-extension-plugin\": [\n      \"php -r \\\"copy('../../layers/GatoGraphQLForWP/plugins/your-extension/composer.json', '../../layers/GatoGraphQLForWP/plugins/your-extension/composer.local.json');\\\"\",\n      \"cd ../../ \u0026\u0026 vendor/bin/monorepo-builder symlink-local-package --config=config/monorepo-builder/symlink-local-package.php layers/GatoGraphQLForWP/plugins/your-extension/composer.local.json\",\n      \"COMPOSER=composer.local.json composer update --no-dev --working-dir=../../layers/GatoGraphQLForWP/plugins/your-extension\"\n    ]\n  }\n}\n```\n\n...also add a line calling `@symlink-vendor-for-gatographql-your-extension-plugin` in the `update-deps` script:\n\n```json\n{\n  \"scripts\": {\n    \"update-deps\": [\n      \"@symlink-vendor-for-gatographql-plugin\",\n      \"@symlink-vendor-for-gatographql-testing-schema-plugin\",\n      \"@symlink-vendor-for-gatographql-testing-plugin\",\n      \"@symlink-vendor-for-gatographql-hello-dolly-plugin\",\n      // Add this entry below:\n      \"@symlink-vendor-for-gatographql-your-extension-plugin\"\n    ]\n  }\n}\n```\n\n...and add entries for `your-extension` (as duplicates as the entries for `hello-dolly`) under the `optimize-autoloader` and `deoptimize-autoloader` scripts:\n\n```json\n{\n  \"scripts\": {\n    \"optimize-autoloader\": [\n        \"COMPOSER=composer.local.json composer dump-autoload --optimize --working-dir=../../submodules/GatoGraphQL/layers/GatoGraphQLForWP/plugins/gatographql\",\n        \"COMPOSER=composer.local.json composer dump-autoload --optimize --working-dir=../../submodules/GatoGraphQL/layers/GatoGraphQLForWP/phpunit-plugins/gatographql-testing\",\n        \"COMPOSER=composer.local.json composer dump-autoload --optimize --working-dir=../../submodules/GatoGraphQL/layers/GatoGraphQLForWP/plugins/testing-schema\",\n        \"COMPOSER=composer.local.json composer dump-autoload --optimize --working-dir=../../layers/GatoGraphQLForWP/plugins/hello-dolly\",\n        // Add this entry below:\n        \"COMPOSER=composer.local.json composer dump-autoload --optimize --working-dir=../../layers/GatoGraphQLForWP/plugins/your-extension\"\n    ],\n    \"deoptimize-autoloader\": [\n        \"COMPOSER=composer.local.json composer dump-autoload --working-dir=../../submodules/GatoGraphQL/layers/GatoGraphQLForWP/plugins/gatographql\",\n        \"COMPOSER=composer.local.json composer dump-autoload --working-dir=../../submodules/GatoGraphQL/layers/GatoGraphQLForWP/phpunit-plugins/gatographql-testing\",\n        \"COMPOSER=composer.local.json composer dump-autoload --working-dir=../../submodules/GatoGraphQL/layers/GatoGraphQLForWP/plugins/testing-schema\",\n        \"COMPOSER=composer.local.json composer dump-autoload --working-dir=../../layers/GatoGraphQLForWP/plugins/hello-dolly\",\n        // Add this entry below:\n        \"COMPOSER=composer.local.json composer dump-autoload --working-dir=../../layers/GatoGraphQLForWP/plugins/your-extension\"\n    ]\n  }\n}\n```\n\nEdit file `webservers/gatographql-extensions/setup-extensions/activate-plugins.sh` and add the following code, replacing `your-wordpress-integration-plugin` with the slug of the WordPress integration plugin for the extension (eg: `woocommerce`, `wordpress-seo`, etc):\n\n```bash\nif wp plugin is-installed your-wordpress-integration-plugin; then\n    wp plugin activate your-wordpress-integration-plugin\nelse\n    wp plugin install your-wordpress-integration-plugin --activate\nfi\n\nwp plugin activate gatographql-your-extension\n```\n\nEdit file `webservers/gatographql-extensions-for-prod/setup-extensions/activate-plugins.sh` and add the following code:\n\n```bash\nif wp plugin is-installed your-wordpress-integration-plugin; then\n    wp plugin activate your-wordpress-integration-plugin\nelse\n    wp plugin install your-wordpress-integration-plugin --activate\nfi\n\n# Activate own plugins\nif wp plugin is-installed gatographql-your-extension; then\n    wp plugin activate gatographql-your-extension\nelse\n    echo \"Please download the latest PROD version of the 'Gato GraphQL - Your Extension' plugin from your GitHub repo, and install it on this WordPress site\"\nfi\n```\n\nThat's it with the editing.\n\n---\n\nThen regenerate the monorepo configuration, by running:\n\n```bash\ncomposer update-monorepo-config\n```\n\nAnd regenerate the mapping for the Lando webserver for DEV, by running:\n\n```bash\ncomposer rebuild-app-and-server\n```\n\nNow, when loading the Lando webserver for DEV (under `https://gatographql-{composer-vendor}-extensions.lndo.site/wp-admin`), the new extension should be loaded and working (even though it doesn't contain any resolver yet). --\u003e\n\n## Extending the GraphQL Schema\n\nThis section provides examples from the codebase in the upstream `GatoGraphQL/GatoGraphQL` monorepo, demonstrating how to create the resolvers to extend the GraphQL schema (for fields, mutations, input objects, directives, etc).\n\nIn your code editor, copy the example file and paste it inside your extension folder (under the original folder structure), and adapt it to your needs:\n\n- Adapt its content accordingly\n- Inspect all services referenced inside the class, and verify if any of them must too be duplicated and adapted\n- Similarly, find all references to the original class (eg: using the [PHP Intelephense](https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client) addon for VSCode), and verify if any of them must also be duplicated and adapted\n\nYou must also define those services in the service container, by uncommenting the corresponding entries on configuration file `layers/GatoGraphQLForWP/packages/{extension-slug}-schema/config/schema-services.yaml`.\n\n(Check [`submodules/GatoGraphQL/layers/CMSSchema/packages/users/config/schema-services.yaml`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/users/config/schema-services.yaml) for an example.)\n\n\u003c!-- _In the future, we expect to have [commands to automatically generate the PHP code inside the extension](https://github.com/GatoGraphQL/ExtensionStarter/issues/74)._ --\u003e\n\n\u003c!-- ### General to GraphQL --\u003e\n\n### Type Resolver\n\n_(From this section downwards, these features are general to GraphQL.)_\n\n`User` type:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/users/src/TypeResolvers/ObjectType/UserObjectTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/users/src/TypeResolvers/ObjectType/UserObjectTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-type-resolver\n```\n--\u003e\n\n### Field Resolver\n\nFields `name`, `displayName`, and others, for the `User` type:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/users/src/FieldResolvers/ObjectType/UserObjectTypeFieldResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/users/src/FieldResolvers/ObjectType/UserObjectTypeFieldResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-field-resolver\n```\n--\u003e\n\n### Mutation Resolver\n\nMutation `createPost`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/post-mutations/src/FieldResolvers/ObjectType/RootObjectTypeFieldResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/post-mutations/src/FieldResolvers/ObjectType/RootObjectTypeFieldResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-mutation-resolver\n```\n--\u003e\n\n### Custom Scalar Resolver\n\nCustom scalar `Email`:\n\n[`submodules/GatoGraphQL/layers/Schema/packages/schema-commons/src/TypeResolvers/ScalarType/EmailScalarTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/Schema/packages/schema-commons/src/TypeResolvers/ScalarType/EmailScalarTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-custom-scalar-resolver\n```\n--\u003e\n\n### Enum Resolver\n\nEnum `CommentTypeEnum`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/comments/src/TypeResolvers/EnumType/CommentTypeEnumTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/comments/src/TypeResolvers/EnumType/CommentTypeEnumTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-enum-resolver\n```\n--\u003e\n\n### Interface Resolver\n\nInterface `CustomPostInterfaceTypeResolver`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/customposts/src/TypeResolvers/InterfaceType/CustomPostInterfaceTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/customposts/src/TypeResolvers/InterfaceType/CustomPostInterfaceTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-interface-resolver\n```\n--\u003e\n\n### Union Type-Resolver\n\nUnion type `CustomPostUnionTypeResolver`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/customposts/src/TypeResolvers/UnionType/CustomPostUnionTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/customposts/src/TypeResolvers/UnionType/CustomPostUnionTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-union-type-resolver\n```\n--\u003e\n\n### Input Object Resolver\n\nInput Object `UserSortInput`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/users/src/TypeResolvers/InputObjectType/UserSortInputObjectTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/users/src/TypeResolvers/InputObjectType/UserSortInputObjectTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-input-object-resolver\n```\n--\u003e\n\n### Oneof Input Object Resolver\n\nOneof Input Object `UserByInput`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/users/src/TypeResolvers/InputObjectType/UserByOneofInputObjectTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/users/src/TypeResolvers/InputObjectType/UserByOneofInputObjectTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-oneof-input-object-resolver\n```\n--\u003e\n\n### Directive Resolver\n\nDirective `@skip`:\n\n[`submodules/GatoGraphQL/layers/Engine/packages/engine/src/DirectiveResolvers/SkipFieldDirectiveResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/Engine/packages/engine/src/DirectiveResolvers/SkipFieldDirectiveResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-directive-resolver\n```\n--\u003e\n\n\u003c!-- ### Specific to Gato GraphQL --\u003e\n\n### Global Field Resolver\n\n_(From this section downwards, these features are specific to Gato GraphQL.)_\n\nField `__typename`:\n\n[`submodules/GatoGraphQL/layers/GraphQLByPoP/packages/graphql-server/src/FieldResolvers/ObjectType/GlobalObjectTypeFieldResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/GraphQLByPoP/packages/graphql-server/src/FieldResolvers/ObjectType/GlobalObjectTypeFieldResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-global-field-resolver\n```\n--\u003e\n\n### Enum String Resolver\n\nEnum String `CustomPostEnumString`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/customposts/src/TypeResolvers/EnumType/CustomPostEnumStringScalarTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/customposts/src/TypeResolvers/EnumType/CustomPostEnumStringScalarTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-enum-string-resolver\n```\n--\u003e\n\n### Error Payload Union Type Resolver\n\nError Payload Union Type `RootAddCommentToCustomPostMutationErrorPayloadUnion`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/comment-mutations/src/TypeResolvers/UnionType/RootAddCommentToCustomPostMutationErrorPayloadUnionTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/comment-mutations/src/TypeResolvers/UnionType/RootAddCommentToCustomPostMutationErrorPayloadUnionTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-error-payload-union-type-resolver\n```\n--\u003e\n\n\u003c!-- ### Composable Directive Resolver\n\n@todo\n\nRun:\n\n```bash\ncomposer create-composable-directive-resolver\n```\n--\u003e\n\n\u003c!-- ### Modifying Field and Directive Resolvers --\u003e\n\n### Adding Nested Mutations\n\nMutation `Post.update`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/post-mutations/src/FieldResolvers/ObjectType/PostObjectTypeFieldResolver.php`](submodules/ExtensionStarter/submodules/GatoGraphQL/layers/CMSSchema/packages/post-mutations/src/FieldResolvers/ObjectType/PostObjectTypeFieldResolver.php)\n\n### Field Arguments to filter data\n\nField `Root.comments`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/comments/src/FieldResolvers/ObjectType/RootObjectTypeFieldResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/comments/src/FieldResolvers/ObjectType/RootObjectTypeFieldResolver.php)\n\n\u003c!-- ### Validating Constraints for Field and Directive Arguments\n\n@todo --\u003e\n\n\u003c!-- ### Versioning Fields and Directives\n\n@todo --\u003e\n\n\u003c!-- ### Specific for WordPress --\u003e\n\n### Custom Post Type - Type Resolver\n\n_(From this section downwards, these features are specific to WordPress.)_\n\nCustom Post Type `Page`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/pages/src/TypeResolvers/ObjectType/PageObjectTypeResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/pages/src/TypeResolvers/ObjectType/PageObjectTypeResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-custom-post-type-resolver\n```\n--\u003e\n\n### Custom Post Type - Field Resolver\n\nField `CustomPost.author`:\n\n[`submodules/GatoGraphQL/layers/CMSSchema/packages/users/src/ConditionalOnModule/CustomPosts/FieldResolvers/ObjectType/CustomPostObjectTypeFieldResolver.php`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/layers/CMSSchema/packages/users/src/ConditionalOnModule/CustomPosts/FieldResolvers/ObjectType/CustomPostObjectTypeFieldResolver.php)\n\n\u003c!--\nRun:\n\n```bash\ncomposer create-custom-post-type-field-resolver\n```\n--\u003e\n\n\u003c!-- ## Creating Tests\n\n### Unit Tests\n\n@todo\n\n### Integration Tests\n\n@todo --\u003e\n\n## Release your extension plugins for PROD\n\nThe monorepo includes scripts that completely automate the process of releasing the extension plugins in the monorepo.\n\nFollow these steps:\n\n### Set the \"Workflow permissions\" to \"Read and write\" in your repo settings\n\n_(This is done only the first time, after creating the repo)_\n\nOn your repo's \"Settings \u003e Actions \u003e General \u003e Workflow permissions\", select option `Read and write permissions`.\n\nThis will enable uploading the generated artifacts when creating a new release.\n\n### Tag the monorepo as `patch`, `minor` or `major`\n\nChoose which version you will be releasing. The same version will be applied to all plugins in the monorepo.\n\n_(Given that the current version is `0.0.0`...)_\n\nTo release version `0.0.1`, run:\n\n```bash\ncomposer release-patch\n```\n\nTo release version `0.1.0`, run:\n\n```bash\ncomposer release-minor\n```\n\nTo release version `1.0.0`, run:\n\n```bash\ncomposer release-major\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eWhat do these commands do? 🤔\u003c/summary\u003e\n\nExecuting these commands will first prepare the repo for PROD:\n\n- Update the version (in the plugin file's header, readme.txt's Stable tag, others) for all the extension plugins in the monorepo\n- Update the documentation image URLs to point to that tag, under `raw.githubusercontent.com`\n- Commit and push\n- Git tag with the version, and push tag to GitHub\n\nAnd then, it will prepare the repo for DEV again:\n\n- Update the version to the next DEV version (next semver + `-dev`)\n- Commit and push\n\n\u003c/details\u003e\n\nTo preview running the command without actually executing it, append `-- --dry-run`:\n\n```bash\ncomposer release-patch -- --dry-run\n```\n\n### Create release from tag in GitHub\n\nAfter tagging the repo on the step above, we must create a release from the tag to generate the extension plugins for production.\n\nTo create the release, head over to the `tags` page in your GitHub repo (`https://github.com/my-account/GatoGraphQLExtensionsForMyCompany/tags`), and click on the new tag (eg: `0.1.0`).\n\nThen, on the tag page, click on `Create release from tag`, and then add a title and content, and submit the form.\n\n![Create release from tag](assets/img/create-release-from-tag.webp)\n\nThis will trigger the [`generate_plugins.yml`](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/generate_plugins.yml) workflow, which will generate the extension plugins and attach them as assets to the tag page.\n\nFor instance, after tagging Gato GraphQL with `1.0.9`, the tag page [GatoGraphQL/GatoGraphQL/releases/tag/1.0.9](https://github.com/GatoGraphQL/GatoGraphQL/releases/tag/1.0.9) had the following assets attached to it:\n\n- `gatographql-1.0.9.zip`\n- `gatographql-testing-1.0.9.zip`\n- `gatographql-testing-schema-1.0.9.zip`\n\n### Install the extension in the PROD webserver\n\nOnce the extension plugin has been generated, install it on the PROD webserver to test it, whether manually or using WP-CLI.\n\nUsing WP-CLI, if your repo is `my-account/GatoGraphQLExtensionsForMyCompany` and you have released version `0.1.0`, run:\n\n```bash\n$ cd webservers/gatographql-extensions-for-prod\n$ lando wp plugin install https://github.com/my-account/GatoGraphQLExtensionsForMyCompany/releases/latest/download/gatographql-hello-dolly-0.1.0.zip --force --activate\n$ cd ../..\n```\n\n### Query the extension in the `wp-admin`\n\nOnce you've installed the release on the Lando webserver for PROD, log-in to the `wp-admin`, access the GraphiQL client, and execute the following GraphQL query:\n\n```graphql\n{\n  helloDolly\n}\n```\n\nIf the release was generated successfully, you will receive a response:\n\n![\"Hello Dolly\" in the webserver for PROD](assets/img/graphiql-hello-dolly-prod.webp)\n\n## Run the webserver for PROD\n\nA Lando webserver is set-up and configured to test the released extension plugins, generated by GitHub Actions.\n\n- Runs on PHP 7.4\n- You must download the generated plugins for PROD (from GitHub Actions) and install them on the webserver\n- XDebug is not enabled\n\nFollow these steps:\n\n### Build the Lando webserver for PROD\n\nRun (only the first time):\n\n```bash\ncomposer build-server-prod\n```\n\nAfter a few minutes, the website will be available under `https://gatographql-{composer-vendor}-extensions-for-prod.lndo.site`.\n\n(The URL is the same one as for DEV above, plus appending `-for-prod` to the domain name.)\n\nTo print the URL again, run:\n\n```bash\ncomposer server-info-prod\n```\n\nThe `wp-admin` login credentials are the same ones as for DEV.\n\n### Start the Lando webserver for PROD\n\nBuilding the webserver (above) is needed only the first time.\n\nFrom then on, run:\n\n```bash\ncomposer init-server-prod\n```\n\n### Run Integration Tests for PROD\n\nRun:\n\n``` bash\ncomposer integration-test-prod\n```\n\n\u003c!-- ### Adding 3rd-party Composer Dependencies\n\n```json\n{\n  \"replace\": {\n    \"pop-schema/schema-commons\": \"self.version\"\n  }\n}    \n```\n\n@todo\n\n#### Scoping\n\nFix everything 4 packages:\n\thello-gato-schema\n\thello-gato-schema-wp\n\thello-gato-schema-mutations\n\thello-gato-schema-mutations-wp\nBecause of scoping!\n\tIndicate in instructions\n\ti.e. If the plugin needs 3rd-party libraries, these must be scoped\n\t\tSo these must be referenced under hello-gato-schema\n\t\tnever under hello-gato-schema-wp, because it has WP code, and it can't be scoped\n\nDocument:\n\n// Exclude all libraries for WordPress\n// 1. Exclude libraries ending in \"-wp\" from general packages\n\nAlso:\n\nFinder::create()-\u003eappend([\n  convertRelativeToFullPath('vendor/getpop/root-wp/src/Module.php'),\n  convertRelativeToFullPath('vendor/getpop/root-wp/src/Hooks/SetupCortexRoutingHookSet.php'),\n])\n\n### Creating Internal Packages\n\nExplain why we manage them with packages\n  Create 2 modules, 1 for mutations\n\nInput all these in:\n\t.vscode/launch.json\n\t.lando.base.yml --\u003e\n\n## Development Tips\n\n### Purging the cache\n\nWhen developing an extension and testing it in the DEV webserver, whenever we create a new PHP service or modify the signature of an existing one (such as the PHP classname), we need to purge the container cache.\n\nRun:\n\n```bash\ncomposer purge-cache\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eHow does Gato GraphQL use a service container? 🤔\u003c/summary\u003e\n\nThe Gato GraphQL plugin uses a service container (via the [Symfony DependencyInjection](https://symfony.com/doc/current/components/dependency_injection.html) library), to manage all services in PHP.\n\nServices are PHP classes, and must be defined in configuration files `services.yaml` and `schema-services.yaml` to be injected into the container.\n\nThe first time the application is invoked, the container gathers all injected services and compiles them, generating a single PHP file that is loaded in the application.\n\nGenerating this file can take several seconds. To avoid waiting for this time on each request, the Gato GraphQL plugin caches this file after it has been generated the first time.\n\nThe container needs to be purged whenever a service is created, or an existing one updated or removed.\n\n(In production, the Gato GraphQL plugin purges the cache whenever a new extension plugin is activated, or when the plugin Settings are updated. During development, it can in addition be triggered manually, by running `composer purge-cache`.)\n\nThis applies to resolvers (type resolvers, field resolvers, directive resolvers, and any other resolver that gives shape to the GraphQL schema), as these are PHP services. Whenever a resolver is added or removed, or is updated in such a way that modifies the GraphQL schema, the cached container must be purged.\n\nSome example resolvers are:\n\n- `String` type: [`StringScalarTypeResolver`](https://github.com/GatoGraphQL/GatoGraphQL/blob/1.0.0/layers/Engine/packages/component-model/src/TypeResolvers/ScalarType/StringScalarTypeResolver.php)\n- Field `User.name` (and others): [`UserObjectTypeFieldResolver`](https://github.com/GatoGraphQL/GatoGraphQL/blob/1.0.0/layers/CMSSchema/packages/users/src/FieldResolvers/ObjectType/UserObjectTypeFieldResolver.php)\n- `@skip` directive: [`SkipFieldDirectiveResolver`](https://github.com/GatoGraphQL/GatoGraphQL/blob/1.0.0/layers/Engine/packages/engine/src/DirectiveResolvers/SkipFieldDirectiveResolver.php)\n\n\u003c/details\u003e\n\n### Regenerating the monorepo configuration\n\nAfter adding a plugin or package to the monorepo, the configuration (containing all the packages) must be regenerated.\n\nRun:\n\n```bash\ncomposer update-monorepo-config\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eWhat does command \u003ccode\u003eupdate-monorepo-config\u003c/code\u003e do? 🤔\u003c/summary\u003e\n\nThe `update-monorepo-config` command will:\n\n- Regenerate the root `composer.json`, adding the new packages\n- Regenerate the root `phpstan.neon`, adding the new packages\n\n\u003c/details\u003e\n\n### Re-install the WordPress site (DEV and PROD)\n\nYou can at any moment re-install the WordPress site (and import the initial dataset).\n\nOn the DEV webserver:\n\n```bash\ncomposer reset-db\n```\n\nOn PROD:\n\n```bash\ncomposer reset-db-prod\n```\n\nThis is useful when:\n\n- The installation when doing `build-server` was halted midway (or failed for some reason)\n- Running the integration tests was not completed (modifying the DB data to a different state, so that running the tests again will fail)\n\n### Re-build the Lando webserver for DEV\n\nWhen a plugin or package folder has been renamed, you need to update the path in the `overrides` section of the [`.lando.upstream.yml`](webservers/gatographql-extensions/.lando.upstream.yml) Lando config file, and then rebuild the Lando webserver to reflect these changes.\n\nRun:\n\n```bash\ncomposer rebuild-server\n```\n\n### Regenerate the Composer autoload files for DEV\n\nWhen a new extension plugin is added to the monorepo, it must have its Composer autoload file generated, and the plugin must be symlinked to the Lando webserver.\n\nRun:\n\n```bash\ncomposer rebuild-app-and-server\n```\n\n## Development Tools\n\n### Error logs\n\nAccess the error logs from the Lando webserver:\n\n```bash\ncomposer log-server-errors\n```\n\nFor PROD:\n\n```bash\ncomposer log-server-errors-prod\n```\n\n### SSH\n\nSSH into the Lando webserver:\n\n```bash\ncomposer ssh-server\n```\n\nFor PROD:\n\n```bash\ncomposer ssh-server-prod\n```\n\n## Debugging\n\nXDebug is already integrated when using VSCode.\n\nAdd a breakpoint in the source code and then, in the `Run and Debug` tab, press on `Start Debugging` with the corresponding configuration (defined in [`.vscode/launch.json`](.vscode/launch.json)):\n\n- `[Lando webserver] Listen for Xdebug`: For debugging the source code while running the Lando webserver for DEV\n- `[PHPUnit] Listen for Xdebug`: For debugging PHPUnit tests\n\nXDebug is enabled but inactive; it must be activated when requesting the webpage (see below).\n\n### Debugging in the Lando webserver for DEV\n\nActivate XDebug for a request by appending parameter `?XDEBUG_TRIGGER=1` to the URL (for any page on the Gato GraphQL plugin, including any page in the wp-admin, the GraphiQL or Interactive Schema public clients, or other).\n\nFor instance:\n\n- `https://gatographql-{composer-vendor}-extensions.lndo.site/wp-admin/edit.php?page=gatographql\u0026action=execute_query\u0026XDEBUG_TRIGGER=1`\n- `https://gatographql-{composer-vendor}-extensions.lndo.site/graphiql/?XDEBUG_TRIGGER=1`\n\n### Debugging PHPUnit tests\n\nActivate XDebug by prepending `XDEBUG_TRIGGER=1` before the `phpunit` command to run the unit tests.\n\nFor instance:\n\n```bash\nXDEBUG_TRIGGER=1 vendor/bin/phpunit submodules/GatoGraphQL/layers/GatoGraphQLForWP/phpunit-packages/gatographql/tests/Unit/Faker/WPFakerFixtureQueryExecutionGraphQLServerTest.php\n```\n\n## Continuous Integration\n\n### Executing Integration Tests against InstaWP\n\nWhen a PR is merged, all extension plugins in the monorepo are generated for DEV, and attached to workflow [`generate_plugins.yml`](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/generate_plugins.yml) (in its Summary tab).\n\nThen, workflow [`integration_tests.yml`](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/integration_tests.yml) is triggered. This workflow installs the generated plugins in an InstaWP instance, and executes the integration tests against this instance.\n\nTo use it, you need to:\n\n- Expose the artifacts in your repo via [nightly.link](https://nightly.link/) (so these can be installed by InstaWP without being logged-in using a GitHub account)\n- Have an account on [InstaWP](https://instawp.com/) with access to SSH + WP-CLI\n- Prepare a template in InstaWP, and import the needed dataset to run the tests, via WP-CLI\n- Provide the template slug and repo ID from InstaWP via file [`InstaWPConfigDataSource.php`](src/Config/Symplify/MonorepoBuilder/DataSources/InstaWPConfigDataSource.php)\n\nTo import the dataset, you must run the following bash scripts in your InstaWP instance:\n\n- [setup/setup.sh](webservers/gatographql-extensions/setup/setup.sh)\n- [setup-extensions/setup.sh](webservers/gatographql-extensions/setup-extensions/setup.sh)\n\n### Disable unneeded workflows\n\nReview the GitHub Actions workflows that you need for your project.\n\nMost likely, the following GitHub Actions workflows are not initially needed:\n\n- [`integration_tests.yml`](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/integration_tests.yml): You first need to have InstaWP and configure the template accordingly\n- [`scoping_tests.yml`](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/scoping_tests.yml): Initially there are no packages to scope in the starter\n- [`split_monorepo_tagged.yml`](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/split_monorepo_tagged.yml): The \"Monorepo Split\" is not enabled by default (see section [Monorepo Split](#monorepo-split) below)\n- [`split_monorepo.yml`](https://github.com/GatoGraphQL/ExtensionStarter/actions/workflows/split_monorepo.yml): Same as above\n\nIf this is the case, you can [disable these workflows](https://docs.github.com/en/actions/using-workflows/disabling-and-enabling-a-workflow) so they don't run unnecessarily.\n\n## Multi-Monorepo (Architecture of the Extension Starter)\n\n`GatoGraphQL/ExtensionStarter` is multi-monorepo. To learn about the features provided by this architecture, visit [Multi-Monorepo (Architecture of the Extension Starter)](docs/Multi-Monorepo_Architecture.md).\n\n## Multi-Monorepo Tools\n\n### Synchronizing files from the upstream Gato GraphQL repo\n\nRun:\n\n```bash\ncomposer copy-upstream-files\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eWhat files does \u003ccode\u003ecopy-upstream-files\u003c/code\u003e copy? 🤔\u003c/summary\u003e\n\nExecuting `composer copy-upstream-files` will copy files from the \"upstream\" `GatoGraphQL/GatoGraphQL` repo (which is a Git submodule), to the \"downstream\" `my-account/GatoGraphQLExtensionsForMyCompany` repo.\n\nThese files include GitHub Actions workflows and Lando config files.\n\nFor instance, the Lando webserver for DEV uses the source code files from the main Gato GraphQL plugin, via the mapping defined in the upstream file [`.lando.upstream.yml`](https://github.com/GatoGraphQL/GatoGraphQL/blob/master/webservers/gatographql/.lando.upstream.yml).\n\nWhenever that file is updated in the Gato GraphQL repo, by executing `composer copy-upstream-files` we will fetch that updated file and copy it as the downstream [`.lando.base.yml`](webservers/gatographql-extensions/.lando.base.yml) file (it is renamed in the process, and the paths are adapted to point to `submodules/GatoGraphQL/...`).\n\nThen we execute `composer rebuild-server`, and the new mapping will take effect.\n\n\u003c/details\u003e\n\n## Monorepo Commands\n\nRetrieve the list of all Composer commands available in the monorepo:\n\n```bash\ncomposer list\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003eView all monorepo commands\u003c/summary\u003e\n\n| `composer` command | Description |\n| --- | --- |\n| `activate-extension-plugins` | Download/activate the extension plugins, and any required integration plugin |\n| `activate-extension-plugins-prod` | Download/activate the extension plugins, and any required integration plugin, in the PROD server |\n| `analyse` | Run PHPStan static analysis of the code |\n| `build-js` | Build all JS packages, blocks and editor scripts for all plugins in the Gato GraphQL - Extension Starter repo |\n| `build-server` | Initialize the Lando webserver with the 'Gato GraphQL' demo site, for development. To be executed only the first time |\n| `build-server-prod` | Initialize the Lando webserver with the 'Gato GraphQL' demo site, for production. To be executed only the first time |\n| `check-style` | Validate PSR-12 coding standards (via phpcs) |\n| `check-style-wp` | Validate WordPress custom rules coding standards (via phpcs) |\n| `copy-files-from-upstream-monorepo` | [multi-monorepo] Copy specific files to be reused across monorepos, from the upstream GatoGraphQL/GatoGraphQL to this downstream repo |\n| `copy-folders-from-upstream-monorepo` | [multi-monorepo] Copy all files in specific folders to be reused across monorepos, from the upstream GatoGraphQL/GatoGraphQL to this downstream repo |\n| `copy-upstream-files` | [multi-monorepo] Copy both specific files, and all files in specific folders, to be reused across monorepos, from the upstream GatoGraphQL/GatoGraphQL to this downstream repo |\n| `create-extension` | Create an extension plugin, hosted in this monorepo |\n| `debug` | Run and debug PHPUnit tests |\n| `delete-settings` | Delete the plugin settings from the DB |\n| `deoptimize-autoloader` | Removes the optimization of the Composer autoloaders for all the plugins installed in the webserver |\n| `destroy-server` | Destroy the Lando webserver with the 'Gato GraphQL' demo site |\n| `destroy-server-prod` | Destroy the Lando webserver with the 'Gato GraphQL' demo site for PROD |\n| `disable-caching` | Disable caching for the 'Gato GraphQL' in DEV |\n| `disable-restrictive-defaults` | Do not use restrictive default values for the Settings |\n| `enable-caching` | Enable caching for the 'Gato GraphQL' in DEV |\n| `enable-restrictive-defaults` | Use restrictive default values for the Settings |\n| `fix-style` | Fix PSR-12 coding standards (via phpcbf) |\n| `fix-style-wp` | Fix WordPress custom rules coding standards (via phpcbf) |\n| `import-data` | Imports pre-defined data into the DB (posts, users, CPTs, etc) |\n| `improve-code-quality` | Improve code quality (via Rector) |\n| `init-server` | Alias of 'start-server |\n| `init-server-prod` | Runs the init-server-prod script as defined in composer.json |\n| `init-server-upstream` | Runs the init-server-upstream script as defined in composer.json |\n| `initialize-project` | Initialize the project, replacing the extension starter data with your own data |\n| `install-deps-build-js` | Install all dependencies from npm to build the JS packages, blocks and editor scripts for all plugins in the Gato GraphQL - Extension Starter repo |\n| `install-site` | Installs the WordPress site |\n| `install-site-prod` | Installs the WordPress site in the PROD server |\n| `integration-test` | Execute integration tests (PHPUnit) |\n| `integration-test-prod` | Execute integration tests (PHPUnit) against the PROD webserver |\n| `log-server-errors` | Show (on real time) the errors from the Lando webserver |\n| `log-server-errors-prod` | Show (on real time) the errors from the Lando webserver for PROD |\n| `log-server-warnings` | Show (on real time) the warnings from the Lando webserver |\n| `log-server-warnings-prod` | Show (on real time) the warnings from the Lando webserver for PROD |\n| `merge-monorepo` | Create the monorepo's composer.json file, containing all dependencies from all packages |\n| `merge-phpstan` | Generate a single PHPStan config for the monorepo, invoking the config for the PHPStan config for all packages |\n| `preview-code-downgrade` | Run Rector in 'dry-run' mode to preview how the all code (i.e. src/ + vendor/ folders) will be downgraded to PHP 7.4 |\n| `preview-hello-dolly-downgrade` | Runs the preview-hello-dolly-downgrade script as defined in composer.json |\n| `preview-src-downgrade` | Run Rector in 'dry-run' mode to preview how the src/ folder will be downgraded to PHP 7.4 |\n| `preview-vendor-downgrade` | Run Rector in 'dry-run' mode to preview how the vendor/ folder will be downgraded to PHP 7.4 |\n| `propagate-monorepo` | Propagate versions from the monorepo's composer.json file to all packages |\n| `purge-cache` | Purge the cache for the 'Gato GraphQL' in DEV |\n| `purge-cache-upstream` | Runs the purge-cache-upstream script as defined in composer.json |\n| `rebuild-app-and-server` | Update the App dependencies (from Composer) and rebuild the Lando webserver |\n| `rebuild-server` | Rebuild the Lando webserver |\n| `rebuild-server-prod` | Rebuild the Lando webserver for PROD |\n| `release-major` | Release a new 'major' version (MAJOR.xx.xx) (bump version, commit, push, tag, revert to 'dev-master', commit, push) |\n| `release-minor` | Release a new 'minor' version (xx.MINOR.xx) (bump version, commit, push, tag, revert to 'dev-master', commit, push) |\n| `release-patch` | Release a new 'patch' version (xx.xx.PATCH) (bump version, commit, push, tag, revert to 'dev-master', commit, push) |\n| `remove-unused-imports` | Remove unused `use` imports |\n| `reset-db` | Resets the WordPress database |\n| `reset-db-prod` | Resets the WordPress database in the PROD server |\n| `server-info` | Retrieve information from the Lando webserver |\n| `server-info-prod` | Retrieve information from the Lando webserver for PROD |\n| `ssh-server` | SSH into the Lando webserver with the 'Gato GraphQL' demo site |\n| `ssh-server-prod` | SSH into the Lando webserver for PROD with the 'Gato GraphQL' demo site |\n| `start-server` | Start the Lando webserver with the 'Gato GraphQL' demo site, for development |\n| `start-server-prod` | Start the Lando webserver for PROD with the 'Gato GraphQL' demo site, for development |\n| `stop-server` | Stop the Lando webserver |\n| `stop-server-prod` | Stop the Lando webserver for PROD |\n| `stop-server-upstream` | Runs the stop-server-upstream script as defined in composer.json |\n| `stopping-integration-test` | Runs the stopping-integration-test script as defined in composer.json |\n| `stopping-integration-test-prod` | Execute integration tests (PHPUnit) against the PROD webserver, stopping as soon as there's an error or failure |\n| `stopping-unit-test` | Runs the stopping-unit-test script as defined in composer.json |\n| `unit-test` | Execute unit tests (PHPUnit) |\n| `update-deps` | Update the Composer dependencies for the 'Gato GraphQL' plugins |\n| `update-monorepo-config` | Update the monorepo's composer.json and phpstan.neon files, with data from all packages |\n| `use-default-restrictive-defaults` | Remove the set value, use the default one |\n| `validate-monorepo` | Validate that version constraints for dependencies are the same for all packages |\n\n\u003c/details\u003e\n\n## Standards\n\n[PSR-1](https://www.php-fig.org/psr/psr-1), [PSR-4](https://www.php-fig.org/psr/psr-4) and [PSR-12](https://www.php-fig.org/psr/psr-12).\n\nTo check the coding standards via [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer), run:\n\n``` bash\ncomposer check-style\n```\n\nTo automatically fix issues, run:\n\n``` bash\ncomposer fix-style\n```\n\n## Testing\n\n### Unit Tests\n\nExecute unit tests via [PHPUnit](https://phpunit.de/):\n\n``` bash\ncomposer unit-test\n```\n\n### Integration Tests\n\nExecute integration tests against the Lando webserver for DEV:\n\n``` bash\ncomposer integration-test\n```\n\nExecute against the Lando webserver for PROD:\n\n``` bash\ncomposer integration-test-prod\n```\n\n## Static analysis\n\nTo execute [PHPStan](https://github.com/phpstan/phpstan), run:\n\n``` bash\ncomposer analyse\n```\n\n## Previewing code downgrade\n\nVia [Rector](https://github.com/rectorphp/rector) (dry-run mode):\n\n```bash\ncomposer preview-code-downgrade\n```\n\n## Report issues\n\nUse the [issue tracker](https://github.com/GatoGraphQL/ExtensionStarter/issues) to report a bug or request a new feature for all packages in the monorepo.\n\n## Contributing\n\nPlease see [CONTRIBUTING](CONTRIBUTING.md) and [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) for details.\n\n## Security\n\nIf you discover any security related issues, please email name@mycompany.com instead of using the issue tracker.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgatographql%2Fextensionstarter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgatographql%2Fextensionstarter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgatographql%2Fextensionstarter/lists"}