PHPackages                             milpa/devtools - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. milpa/devtools

ActiveMilpa-capability[Framework](/categories/framework)

milpa/devtools
==============

The coa generate-verify-inspect developer loop for the Milpa PHP framework: deterministic controller/entity scaffolding (Make engine), framework health + plugin-manifest + capability-graph validators, and BaseController/Doctrine-entity convention verifiers.

v0.14.2(2w ago)0778↑14.4%3Apache-2.0PHPPHP &gt;=8.3CI passing

Since Jul 8Pushed 1mo agoCompare

[ Source](https://github.com/getmilpa/devtools)[ Packagist](https://packagist.org/packages/milpa/devtools)[ RSS](/packages/milpa-devtools/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (6)Dependencies (21)Versions (32)Used By (3)

 [   ![Milpa](https://raw.githubusercontent.com/getmilpa/core/main/art/lockup/milpa-lockup-v-color-light.svg)  ](https://github.com/getmilpa)

Milpa DevTools
==============

[](#milpa-devtools)

> The **generate-verify-inspect** developer loop for the Milpa PHP framework: deterministic controller/entity scaffolding (the Make engine), boot-time doctors, and architectural validators — capability graphs, plugin manifests, boundary rules — that run **in-process**, with Composer-safe root resolution.

[![CI](https://github.com/getmilpa/devtools/actions/workflows/ci.yml/badge.svg)](https://github.com/getmilpa/devtools/actions/workflows/ci.yml)[![Packagist](https://camo.githubusercontent.com/19e34087053a9bd1f35dedf325978c46464582b5e47f079b23c5dc15ffe88681/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d696c70612f646576746f6f6c732e737667)](https://packagist.org/packages/milpa/devtools)[![PHP](https://camo.githubusercontent.com/ca03f11ea27dac4dedc8ad56a7bdfc4a9ff5feb825055f9d2983616115076607/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d254532253839254135253230382e332d3737376262342e737667)](https://www.php.net/)[![License](https://camo.githubusercontent.com/798509b4df525f56802b56f8096862487f08023e3d7561c68656f8dab10d0d6e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4170616368652d2d322e302d626c75652e737667)](LICENSE)[![Docs](https://camo.githubusercontent.com/c6dc6a3411e15b0ac7cc4583e8e6a8144181caedb82f5d98753353decda06d77/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646f63732d4150492532307265666572656e63652d626c75652e737667)](https://getmilpa.github.io/devtools/)

`milpa/devtools` is what `coa` calls when you type `coa:make`, `coa:doctor`, `coa:validate`, or `coa:inspect` — the engine behind that whole CLI surface, extracted so it runs the same in-process whether it's driven by a real host app's console or by your own tests. **Generate** deterministic, convention-following scaffolding; **verify** it against the exact runtime rules the framework enforces; **inspect** a plugin ecosystem's capability graph and manifests for problems before they become a boot-time failure. No `exec()` to a script at a hardcoded path, no assumption about install depth — just classes you can `new` and call.

Install
-------

[](#install)

```
composer require milpa/devtools
```

Quick example: generate, then read what you got
-----------------------------------------------

[](#quick-example-generate-then-read-what-you-got)

`EntityGenerator`/`ControllerGenerator` both target **two conventions** — a Doctrine `Milpa\app`legacy host, or a plain `milpa/data`/PSR-7 `milpa/runtime` host — auto-detected per app root by `ConventionDetector` (override with `GenerationContext`'s `flavor` option, e.g. `--flavor=runtime`). The full split, exact CLI syntax for each host, and the `--fields` DSL live in [`docs/DEVTOOLS-MAKE.md`](../../docs/DEVTOOLS-MAKE.md) of the host monorepo; this README's example below shows the **legacy** flavor. Either way it's a string, in memory, with zero disk I/O of its own (that's `WriteGuard`'s job, so a caller can inspect, diff, or dry-run a generation before anything touches the filesystem):

```
use Milpa\DevTools\Make\GenerationContext;
use Milpa\DevTools\Make\Generators\EntityGenerator;

$context = new GenerationContext(
    plugin: 'InventoryPlugin',
    name: 'Product',
    options: ['fields' => 'name:string:120,price:decimal:10,2,active:bool'],
    root: '/path/to/host-app',
);

$result = (new EntityGenerator())->generate($context);

echo $result->files[0]->path;
// -> /path/to/host-app/plugins/InventoryPlugin/Entities/Product.php

echo $result->files[0]->contents;
```

produces (verbatim, this is a real run — see [What's inside](#whats-inside) for the full field DSL):

```
