Skip to content

Organizations resource + Page<T> + list-options pattern #3

@fbarrento

Description

@fbarrento

What to build

First paginated, list-style resource. Introduces the generic Page<T> for cursor-based pagination and the List{Resource}Options DTO pattern that every subsequent list endpoint will reuse.

Endpoints (from docs/forge.openapi.json): GET /orgs, GET /orgs/{slug}.

Source design: see project_sdk_design.md in the project's memory.

Acceptance criteria

Generic infrastructure

  • Page<T> generic readonly class: properties data: list<T>, nextCursor: ?string, prevCursor: ?string, size: int. Implements IteratorAggregate (yields data) and JsonSerializable. Methods: hasMore(): bool, getIterator(): Generator.
  • Helper for parsing Forge's pagination envelope into Page<T> — confirm exact response shape and cursor field names from docs/forge.openapi.json (Forge uses page[size] / page[cursor] on input)

Organizations slice

  • Organization DTO (readonly, JsonSerializable, ::from(array) throws on unknown keys)
  • ListOrganizationsOptions readonly DTO: size?: int, cursor?: string, sort?: string, plus any filter[...] keys the spec defines on /orgs. Has toQuery(): array that emits the Forge query-string shape (e.g. page[size]=30&page[cursor]=...)
  • GetOrganizationsRequest, GetOrganizationRequest (Saloon requests)
  • OrganizationsResource with all(?ListOrganizationsOptions): Page<Organization> and iterate(?ListOrganizationsOptions): Generator<Organization>
  • OrganizationResource (singular) with get(): Organization
  • $forge->organizations()OrganizationsResource, $forge->organization($slug)OrganizationResource

Tests

  • $forge->organizations()->all() returns a populated Page<Organization> against a mocked response
  • Page::hasMore() is true when nextCursor is set, false when not
  • iterate() makes successive requests through nextCursor and stops cleanly
  • ListOrganizationsOptions::toQuery() emits page[size] / page[cursor] / sort correctly
  • $forge->organization('acme')->get() returns a hydrated Organization
  • composer test green

Blocked by

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions