import { EMPTY , Observable } from 'rxjs' ; import { concatMap , expand , map , toArray } from 'rxjs/operators' ; import { ODataApi } from '../../api' ; import { ODataCollection , ODataModel } from '../../models' ; import { ODataStructuredType , ODataStructuredTypeParser } from '../../schema' ; import { PathSegmentNames } from '../../types' ; import { ODataPathSegments } from '../path' ; import { ODataQueryOptions } from '../query' ; import { ODataResource } from '../resource' ; import { ODataEntities , ODataEntitiesAnnotations , ODataEntity , ODataEntityAnnotations , ODataProperty , } from '../responses' ; import { ODataEntitiesOptions , ODataEntityOptions , ODataOptions , ODataPropertyOptions , } from './options' ; import { ODataValueResource } from './value' ; export class ODataPropertyResource < T > extends ODataResource < T > { static factory < P > ( api , { path , type , schema , segments , query , } ) { const segment = segments . add ( PathSegmentNames . property , path ) ; if ( schema !== undefined ) segment . type ( schema . type ( ) ) ; else if ( type !== undefined ) segment . type ( type ) ; query ?. clear ( ) ; return new ODataPropertyResource < P > ( api , { segments , query , schema , } ) ; } static fromResource < N > ( resource , path ) { const baseType = resource . type ( ) ; let baseSchema = resource . schema as ODataStructuredType < any > | undefined ; let fieldType ; let fieldSchema ; if ( baseSchema !== undefined ) { const field = baseSchema . findFieldByName < N > ( path ) ; fieldType = field ?. type ; fieldSchema = fieldType !== undefined ? resource . api . findStructuredTypeForType ( fieldType ) : undefined ; baseSchema = field !== undefined ? baseSchema . findSchemaForField < N > ( field ) : undefined ; } const property = ODataPropertyResource . factory < N > ( resource . api , { path , type : fieldType , schema : fieldSchema , segments : resource . cloneSegments ( ) , query : resource . cloneQuery < N > ( ) , } ) ; if ( baseSchema !== undefined && baseSchema . type ( ) !== baseType ) { let entitySet = resource . api . findEntitySetForType ( baseSchema . type ( ) ) ; if ( entitySet !== undefined ) { property . segment ( ( s ) => s . entitySet ( ) . path ( entitySet ! . name ) ) ; } } return property ; } key ( value ) { const property = this . clone < ODataPropertyResource < T > > ( ) ; var key = this . resolveKey ( value ) ; if ( key !== undefined ) property . segment ( ( s ) => s . property ( ) . key ( key ) ) ; return property ; } keys ( values ) { const property = this . clone < ODataPropertyResource < T > > ( ) ; const types = this . pathSegments . types ( { key : true } ) ; const keys = values . map ( ( value , index ) => ODataResource . resolveKey ( value , this . api . findStructuredTypeForType < T > ( types [ index ] ) ) ) ; property . segment ( ( s ) => s . keys ( keys ) ) ; return property ; } value ( ) { return ODataValueResource . factory < T > ( this . api , { type : this . returnType ( ) , schema : this . schema as ODataStructuredType < T > , segments : this . cloneSegments ( ) , query : this . cloneQuery < T > ( ) , } ) ; } property < P > ( path ) { let type ; let schema ; if ( this . schema instanceof ODataStructuredType ) { const field = this . schema . findFieldByName < any > ( path as keyof T ) ; type = field ?. type ; schema = field !== undefined ? this . schema . findSchemaForField < P > ( field ) : undefined ; } return ODataPropertyResource . factory < P > ( this . api , { path , type , schema , segments : this . cloneSegments ( ) , query : this . cloneQuery < P > ( ) , } ) ; } protected override get ( options ) { return super . get ( options ) ; } param options return fetch ( options ? ) ; fetch ( options ? ) ; fetch ( options ? ) ; fetch ( options = { } ) { return this . get ( options ) ; } param options returns fetchProperty ( options = { } ) { return this . fetch ( { responseType : 'property' , ... options } ) . pipe ( map ( ( { property } ) => property ) ) ; } param options returns fetchEntity ( options = { } ) { return this . fetch ( { responseType : 'entity' , ... options } ) . pipe ( map ( ( { entity } ) => entity ) ) ; } param options returns fetchModel < M extends ODataModel < T > > ( options = { } ) { return this . fetch ( { responseType : 'entity' , ... options } ) . pipe ( map ( ( { entity , annots } ) => entity ? this . asModel < M > ( entity , { annots , reset : true } ) : null ) ) ; } param options returns fetchEntities ( options = { } ) { return this . fetch ( { responseType : 'entities' , ... options } ) . pipe ( map ( ( { entities } ) => entities ) ) ; } param options returns fetchCollection < M extends ODataModel < T > , C extends ODataCollection < T , M > > ( options = { } ) { return this . fetch ( { responseType : 'entities' , ... options } ) . pipe ( map ( ( { entities , annots } ) => entities ? this . asCollection < M , C > ( entities , { annots , reset : true } ) : null ) ) ; } param options returns fetchAll ( options = { } ) { let res = this . clone < ODataPropertyResource < T > > ( ) ; res . query ( ( q ) => q . clearPaging ( ) ) ; let fetch = ( opts ? ) : Observable < ODataEntities < T > > => { if ( opts ) { res . query ( ( q ) => q . paging ( opts ) ) ; } return res . fetch ( { responseType : 'entities' , ... options } ) ; } ; return fetch ( ) . pipe ( expand ( ( { annots : meta } ) => meta . skip || meta . skiptoken ? fetch ( meta ) : EMPTY ) , concatMap ( ( { entities } ) => entities || [ ] ) , toArray ( ) ) ; } }