wlogic/qbjs-parser
A lightweight Laravel/PHP parser for QBJS (QuickBooks JSON) data. It converts accounting records into structured PHP arrays and objects, making validation, querying, and integration simple. Ideal for importing customers, invoices, and transactions.
What it is. A narrow transformation library: take the JSON rule tree emitted by jQuery QueryBuilder (the {condition, rules:[...]} structure), and turn it into database query predicates. It sits on a single seam — untrusted client JSON in, query builder out.
Architecture fit. Good, precisely because it is small. No migrations, no schema, no background workers, no external services, no state. It is a leaf dependency whose blast radius is one feature (ad-hoc filtering / reporting). The input contract is public, versioned, and stable — jQuery QueryBuilder's rule JSON has not meaningfully changed in years — so the package is not defending a moving target. Fit within Laravel is natural if it emits an Illuminate\Database\Query\Builder or Eloquent builder that we can still constrain with tenant scopes, soft deletes, and global scopes. Fit degrades if it hands back raw SQL strings, because we then lose the ability to compose and re-constrain.
Integration feasibility. Moderate effort, low technical uncertainty. The parsing itself is a solved problem; the real work is the policy layer around it (see below). Verify from composer.json before committing: PHP constraint, Illuminate/Laravel version support, whether it is framework-agnostic or coupled to Illuminate contracts, and whether a test suite exists that we can run as a conformance check.
Technical risk. High, but concentrated and mitigable.
Key questions for the spike. Bound parameters or string interpolation? Does it fail closed on unknown operators, or silently skip? Nested groups and NOT supported? Empty rule set behavior? Does the output expose id/field mapping we can validate against our allowlist? Return type — builder or string? Declared PHP/Laravel matrix? Existing test coverage?
Recommendation. Timeboxed spike yes; permanent dependency no. Vendor or fork from day one so we are not patching code we do not own.
Stack fit. Clean if the application is Laravel 10/11 + Eloquent and the frontend already uses jQuery QueryBuilder. If the parser is Illuminate-coupled, it is not reusable in non-Laravel services — acceptable for an admin/reporting surface, a constraint if filtering ever needs to run in a separate reporting service or a queue worker.
Migration path. Do not call the package from controllers or form requests. Introduce one interface — RuleSetCompiler::compile(array $rules, FilterPolicy $policy): Builder — and make the package the first implementation behind it. Keep a second implementation (hand-written) in reserve. Swapping vendors later becomes a container binding change with no call-site churn, and it forces the policy object into the signature where it belongs.
Compatibility. Pin an exact version. Encode the tested PHP/Laravel matrix in CI. Add conflict entries for untested Illuminate majors so upgrades fail loudly at composer update rather than quietly at runtime.
Sequencing.
IN with 10k values.IN cardinality. Reject with a 422; never ignore.Maintenance. Budget for ownership. No upstream patch stream, no release cadence to plan around; the next Laravel major will break this and it will be our ticket. The fork is small — likely a handful of classes — but it must be scheduled, not discovered.
Support. None. No issue triage, no security advisories, no maintainer response path. We become the incident response team for this code path. That is tolerable only because it is a leaf feature that can be disabled by flag without taking down checkout, auth, or data ingest.
Scaling. Parse cost is noise next to query execution. The scaling risk is query shape: unbounded IN lists, wide OR trees, and unindexed column combinations. Enforce server-side caps and a statement timeout; log any rule set that trips a cap, since those are the ones that will page someone. If compiled queries are cached, the cache key must include the rule JSON hash and the policy version — otherwise tightening the allowlist silently does not take effect for cached entries.
Failure modes, ranked by damage.
Ramp-up. Low for the library itself; half a day for an engineer comfortable with query builders to read the parser end-to-end. The real ramp-up is the guardrails — allowlists, caps, fixtures, error semantics — which the package does not provide and which will be the majority of the work. Plan the estimate accordingly: the library saves roughly a day of parsing code and costs a day of review plus an ongoing fork obligation. Worth it only if the spike confirms the policy layer can sit cleanly outside the package rather than requiring patches inside it.
How can I help you explore Laravel packages today?