Skip to content

javaabu/settings v2.0 (next-gen) - #2

Open
n4ff4h wants to merge 9 commits into
Javaabu:mainfrom
n4ff4h:next-gen
Open

n4ff4h wants to merge 9 commits into
Javaabu:mainfrom
n4ff4h:next-gen

Conversation

@n4ff4h

@n4ff4h n4ff4h commented Nov 4, 2026

Copy link
Copy Markdown

javaabu/settings v2.0

This is the next major of settings: you define each setting once, with javaabu/stencil, and it gets typed access, a settings page in Blade or Inertia React, and fresh values in queue workers. It was developed on the fork n4ff4h/settings (branch next-gen) and tracked in n4ff4h#12.

What's in it

  • Definitions. Setting::make('per_page')->default(20)->integer()->minValue(1) puts the default, the stencil field and the validation in one place. Settings are grouped into SettingsPage classes (or inline pages) and Sections. Settings::define() covers settings that have no page.
  • Storage. v2 has its own database (default), json and array stores, plus custom drivers, replacing anlutro/l4-settings. Values are kept as JSON, so their types survive. php artisan settings:import-v1 copies the v1 values across.
  • Reading. The settings() helper and the Settings facade cast values from the field (booleans, integers, floats, arrays, enums). Typed getters (settings()->integer('per_page')) throw on the wrong type. Settings can be encrypted, and file settings have URLs.
  • Fresh everywhere. Values are cached under a version token. Queue workers (before each job) and Octane (before each request) reload them when another process changes them. This is tested with a real queue:work process, both with the reload on and off.
  • Pages. Route::settings([...]) gives each page a form, validation, saving, uploads and live fields. You choose the prefix, name, guard and middleware.
    • Blade: built with javaabu/forms.
    • Inertia React: settings::Settings/Edit with <StencilForm>, shipped through javaabu/manifest; the components are exported as @javaabu/settings.
    • JSON for API clients. The controller can be overridden.
  • RBAC. view_settings, edit_settings and per-page permissions are registered with javaabu/permissions. SettingsPolicy can be overridden. Any guard and user model works.
  • Optional packages. Translatable settings come from javaabu/translatable v3 (->translatable(), one input per language). The activity log comes from spatie/laravel-activitylog, and encrypted values are never logged.
  • Dhivehi, RTL and docs. Dhivehi translations, RTL pages and Thaana fields. Docusaurus docs, llms.txt, AGENTS.md, and a Laravel Boost guideline and skill.

Breaking changes (full list in docs/upgrading.md)

  • Requires PHP 8.4 and Laravel 12 or 13.
  • anlutro/l4-settings is gone. Replace anlutro\LaravelSettings\Facades\Setting with Javaabu\Settings\Facades\Settings; writes save immediately, so there's no save(). anlutro's config/settings.php is replaced by v2's file of the same name.
  • Values keep their types (v1's database store returned strings).
  • SettingsUpdated::$causer is any Eloquent model, and defaults to the authenticated user.
  • spatie/laravel-activitylog is now optional.
  • Providers\EventServiceProvider is removed.
  • Still working from v1: get_setting(), default_setting(), set_file_setting(), reset_file_setting(), remove_prefix(), config/defaults.php, FakesSettings and SettingsUpdated.

Tests and CI

  • 114 PHPUnit tests: two guards, Blade, Inertia, JSON, live fields, a real queue worker, and translatable on and off.
  • Vitest tests of the React page.
  • CI runs PHP 8.4/8.5 × Laravel 12/13 × lowest/stable, plus Pint, the React page checks (typecheck and Vitest) and a job without the optional packages. All green on the fork.

Before or after merging

🤖 Generated with Claude Code

n4ff4h and others added 9 commits November 4, 2026 16:18
- PHP ^8.4, Laravel 12/13, Testbench 10/11, PHPUnit 11.5/12.5; branch alias
  dev-next-gen => 2.x-dev; Pint with the Javaabu rules; CI matrix with
  coverage from one leg and a leg without the optional packages
- Drops anlutro/l4-settings: database, json and array stores behind a
  SettingsStore contract, cached with a version token per change
- Setting::make()->default()->field() with calls forwarded to the stencil
  field; SettingsPage classes, inline pages and sections
- settings() helper, Settings facade, typed getters, casts from the field,
  encrypted settings, file URLs
- v1 helpers, config/defaults.php fallback, FakesSettings and
  SettingsUpdated kept; activity log is optional; settings:import-v1

Refs #1
Closes #2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Workers check the settings cache version before each job (Queue::before)
and Octane before each request, task and tick, and reload when another
process changed a setting. Tested with an in-process worker and with a real
queue:work process started through vendor/bin/testbench, both ways.

Closes #4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SettingsForm: a stencil form class per page, filled with the current
  values, validated and saved by the schema; uploads replace (and delete)
  the old file; encrypted values never reach the browser and stay when
  left empty; live fields work through Route::stencil()
- Route::settings() with prefix, name, middleware, guard and controller
  options; SettingsController overridable from config or the macro, with
  JSON responses for JSON requests
- view_settings / edit_settings registered with javaabu/permissions, plus
  each page's own permission; SettingsPolicy on SettingsPage, overridable
  from config or Gate::policy()
- Blade page with javaabu/forms nav tabs between pages
- Tests for both guards, user models, permissions and overrides

Refs #3, #8
Closes #9

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
settings::Settings/Edit renders the page's stencil schema with
<StencilForm>, tabs between pages (@javaabu/forms NavTabs), the saved
status and a read-only notice; SettingsNav and the types are exported as
@javaabu/settings. settings.views picks blade or inertia; the Blade view
is publishable and the React page can be overridden through manifest.
Vitest renders the page from the props PHP sends (a fixture written by
InertiaPagesTest); CI typechecks and tests it.

Closes #3
Closes #8

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lang/en.json and lang/dv.json for the page, the form, the notices and the
permission descriptions, with a test that every __() string has a Dhivehi
translation; page and Inertia tests in Dhivehi and RTL.

Refs #7

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Setting::translatable() gives a value per language when translatable is
installed and enabled: the page's form edits a never-saved JSON-translatable
SettingsRecord, so stencil renders site_title_en / site_title_dv with
translatable's rules; values are stored as a locale map and read in the
current language with fallback. Without translatable it's a plain setting,
and stored maps are still read in the app locale.

Tested both ways locally against translatable's next-gen (with its
javaabu/helpers requirement removed); the tests skip until it can be
installed next to settings v2 (n4ff4h/translatable#11).

Refs #10

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Docusaurus docs: introduction, requirements, installation, upgrading
  from v1, defining settings, reading and writing, settings pages (Blade
  and React), testing, configuration, stores and caching, queue workers
  and Octane, permissions, overriding, activity log, translatable
  settings, Dhivehi and RTL (with translations to review), API reference
- llms.txt with the rules and every page; AGENTS.md and CLAUDE.md
- Boost guideline and the javaabu-settings skill with references
- README and CHANGELOG for v2

Closes #5
Closes #6
Closes #7

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Same as Queue::before(), without resolving the queue manager on every
request.

Refs #4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
n4ff4h/translatable#11 dropped javaabu/helpers, so translatable v3 installs
next to settings v2: it's in require-dev, the translatable tests run, and
the "without optional packages" job removes it to test the other way.

Closes #10

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant