simple_query 0.2.3
simple_query: ^0.2.3 copied to clipboard
Cross-platform typed query API for device data (contacts, media, files, calendar, messages, calls).
0.2.3 #
- fix(UNFY-123): validate the MMS query dependency release
- fix(UNFY-270): validate observer identity and dependency contract
- chore(release): reset versions to align with pub.dev (smallest iteration)
- Update binary_content.dart
- fix: address review feedback on PR #31 (staging→main)
- chore: bring .gitignore to Flutter-template parity + untrack pubspec.lock files
- chore(release): unblock pub publish — split path overrides into pubspec_overrides.yaml
- test: propagate const→final flip across all affected packages
- fix(facade): rename BinaryContent.forTesting → fromHandle
- chore(release): coordinated 0.6.0 across all simple_query packages
- docs+tool: CHANGELOG Unreleased discipline
- docs(api): dartdoc completeness + singleton/thread-safety notes
- chore(release): coordinated 0.5.0 across all simple_query packages
- feat(builder): canonical-field validation + facade entry + paged execute
- feat(facade): BinaryContent wrapper with self-closing lifecycle
- feat(facade): add queryPaginated + queryPaginatedTyped stream helpers
- chore(release): coordinated 0.4.0 across all simple_query packages
- feat(permissions): inline check, drop simple_permissions dependency
- feat(facade): add SimpleQuery.queryRaw for first-party content providers
- release: 0.3.1 — coordinated bump + audit-driven cleanup (#20)
- ci: address review feedback + unblock CI
- feat(kotlin): ContentQuery helper for sibling plugins
- chore: alphabetize imports + refresh lockfiles
- Initial Push
Unreleased #
- Require platform interface >=0.2.1 for field catalog and runtime validation (UNFY-123).
- Require simple_query_android >=0.2.2 so Android observer identity and metadata reach consumers (UNFY-270).
0.2.1 #
Reset to align with pub.dev's published series #
This package on pub.dev is at 0.2.0. Local git tags 0.3.0 (and
0.3.1 on _android) and the develop pubspec at 0.6.0 were
authored ahead of the next publish but never reached pub.dev.
Orphan tags deleted from origin and the version reset to the
smallest patch above the last-published version (0.2.0 → 0.2.1).
Cross-package constraints lowered from ^0.6.0 to ^0.2.0 to
match the published series.
The 0.3 — 0.6 work described in the entries below is not lost — it lives in source and will surface in published form through subsequent patch / minor / major bumps as appropriate. Entries kept for archival reference.
0.6.0 #
Documentation and developer-experience release. Strictly additive — no public-API changes from 0.5.0.
Added #
docs/DESIGN.md— codifies the seven design principles (P1–P7 plus the permissions rule) that govern the public API. Read before contributing.docs/EXTENSIONS.md— single index linking the five per-platform extension docs with a usage example and stability policy.tool/regen_pigeon.shalready landed in 0.5.0; documented here for completeness.- Every package's
CHANGELOG.mdnow leads with a## Unreleasedsection.tool/publish.shwarns when the section is still present during a live publish.
Changed #
- Root
README.mdnow links every doc (DESIGN, API_SEMANTICS, ERROR_MAPPING, MIGRATION, PLATFORM_SUPPORT_MATRIX, EXTENSIONS, RELEASE) in a navigation table. "Highlights" expanded to cover the 0.4.0 / 0.5.0 additions. docs/MIGRATION.mdrewritten to cover iOS / macOS / desktop migrations alongside Android. Includes the column-name → canonical-field translation table for 0.4.0's symmetric vocabulary.docs/API_SEMANTICS.md— "includereserved for future use" replaced with a clear non-goal statement and pointer tocallExtension('android.provider', 'queryWithJoins').docs/RELEASE.md— adds a "CHANGELOG discipline" section documenting the Unreleased → release promotion flow.SimpleQueryPlatform(platform interface) now has class-level and per-method dartdoc. Documents thatinstance =is not thread-safe.SimpleQuery(facade) class doc calls out the singleton contract explicitly and explains how tests swap the backend (viaSimpleQueryPlatform.instance, not the facade).- Every facade passthrough (
query,mutate,batch,observe,callExtension,dispose) now has a dartdoc block with cross-links. QueryDomainContractsandCapabilityContractshave class-level dartdoc.
Example app #
- Rewritten to showcase the full 0.5.0 API:
queryBuilder,queryPaginated,mutateround-trip,observewith live filesystem events,withBinaryContent,callExtension(platform-aware), andqueryRaw(Android). Buttons are capability-gated; a refresh button re-probes.
Migration #
None required — docs/example/dartdoc changes only.
0.5.0 #
Consumer-ergonomics release. Additive — no breaking changes from 0.4.0.
Added #
SimpleQuery.queryPaginated(request)— returns aStream<QueryResult>that walksnextCursor/nextOffsetto exhaustion. Cursor is preferred when both are present; stops on the first empty page or when both pagination tokens are null. Cancellable via the stream subscription.SimpleQuery.queryPaginatedTyped<T>(request, fromRecord)— same but maps each page throughfromRecord. Mapping failures wrapped inSimpleQueryError(invalidQuery, details: {recordIndex, cause})likequeryTyped.BinaryContentclass wrapsBinaryContentHandlewith typed getters and a self-closingclose()that's idempotent.SimpleQuery.openBinaryContent(request)— opens binary content as aBinaryContent.SimpleQuery.withBinaryContent(request, body)— scoped helper that runsbodywith an openBinaryContentand guarantees close on return or throw.SimpleQuery.queryBuilder(domain)— fluent entry point for building queries off the facade instead of importingQueryBuilderdirectly.QueryBuilder.pageOffset({limit, required offset})andpageCursor({limit, required cursor})— type-safe pagination convenience methods.QueryBuilder.executePaginated()— convenience forqueryPaginated(build()).
Changed #
QueryBuilder.build()now validates filter/sort/projection field names againstQueryFieldCatalogbefore returning. Unknown canonical fields throwSimpleQueryError(invalidQuery, details: {field, allowed})instead of failing later in the platform layer with a less actionable error. No-op forQueryDomain.platformSpecific.
Tooling #
- Pigeon dependency pinned to exact version
22.7.4in every platform package — different developers will produce identical generated output. - New
tool/regen_pigeon.shregenerates every platform's pigeon glue and runsdart formaton the output for stable line-wrap. - New
pigeon-driftCI job re-runs the regen tool and fails the build if the committed.g.dart/.g.ktare stale. Catches "edited pigeon.dart but forgot to commit the regen" before merge.
Migration #
None required. All additions are new methods; existing code keeps working.
Deferred #
- Typed
callExtensionregistry (plan 2.5) — needs concrete consumer demand to design correctly; rawcallExtensionremains the supported path.
0.4.0 #
Breaking changes #
- Filter / sort / projection field vocabulary is now canonical on every named domain. Callers must pass the canonical names (
callType,timestamp,durationSec,id, ...) defined inQueryFieldCatalog.canonicalFields(domain). Raw native column names (type,date,_id, ...) on a named domain throwSimpleQueryError(invalidQuery, details: {field, allowed}). UseQueryDomain.platformSpecific(orSimpleQuery.queryRaw) when you need raw column names. - Android:
simple_permissions_nativedependency dropped. TheSimpleQueryAndroidApiconstructor no longer takes acheckPermissioncallback. simple_query checks permissions inline via a new pigeonhasPermissioncall and throwsSimpleQueryError(permissionDenied, details: {permissions: [...], contentUri, write})when a permission is missing. Callers request the permission via their own mechanism (permission_handler,simple_permissions, rawActivityCompat.requestPermissions) and retry.
Added #
QueryFieldCatalog(insimple_query_platform_interface) — single source of truth for the canonical field vocabulary per domain. ExposescanonicalFields(domain),ensureKnown({domain, canonical}), andensureAllKnown({domain, fields}). No-op forQueryDomain.platformSpecific.RuntimeContractValidation.validateQueryRequest/validateMutationRequest(extended) /validateObserveRequest(extended) now reject unknown canonical fields with a clear error before reaching the platform.SimpleQuery.queryRaw({contentUri, ...})— first-class entry point for arbitrary content providers (content://com.biz.app/...). Bypasses canonical validation; returns rawMap<String, Object?>records. Currently Android-only.- Every typed
*Record(Contact, CalendarEvent, Media, File, Message, Call) now exposesraw: Map<String, Object?>(untouched source map) andextras: Map<String, Object?>(raw minus canonical keys). Surfaces OEM and niche columns without losing the typed view. CallRecordgains the optional canonical fieldsisNew,isRead,geocodedLocation,subscriptionId, populated by Android from native columnsnew,is_read,geocoded_location,subscription_id. Absent (not defaulted) on devices that don't expose the column. Closes the gap surfaced bysimple-telephony'slistCallLoghandoff.
Changed #
- Android backend now translates canonical filter / sort / projection field names to native ContentResolver columns symmetrically (output records were already canonical). New
_AndroidFieldAliaseshelper centralises the mapping;platformSpecificskips translation. - Apple
permissionDeniederrors now carrydetails: {framework, infoPlistKey, authorizationStatus}so callers learn exactly which Info.plist usage description to declare. - Filesystem fallback (Linux / Windows / non-Android desktop) maps
FileSystemExceptionwith errno 1 / 13 / 5 (EPERM, EACCES, ERROR_ACCESS_DENIED) toSimpleQueryErrorCode.permissionDeniedinstead of the previousunavailable. validateBatchRequestno longer cascades to per-operation validation. Batches are sequentialBestEffort — a malformed op records its error in per-resultmetadata.errorinstead of aborting the batch.
Migration #
- If you currently filter or sort on a named domain using raw Android column names, switch to canonical names. Example:
field: 'type'→field: 'callType',field: 'date'→field: 'timestamp',field: '_id'→field: 'id'. Full catalog:QueryFieldCatalog.canonicalFields(domain). - If you constructed
SimpleQueryAndroidApidirectly withcheckPermission:, drop the argument. The internal pigeon-based permission check replaces it. Permission requests stay your responsibility. - If your app handled
SimpleQueryErrorCode.unavailablefor filesystem permission errors, add apermissionDeniedbranch.
0.3.1 #
Added #
- Strict type coercion in record parsers (
records.dart).ContactRecord,CalendarEventRecord,MediaRecord,FileRecord,MessageRecord,CallRecordnow throwSimpleQueryError(invalidQuery)with the offending field name and runtimeType instead of silently returning[],"Instance of 'Map'", or misinterpreting1/"true"asfalse. - Runtime contract coverage:
RuntimeContractValidationgainsvalidateMutationRequest,validateBatchRequest,validateObserveRequest,validateBinaryRequest.validateQueryResultnow includesdomainin error details. - Constructor guards:
QueryPageassertsoffsetandcursorare mutually exclusive and addsQueryPage.offset/QueryPage.cursornamed constructors.QueryFilterConditionasserts thatinListoperator carries aListvalue. - New
testing.dartentry point exportsFakeSimpleQueryPlatformfor use by both this package's own tests and sibling packages, replacing the duplicated private fakes that had drifted between them.
Changed #
SimpleQueryError.toString()now appends thedetailsmap so log output surfaces the contextual fields (missingDomains,recordIndex,field, etc.) that were being constructed but never rendered.- Every
copyWiththat takes nullable fields now accepts explicitnullto clear the value. Previously allcopyWithmethods usedfield ?? this.field, making it impossible to move aQueryPagefrom offset-mode to cursor-mode or to unsetmetadata/nextOffset/nextCursor/entityType/pollingIntervalon any request/result. Uses an_unsetsentinel under the hood.
Developer-facing #
- Coordinated 0.3.1 release across all simple_query packages. Adopting lock-step versioning so consumers see a single matching version across facade, interface, and platform implementations.
0.3.0 #
Added — native Kotlin helper #
ContentQueryobject (inpackages/simple_query_android) exposes a public Kotlin API for content-provider queries that sibling plugins can call from their own Kotlin code. Previously the only shared query API was Dart-side (via Pigeon), forcing sibling plugins' internal Kotlin helpers to reach forContentResolver.query(...)directly — losing the "simple_queryowns content-provider access" invariant.ContentQuery.query(context, contentUri, projection?, selection?, selectionArgs?, sortOrder?): List<Map<String, Any?>>— mirrorsContentResolver.query(...)'s parameter list; returns rows as(columnName -> value)maps; empty list on null cursor.ContentQuery.drainRows(cursor): List<Map<String, Any?>>— helper for already-opened cursors.- Matches the Pigeon path's BLOB-to-null coercion so callers can swap between the two without downstream changes.
- Consumers wire the helper with
implementation(project(":simple_query_android"))in their plugin'sandroid/build.gradle. Same two-line cross-repo pattern documented insimple_permissions_android.PermissionGuards— works out of the box via Flutter's plugin-loader if the consuming plugin declaressimple_queryat the pub level.
0.2.0 #
- Initial public release.
- Federated plugin architecture with per-platform packages.
- Typed query API with 7 domains: contacts, media, files, calendar, messages, calls, platformSpecific.
- Cursor-based and offset-based pagination.
- Capability-driven design via
getCapabilities(). - Typed record classes:
ContactRecord,CalendarEventRecord,MediaRecord,FileRecord,MessageRecord,CallRecord. - Structured error model with 5 error codes.
- Cross-platform support: Android (full), iOS/macOS (contacts, calendar, files, media), Windows/Linux (contacts, calendar, files, media).