feat: Add directive layer#807
Conversation
|
Hey @oojacoboo, I don't want this to become stale. Is it something that you need to get it over the finish line? |
|
Well, for starters, the tests are all going to have to pass. Beyond that, an hour of my time to review it. |
see #811 |
|
@michael-georgiadis #811 was merged. Please rebase and hopefully that resolves tests. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #807 +/- ##
============================================
- Coverage 95.72% 92.36% -3.36%
- Complexity 1773 2019 +246
============================================
Files 154 198 +44
Lines 4586 5424 +838
============================================
+ Hits 4390 5010 +620
- Misses 196 414 +218 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@oojacoboo Done ✅ ! I think the most meaningful cases are covered and I also included an end-to-end one. However, if you want more coverage on specific sub-units happy to add more 🫡 |
Description
As per your comment on this PR, I am splitting the implementation into two.
I am focusing on configuring the directive layer on this one. Specifying two directives to start with.
How it works
A directive is a PHP attribute implementing one of the family interfaces, which ties it to a GraphQL location (
FieldDirective→FIELD_DEFINITION,InputObjectTypeDirective→INPUT_OBJECT, etc.). Implementing the marker interface alone is metadata-only; implementing the matchingBehavioral*sub-interface adds an apply hook that runs through a middleware pipe during type generation.The built-ins on the layer
#[OneOf]→ sets webonyx'sisOneOfflag → printsinput LookupInput @oneOf.#[Deprecated(reason:)]→ sets the field's deprecation reason → printslegacy: String! @deprecated(reason: "...").Both bind to directives webonyx already declares, so they print through webonyx's own SDL output and we don't register duplicate definitions for them (
DirectiveDefinition::$builtIn).@deprecated: additive, not a rewriteThe existing docblock
@deprecatedsupport is untouched.#[Deprecated]is an attribute-basedpath that composes with it rather than fighting it:
#[Deprecated(reason: 'X')](± docblock)@deprecated(reason: "X")— explicit wins#[Deprecated]+/** @deprecated Y */@deprecated(reason: "Y")— docblock kept#[Deprecated], no docblock@deprecated(reason: "No longer supported")— defaultUsage validation
PHP's
#[Attribute]targets can't tell a#[Type]class from an#[Input]class (both areTARGET_CLASS), so a misplaced#[OneOf]on a#[Type]would otherwise be silently dropped by the interface-based collection.DirectiveValidatorcatches that and throws a clearInvalidDirectiveExceptioninstead.