feat: minimal MailerLite addon — sync pipeline + per-form config + resync action#4
Closed
jurnskie wants to merge 1 commit into
Closed
feat: minimal MailerLite addon — sync pipeline + per-form config + resync action#4jurnskie wants to merge 1 commit into
jurnskie wants to merge 1 commit into
Conversation
…sync action
This is the v1.0 marketplace release shape, rebuilt per colleague review:
> "Basis was prima, alleen die formconfig dingen moesten anders."
The basis (sync job + listener + MailerLite SDK wrapper + per-form blueprint
section) is preserved. The over-engineering generated during exploration
(dashboard, activity log surface, retry controller + rate limiter, central
form-config repository, custom CP routes/permissions/nav, Vue/Inertia pages)
has been removed. Re-sync is delivered as a Statamic native Submission Action
that appears on the form's built-in submissions list — one button, no
parallel CP surface.
Per-form config is read DIRECTLY from each form's own YAML via
`Form::find($handle)->get('enabled' | 'mappings' | 'groups')`. No addon-side
mirror, no central form-config repository. Statamic's Form::appendConfigFields
already persists the values where Statamic looks for them.
Components:
src/AddonSettings.php
Thin wrapper around Statamic's native addon-settings store. Single
responsibility: read the API key. Container-bound singleton; tests
replace via app()->instance().
src/MailerLite/MailerLiteService.php + Contracts/, Exceptions/
SDK wrapper. upsertSubscriber(), ping(), listFields(), listGroups().
Translates SDK exceptions to addon-namespace types so the rest of the
addon doesn't depend on the SDK's surface.
src/Sync/SyncSubscriberJob.php
Queued upsert. Reads the API key from AddonSettings and the per-form
mappings/groups directly off the form blueprint. tries=3, backoff=
[60,300,900]. 4xx -> permanent_failure (no retry); 5xx -> transient
(Laravel retries). The finally block emits a Log::info breadcrumb but
does not maintain a separate activity store.
src/Listeners/FormSubmittedListener.php
Captures the visitor IP onto the submission pre-persist.
src/Listeners/SubmissionCreatedListener.php
Thin dispatch gate — reads `enabled` from the form, dispatches the
job. No driver dependency, no form-config repository.
src/Actions/ResyncToMailerLite.php
Statamic Submission Action (auto-discovered from src/Actions/). Visible
on the form's submissions list when the form has MailerLite sync
enabled. Dispatches a fresh SyncSubscriberJob per selected submission.
src/Fieldtypes/MailerLite{Field,Group}Fieldtype.php
Live-fetched dropdowns. Per-request cache keyed by sha256(api_key)
keeps the SDK call count to one per CP render.
src/StatamicMailerLiteServiceProvider.php
Bindings (AddonSettings singleton + MailerLiteService via interface)
and the per-form MailerLite section append. Listeners and the Action
auto-discover from their respective folders.
resources/blueprints/settings.yaml
Statamic native addon-settings blueprint — API key field. Rendered
under Tools → Addons → MailerLite.
Removed (vs the exploratory PR #3 history on f/js/gsd-mailerlite):
- StorageDriverInterface + AddonYamlDriver (and the FormConfig methods).
Per-form config now lives where Statamic stores it natively, not
mirrored into addon storage.
- ActivityLogger, ActivityLogEntry, ActivityLogStore (JSONL).
- All four CP/* controllers (Dashboard, Activity, Retry, FormHealthSummary).
- PruneActivityLogCommand.
- FormSavedListener (the mirror writer).
- Custom CP routes, top-level nav, configure-mailerlite permission,
retry rate limiter.
- Vue/Inertia Dashboard + Activity pages and the Vite build pipeline.
Quality gates:
Pest 124/124 · PHPStan level 5 clean · Pint clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the v1.0 marketplace release shape, rebuilt per colleague review:
The basis (sync job + listener + MailerLite SDK wrapper + per-form blueprint
section) is preserved. The over-engineering generated during exploration
(dashboard, activity log surface, retry controller + rate limiter, central
form-config repository, custom CP routes/permissions/nav, Vue/Inertia pages)
has been removed. Re-sync is delivered as a Statamic native Submission Action
that appears on the form's built-in submissions list — one button, no
parallel CP surface.
Per-form config is read DIRECTLY from each form's own YAML via
Form::find($handle)->get('enabled' | 'mappings' | 'groups'). No addon-sidemirror, no central form-config repository. Statamic's Form::appendConfigFields
already persists the values where Statamic looks for them.
Components:
src/AddonSettings.php
Thin wrapper around Statamic's native addon-settings store. Single
responsibility: read the API key. Container-bound singleton; tests
replace via app()->instance().
src/MailerLite/MailerLiteService.php + Contracts/, Exceptions/
SDK wrapper. upsertSubscriber(), ping(), listFields(), listGroups().
Translates SDK exceptions to addon-namespace types so the rest of the
addon doesn't depend on the SDK's surface.
src/Sync/SyncSubscriberJob.php
Queued upsert. Reads the API key from AddonSettings and the per-form
mappings/groups directly off the form blueprint. tries=3, backoff=
[60,300,900]. 4xx -> permanent_failure (no retry); 5xx -> transient
(Laravel retries). The finally block emits a Log::info breadcrumb but
does not maintain a separate activity store.
src/Listeners/FormSubmittedListener.php
Captures the visitor IP onto the submission pre-persist.
src/Listeners/SubmissionCreatedListener.php
Thin dispatch gate — reads
enabledfrom the form, dispatches thejob. No driver dependency, no form-config repository.
src/Actions/ResyncToMailerLite.php
Statamic Submission Action (auto-discovered from src/Actions/). Visible
on the form's submissions list when the form has MailerLite sync
enabled. Dispatches a fresh SyncSubscriberJob per selected submission.
src/Fieldtypes/MailerLite{Field,Group}Fieldtype.php
Live-fetched dropdowns. Per-request cache keyed by sha256(api_key)
keeps the SDK call count to one per CP render.
src/StatamicMailerLiteServiceProvider.php
Bindings (AddonSettings singleton + MailerLiteService via interface)
and the per-form MailerLite section append. Listeners and the Action
auto-discover from their respective folders.
resources/blueprints/settings.yaml
Statamic native addon-settings blueprint — API key field. Rendered
under Tools → Addons → MailerLite.
Removed (vs the exploratory PR #3 history on f/js/gsd-mailerlite):
Per-form config now lives where Statamic stores it natively, not
mirrored into addon storage.
retry rate limiter.
Quality gates:
Pest 124/124 · PHPStan level 5 clean · Pint clean.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com