@@ -84,6 +84,13 @@ import {
8484 ApiRoutes ,
8585 ImportRequest ,
8686 ImportResponse ,
87+ CreateImportJobRequest ,
88+ CreateImportJobResponse ,
89+ ImportJobProgress ,
90+ ImportJobResults ,
91+ ImportJobSummary ,
92+ ListImportJobsRequest ,
93+ ListImportJobsResponse ,
8794} from '@objectstack/spec/api' ;
8895import type {
8996 ApprovalRequestRow ,
@@ -3067,6 +3074,62 @@ export class ObjectStackClient {
30673074 return this . unwrapResponse < ImportResponse > ( res ) ;
30683075 } ,
30693076
3077+ /**
3078+ * Import-job namespace — the asynchronous counterpart to {@link import} for
3079+ * large files (up to 50,000 rows). `createImportJob` posts the whole payload
3080+ * once and returns immediately with a `jobId`; a server worker processes the
3081+ * batch in the background. Poll {@link getImportJobProgress} for live
3082+ * counters, {@link getImportJobResults} for the capped per-row report, and
3083+ * {@link listImportJobs} for history. {@link cancelImportJob} stops a
3084+ * pending/running job cooperatively.
3085+ *
3086+ * These routes require a server new enough to expose them — older servers
3087+ * return 404, which surfaces here as a rejected promise. Callers that want
3088+ * graceful degradation should feature-detect (e.g. try the job, fall back
3089+ * to the synchronous {@link import} on 404).
3090+ */
3091+ createImportJob : async ( object : string , request : CreateImportJobRequest ) : Promise < CreateImportJobResponse > => {
3092+ const route = this . getRoute ( 'data' ) ;
3093+ const res = await this . fetch ( `${ this . baseUrl } ${ route } /${ object } /import/jobs` , {
3094+ method : 'POST' ,
3095+ body : JSON . stringify ( request ) ,
3096+ } ) ;
3097+ return this . unwrapResponse < CreateImportJobResponse > ( res ) ;
3098+ } ,
3099+
3100+ getImportJobProgress : async ( jobId : string ) : Promise < ImportJobProgress > => {
3101+ const route = this . getRoute ( 'data' ) ;
3102+ const res = await this . fetch ( `${ this . baseUrl } ${ route } /import/jobs/${ encodeURIComponent ( jobId ) } ` ) ;
3103+ return this . unwrapResponse < ImportJobProgress > ( res ) ;
3104+ } ,
3105+
3106+ getImportJobResults : async ( jobId : string ) : Promise < ImportJobResults > => {
3107+ const route = this . getRoute ( 'data' ) ;
3108+ const res = await this . fetch ( `${ this . baseUrl } ${ route } /import/jobs/${ encodeURIComponent ( jobId ) } /results` ) ;
3109+ return this . unwrapResponse < ImportJobResults > ( res ) ;
3110+ } ,
3111+
3112+ listImportJobs : async ( query : Partial < ListImportJobsRequest > = { } ) : Promise < ImportJobSummary [ ] > => {
3113+ const route = this . getRoute ( 'data' ) ;
3114+ const qs = new URLSearchParams ( ) ;
3115+ if ( query . object ) qs . set ( 'object' , query . object ) ;
3116+ if ( query . status ) qs . set ( 'status' , query . status ) ;
3117+ if ( query . limit != null ) qs . set ( 'limit' , String ( query . limit ) ) ;
3118+ if ( query . offset != null ) qs . set ( 'offset' , String ( query . offset ) ) ;
3119+ const suffix = qs . toString ( ) ? `?${ qs . toString ( ) } ` : '' ;
3120+ const res = await this . fetch ( `${ this . baseUrl } ${ route } /import/jobs${ suffix } ` ) ;
3121+ const body = await this . unwrapResponse < ListImportJobsResponse > ( res ) ;
3122+ return body . jobs ;
3123+ } ,
3124+
3125+ cancelImportJob : async ( jobId : string ) : Promise < { success : boolean } > => {
3126+ const route = this . getRoute ( 'data' ) ;
3127+ const res = await this . fetch ( `${ this . baseUrl } ${ route } /import/jobs/${ encodeURIComponent ( jobId ) } /cancel` , {
3128+ method : 'POST' ,
3129+ } ) ;
3130+ return this . unwrapResponse < { success : boolean } > ( res ) ;
3131+ } ,
3132+
30703133 update : async < T = any > (
30713134 object : string ,
30723135 id : string ,
@@ -3492,6 +3555,43 @@ export class ScopedProjectClient {
34923555 } ) ;
34933556 return this . parent . _unwrap < ImportResponse > ( res ) ;
34943557 } ,
3558+ /**
3559+ * Asynchronous import jobs (scoped) — see the top-level `data.createImportJob`
3560+ * for semantics. Large payloads are posted once; a server worker processes
3561+ * them in the background while callers poll progress / results / history.
3562+ */
3563+ createImportJob : async ( object : string , request : CreateImportJobRequest ) : Promise < CreateImportJobResponse > => {
3564+ const res = await this . parent . _fetch ( this . url ( `/data/${ object } /import/jobs` ) , {
3565+ method : 'POST' ,
3566+ body : JSON . stringify ( request ) ,
3567+ } ) ;
3568+ return this . parent . _unwrap < CreateImportJobResponse > ( res ) ;
3569+ } ,
3570+ getImportJobProgress : async ( jobId : string ) : Promise < ImportJobProgress > => {
3571+ const res = await this . parent . _fetch ( this . url ( `/data/import/jobs/${ encodeURIComponent ( jobId ) } ` ) ) ;
3572+ return this . parent . _unwrap < ImportJobProgress > ( res ) ;
3573+ } ,
3574+ getImportJobResults : async ( jobId : string ) : Promise < ImportJobResults > => {
3575+ const res = await this . parent . _fetch ( this . url ( `/data/import/jobs/${ encodeURIComponent ( jobId ) } /results` ) ) ;
3576+ return this . parent . _unwrap < ImportJobResults > ( res ) ;
3577+ } ,
3578+ listImportJobs : async ( query : Partial < ListImportJobsRequest > = { } ) : Promise < ImportJobSummary [ ] > => {
3579+ const qs = new URLSearchParams ( ) ;
3580+ if ( query . object ) qs . set ( 'object' , query . object ) ;
3581+ if ( query . status ) qs . set ( 'status' , query . status ) ;
3582+ if ( query . limit != null ) qs . set ( 'limit' , String ( query . limit ) ) ;
3583+ if ( query . offset != null ) qs . set ( 'offset' , String ( query . offset ) ) ;
3584+ const suffix = qs . toString ( ) ? `?${ qs . toString ( ) } ` : '' ;
3585+ const res = await this . parent . _fetch ( this . url ( `/data/import/jobs${ suffix } ` ) ) ;
3586+ const body = await this . parent . _unwrap < ListImportJobsResponse > ( res ) ;
3587+ return body . jobs ;
3588+ } ,
3589+ cancelImportJob : async ( jobId : string ) : Promise < { success : boolean } > => {
3590+ const res = await this . parent . _fetch ( this . url ( `/data/import/jobs/${ encodeURIComponent ( jobId ) } /cancel` ) , {
3591+ method : 'POST' ,
3592+ } ) ;
3593+ return this . parent . _unwrap < { success : boolean } > ( res ) ;
3594+ } ,
34953595 update : async < T = any > ( object : string , id : string , data : Partial < T > ) : Promise < UpdateDataResult < T > > => {
34963596 const res = await this . parent . _fetch ( this . url ( `/data/${ object } /${ id } ` ) , {
34973597 method : 'PATCH' ,
@@ -3674,6 +3774,13 @@ export type {
36743774 AuthProviderInfo ,
36753775 EmailPasswordConfigPublic ,
36763776 AuthFeaturesConfig ,
3777+ CreateImportJobRequest ,
3778+ CreateImportJobResponse ,
3779+ ImportJobProgress ,
3780+ ImportJobResults ,
3781+ ImportJobSummary ,
3782+ ListImportJobsRequest ,
3783+ ListImportJobsResponse ,
36773784} from '@objectstack/spec/api' ;
36783785
36793786// Approval runtime types (ADR-0019) — surfaced so SDK consumers can type the
0 commit comments