Skip to content

feat(client): Complete @objectstack/client to cover full spec API surface #565

@hotlong

Description

@hotlong

Summary

The @objectstack/client currently implements ~51% of the spec-defined protocol (26/51 methods across 7/14 domains). This issue tracks completing the remaining API surface to achieve full spec compliance.

Current Coverage

✅ Fully Implemented (7 domains)

  • Discoveryconnect() with well-known fallback
  • Metadatameta.getTypes/getItems/getItem/saveItem/getCached/getView
  • Data CRUDdata.find/get/create/update/delete
  • Batchdata.batch/createMany/updateMany/deleteMany
  • Storagestorage.upload/getDownloadUrl
  • Analyticsanalytics.query/meta/explain
  • Packagespackages.list/get/install/uninstall/enable/disable

❌ Missing Domains (5 domains, ~25 methods)

Tasks

P0 — Critical

  • Permissions namespace (client.permissions.*)

    • checkPermission({ object, action, recordId?, field? })GET /permissions/check
    • getObjectPermissions({ object })GET /permissions/objects/:object
    • getEffectivePermissions()GET /permissions/effective
    • Reference: ObjectStackProtocol in packages/spec/src/api/protocol.zod.ts
  • Realtime namespace (client.realtime.*)

    • connect({ transport?, channels?, token? }) — WebSocket/SSE connection
    • disconnect()
    • subscribe({ channel, events?, filter? }) → returns subscriptionId
    • unsubscribe({ subscriptionId })
    • setPresence({ channel, state })
    • getPresence({ channel })
    • Reference: WebSocketMessageSchema in packages/spec/src/api/websocket.zod.ts

P1 — Important

  • Workflow namespace (client.workflow.*)

    • getConfig({ object })GET /workflow/:object/config
    • getState({ object, recordId })GET /workflow/:object/:id/state
    • transition({ object, recordId, transition, comment?, data? })
    • approve({ object, recordId, comment?, data? })
    • reject({ object, recordId, reason, comment? })
  • Views CRUD namespace (client.views.*)

    • list({ object, type? })GET /ui/views/:object
    • get({ object, viewId })GET /ui/views/:object/:viewId
    • create({ object, data })POST /ui/views/:object
    • update({ object, viewId, data })PUT /ui/views/:object/:viewId
    • delete({ object, viewId })DELETE /ui/views/:object/:viewId
  • Auth enhancements

    • auth.register(request)POST /auth/register
    • auth.refreshToken(refreshToken)POST /auth/refresh
  • QueryBuilder enhancements — add fluent methods for:

    • .expand(relation, subQuery) — nested relation loading
    • .search(query, options?) — full-text search
    • .cursor(cursor) — keyset pagination
    • .distinct() — SELECT DISTINCT
    • .between(field, min, max) on FilterBuilder
    • .contains(field, value) on FilterBuilder
    • .startsWith(field, value) on FilterBuilder
    • .endsWith(field, value) on FilterBuilder
    • .exists(field) on FilterBuilder

P2 — Nice to Have

  • Notifications namespace (client.notifications.*)

    • registerDevice, unregisterDevice
    • getPreferences, updatePreferences
    • list, markRead, markAllRead
  • AI namespace (client.ai.*)

    • nlq({ query, object?, conversationId? })
    • chat({ message, conversationId?, context? })
    • suggest({ object, field?, recordId?, partial? })
    • insights({ object, recordId?, type? })
  • i18n namespace (client.i18n.*)

    • getLocales()
    • getTranslations({ locale, namespace?, keys? })
    • getFieldLabels({ object, locale })
  • QueryBuilder advanced — fluent methods for:

    • .join(object, on, type?) — explicit joins
    • .having(filter) — HAVING clause
    • .window(fn, partitionBy, orderBy) — window functions

Implementation Guidelines

  1. Follow the existing namespace pattern in packages/client/src/index.ts (e.g., client.meta.*, client.data.*)
  2. All methods should call this.request() internally and use unwrapResponse() for envelope stripping
  3. Use route resolution via getRoute(type) with fallback to conventional paths
  4. Types should be imported from @objectstack/spec/api where available
  5. Add corresponding tests in client.test.ts (unit) and client.msw.test.ts (integration)
  6. Export all new types from index.ts

Acceptance Criteria

  • All P0 methods implemented with full type safety
  • Unit tests for each new namespace (mocked fetch)
  • Integration tests with MSW for P0 methods
  • All existing tests continue to pass
  • Exported types align with spec schemas
  • README.md updated with new namespace documentation

References

  • Spec protocol: packages/spec/src/api/protocol.zod.ts
  • REST routes: packages/spec/src/api/router.zod.ts
  • Contracts: packages/spec/src/contracts/
  • Existing client: packages/client/src/index.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions