feat: expand Export API protocol with full CRUD endpoints and IExportService contract#768
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…ract, and cursor-based pagination Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR expands the Export API from 2 basic endpoints to a complete CRUD lifecycle with 6 endpoints, adds the IExportService contract for dependency inversion, and implements cursor-based pagination in the data protocol. The implementation aligns with the "Post-SaaS Operating System" vision by providing a comprehensive data export and scheduling infrastructure.
Changes:
- Added 4 new Export API endpoints: download link retrieval, job listing with pagination, scheduled exports, and job cancellation
- Created
IExportServicecontract with 6 required methods and 2 optional template methods following dependency inversion principles - Enhanced
FindDataResponseSchemawithnextCursorfield for cursor-based pagination, aligning with patterns in Feed and Automation APIs - Added 18 comprehensive test cases covering all new schemas and contracts
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/spec/src/api/export.zod.ts | Expanded ExportApiContracts from 2 to 6 endpoints with download, listing, scheduling, and cancellation schemas |
| packages/spec/src/api/protocol.zod.ts | Added nextCursor field to FindDataResponseSchema for cursor-based pagination support |
| packages/spec/src/contracts/export-service.ts | New IExportService interface with 6 required methods and 2 optional template methods; imports API response types instead of domain types (issue identified) |
| packages/spec/src/contracts/export-service.test.ts | Contract validation tests; test mocks return API response wrappers instead of domain types (issue identified) |
| packages/spec/src/api/export.test.ts | 18 new test cases for download, listing, and scheduling schemas |
| packages/spec/src/contracts/index.ts | Export statement for new export-service contract |
| ROADMAP.md | Updated roadmap with completed export API features |
| import type { | ||
| ExportFormat, | ||
| ExportJobStatus, | ||
| ExportJobProgress, | ||
| ExportJobSummary, | ||
| ExportImportTemplate, | ||
| ScheduledExport, | ||
| } from '../api/export.zod'; |
There was a problem hiding this comment.
The getExportJobProgress method returns ExportJobProgress | null, but ExportJobProgress is imported from api/export.zod.ts which is the full API response schema (includes success and data fields from BaseResponseSchema).
Service contracts should return domain types, not API response wrappers. Following the pattern used in IFeedService and IAutomationService, this method should either:
- Define a new interface type in this file that represents just the progress data, OR
- Create a domain type in a separate file under
data/orsystem/and import from there
The API layer is responsible for wrapping service results in the BaseResponseSchema format. The service layer should work with plain domain objects.
| getExportJobProgress: async (jobId) => { | ||
| const job = jobs.get(jobId); | ||
| if (!job) return null; | ||
| return { | ||
| success: true, | ||
| data: { | ||
| jobId, | ||
| status: job.status, | ||
| format: job.input.format ?? 'csv', | ||
| processedRecords: 0, | ||
| percentComplete: 0, | ||
| }, | ||
| }; | ||
| }, |
There was a problem hiding this comment.
The test mock for getExportJobProgress returns an object with success and data fields (lines 54-63), which matches the API response schema structure. However, the IExportService.getExportJobProgress method signature indicates it should return ExportJobProgress | null.
Since there's an issue with the service contract using API response types (see comment on import statement), this test implementation is actually incorrect and masks the type mismatch. Once the service contract is fixed to return a proper domain type, this test will need to be updated to return just the progress data without the API wrapper.
Export API had only 2 endpoints (create + progress). This adds the remaining endpoints needed for the full export lifecycle: download, listing, scheduling, and cancellation. Also adds the
IExportServicecontract and cursor-based pagination ondata.find().New schemas in
api/export.zod.tsGetExportJobDownloadRequest/Response— presigned download URL with file metadata and checksumListExportJobsRequest/Response+ExportJobSummary— paginated job history with cursor-based paginationScheduleExportRequest/Response— recurring export creationExportApiContractsexpanded from 2 → 6 endpoints (+getExportJobDownload, listExportJobs, scheduleExport, cancelExportJob)IExportServicecontract (contracts/export-service.ts)createExportJob,getExportJobProgress,getExportJobDownload,cancelExportJob,listExportJobs,scheduleExportgetTemplate,listTemplatesCursor-based pagination in
FindDataResponseSchemanextCursorfield alongside existinghasMore, aligning with the pattern already used inListRecordResponseSchema,FeedApiContracts, andAutomationApiContractsTests
export.test.tsandexport-service.test.tsOriginal prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.