Repository navigation
Conversation
…files with OpenSpout maatwebsite/excel can't be installed on PHP 8.5 (PhpSpreadsheet 1.30 caps PHP below 8.5), so it's replaced here rather than later: exports are written with OpenSpout (CSV, XLSX, ODS) through SpreadsheetWriter, and ModelExport gets download(), store() and writeTo() from the WritesFiles trait. The v1 ModelExport API and output are unchanged for now. Closes #1 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rows are read with lazyById() (lazy() when the query is ordered) and eager loaded per chunk, so memory stays flat: the 1M-row benchmark (composer benchmark, and its own CI job) peaks at +4.4 MB for CSV and +3.3 MB for XLSX. ModelExport now picks readable defaults: no hidden attributes or secrets, foreign keys replaced by their BelongsTo relation, headings from the column, the model's exportHeadings(), validation attribute names, or a translated headline; enum labels, Yes/No, dates in the app timezone, JSON for arrays, related models by name. columns() takes dot notation and Column definitions. The v1 hooks (allowedAttributes, relationsToInclude, formatValue, headings, map) still work. Closes #2 Closes #3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
queue() creates an Export (uuid, user morph, format, status, rows, disk,
path, size, expiry) and dispatches ProcessExport. The job streams the whole
file in one go (XLSX and ODS can't be appended to from parallel jobs), saves
progress every chunk, stops when the export is cancelled, moves the file to
the configured disk under exports/{uuid}/, and notifies the user with a signed
link that expires with the file. Builders passed to an export are serialized
as SQL, bindings, order and eager loads (closures included) and rebuilt in
the job; models held by an export are serialized as identifiers.
exports:prune deletes expired exports, and stuck ones older than the expiry
period, with their files.
Closes #4
Refs #5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions Route::exports() registers index, store, show, download, cancel and destroy under the app's prefix, name, guard and middleware, plus a signed download route for notification links. ExportsController answers JSON (ExportResource with progress, abilities, links and broadcast info) or renders pages through ViewRenderer, and is replaceable from config, the macro or the container. Permissions view_exports, view_others_exports, delete_exports and delete_others_exports are registered with javaabu/permissions, with ExportPolicy as the default policy (overridable from permissions.policies or Gate::policy()). Users see their own exports; *_others_* see everyone's. Tested with two guards and two user models. Closes #11 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Export events implement ShouldBroadcastNow and broadcast only when
Broadcasting::enabled(): forced by exports.broadcasting.enabled, or on 'auto'
when laravel/reverb is installed and the default broadcaster isn't null or
log. They go to private-exports.{uuid} (authorized with the policy's view
ability) and private-exports.owner.{type}.{id} (the owner only) as
export.started, export.progressed, export.completed, export.failed and
export.cancelled, with a small progress payload.
Without broadcasting, the JSON meta says broadcasting: false and gives the
poll interval, so pages poll the show route. laravel/reverb is suggested and
installed for tests only.
Closes #6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lang/en.json and lang/dv.json cover statuses, formats, messages, notifications, permission descriptions and the common default headings. A test fails when a __() string in src or the views has no Dhivehi line. Refs #9 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Docs for installing, model exports, downloading and storing, queued exports, the exports page and API, performance (with the benchmark), permissions and policies with multiple guards, live progress, translations, configuration, an API reference, AI assistants, and upgrading from v1 with the reasons for dropping maatwebsite/excel and how to migrate. llms.txt indexes every page. AGENTS.md and CLAUDE.md for agents working on the repo. Queued exports now write the file in the locale active when queue() was called. Broadcasting's enabled flag accepts boolean strings. The pages for the views come with the views. Closes #8 Refs #7 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blade pages (exports::exports.index and .show) built with javaabu/forms v2 components: a form to start a registered export, a status filter, a table with status, a progress bar, rows, owner and actions, and pagination. They extend the app's layout (exports.layout) and load exports::progress through javaabu/manifest, which follows unfinished rows over Echo or by polling. Inertia pages (exports::Exports/Index and /Show) in TypeScript with @javaabu/forms and @javaabu/onu's ProgressBar, registered with manifest's registerAssets() (pages, @javaabu/exports alias, npm dependencies). They get their translated text in a strings prop and follow progress with useExportProgress(). Both stacks use logical utilities only, and a test rejects physical ones. Tests: Blade rendering (English and Dhivehi, permissions, flash messages, required assets), Inertia props, manifest registration, and Vitest for the hook, the progress component and the Blade script. CI gets a JS job. Closes #10 Closes #9 Closes #5 Closes #7 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
forms next-gen now honours no-bulk, but its table template then drops the whole table (Javaabu/forms#17). The index doesn't pass a bulk form, so it leaves no-bulk off. Install pnpm packages with the store outside node_modules in CI, so the git build of @javaabu/forms works (Javaabu/react-forms issue filed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 tasks done
@javaabu/forms, @javaabu/onu, react, react-dom and @inertiajs/react are only imported by the Inertia pages and the @javaabu/exports alias; the Blade progress script imports no npm packages. Moving them into npm(..., for: NpmScopes::PAGES) (Javaabu/manifest#17) means a Blade-only app's manifest:check asks exports for nothing but vite and laravel-vite-plugin. NpmRequirementsTest runs manifest:check against a Blade-only and an Inertia package.json fixture. Docs, the Boost skill and AGENTS.md say which packages each stack needs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
javaabu/permissions now registers React pages in the assets scope (it hasn't adopted Javaabu/manifest#17 yet), so the whole-app check listed react. The test now judges only the rows exports is needed by. Co-Authored-By: Claude Opus 5.5 <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.
javaabu/exports v2.0
The next-gen major of exports, built on the fork
n4ff4h/exports(next-gen). Tracked in n4ff4h#13.What's new
lazyById()(orlazy()for ordered queries) with eager loads per chunk. A 1M-row benchmark runs in CI: +4.8 MB peak for CSV and +3.6 MB for XLSX.ModelExportdefaults.columns()takes dot notation andColumndefinitions.Exportmodel (uuid, user morph, status, progress, file, expiry).ProcessExportsaves progress, can be cancelled, writes in the locale the export was queued in, and stores to any disk.exports:prunedeletes expired exports.Route::exports()lets the app choose the prefix, name, guard and middleware.Exports::register()lets the page start an export by name.ExportPolicyplusview_exports,view_others_exports,delete_exportsanddelete_others_exports, registered through javaabu/permissions v3 and overridable. Tested with two guards and two user models.docs/, plusllms.txt, a Laravel Boost guideline and skill, andAGENTS.md.Upgrade notes (full guide in
docs/upgrading.md)Excel::download(new UsersExport, …)withUsersExport::make()->download(…), and the same forstore().queue()becomesqueue($user, …), which returns anExport.WithStyles,WithEvents, …) aren't supported.modelClass,relationsToInclude,allowedAttributes,formatValue,headings,map.IDheadings, FK columns replaced by relations,,separators.php artisan migrate(theexportstable) andphp artisan permissions:sync.Dependencies on unreleased packages
This branch requires
javaabu/permissions ^3.0@dev,javaabu/forms ^2.0@devandjavaabu/manifest ^1.0@devthrough VCS repositories. It also uses@javaabu/formsfromgithub:Javaabu/react-forms#next-genfor the React pages. Before tagging v2.0:repositoriesentries.For the reviewer
CODECOV_TOKENmust be available to Javaabu/exports, or coverage uploads are skipped (CI doesn't fail on that).docs/advanced-usage/translations.md#strings-for-reviewneed a native speaker's check.🤖 Generated with Claude Code