升级 SDK API 数据契约,补齐 guideStops、业务 POI、诊断与路线数据接口。 修复 SDK 模式下 POI/模型/楼层混用静态数据的问题,并为 ThreeMap 模型加载增加短退避重试。
601 lines
18 KiB
TypeScript
601 lines
18 KiB
TypeScript
import {
|
|
dataSourceConfig
|
|
} from '@/config/dataSource'
|
|
|
|
export type SgsDiagnosticsStatusPayload = 'OK' | 'WARN' | 'ERROR'
|
|
|
|
export interface SgsSdkFloorSummaryPayload {
|
|
floorId: string | number
|
|
floorCode?: string | null
|
|
floorName?: string | null
|
|
sortOrder?: number | null
|
|
modelSizeBytes?: number | null
|
|
poiCount?: number | null
|
|
spaceCount?: number | null
|
|
}
|
|
|
|
export interface SgsSdkManifestPayload {
|
|
mapId: string | number
|
|
mapName?: string | null
|
|
sdkVersion?: string | null
|
|
protocolVersion?: number | null
|
|
dataVersion?: string | null
|
|
updatedAt?: string | null
|
|
coordinateSystem?: string | null
|
|
floors: SgsSdkFloorSummaryPayload[]
|
|
capabilities?: Record<string, boolean | undefined>
|
|
}
|
|
|
|
export type SgsPoiGroupPayload = 'SERVICE' | 'BUSINESS' | 'OTHER'
|
|
|
|
export type SgsBusinessPoiTypePayload =
|
|
| 'shop'
|
|
| 'restaurant'
|
|
| 'cafe'
|
|
| 'vending'
|
|
| 'bookstore'
|
|
| 'cultural_shop'
|
|
| 'photo_spot'
|
|
| string
|
|
|
|
export interface SgsPoiQueryParamsPayload {
|
|
mapId?: string | number
|
|
floorId?: string | number
|
|
group?: SgsPoiGroupPayload
|
|
types?: string[]
|
|
keyword?: string
|
|
limit?: number
|
|
}
|
|
|
|
export interface SgsPositionPayload {
|
|
x?: number | null
|
|
y?: number | null
|
|
z?: number | null
|
|
}
|
|
|
|
export interface SgsPoiPayload {
|
|
id: string | number
|
|
name?: string | null
|
|
type?: string | null
|
|
typeName?: string | null
|
|
floorCode?: string | null
|
|
floorId?: string | number | null
|
|
position?: SgsPositionPayload | null
|
|
x?: number | null
|
|
y?: number | null
|
|
z?: number | null
|
|
status?: string | null
|
|
anchorNodeName?: string | null
|
|
description?: string | null
|
|
iconUrl?: string | null
|
|
poiGroup?: SgsPoiGroupPayload | string | null
|
|
businessType?: SgsBusinessPoiTypePayload | null
|
|
coverImageUrl?: string | null
|
|
phone?: string | null
|
|
businessHours?: string | null
|
|
sortOrder?: number | null
|
|
spatialAreaId?: string | number | null
|
|
spatialAreaName?: string | null
|
|
}
|
|
|
|
export interface SgsSpacePayload {
|
|
id: string | number
|
|
name?: string | null
|
|
type?: string | null
|
|
floorId?: string | number | null
|
|
boundaryWkt?: string | null
|
|
center?: SgsPositionPayload | null
|
|
sourceNodeName?: string | null
|
|
status?: string | null
|
|
colorHex?: string | null
|
|
}
|
|
|
|
export interface SgsNavigablePlacePayload {
|
|
id?: string | number | null
|
|
name?: string | null
|
|
category?: string | null
|
|
type?: string | null
|
|
typeCode?: string | null
|
|
typeName?: string | null
|
|
floorId?: string | number | null
|
|
floorCode?: string | null
|
|
floorName?: string | null
|
|
position?: SgsPositionPayload | null
|
|
x?: number | null
|
|
y?: number | null
|
|
z?: number | null
|
|
nodeId?: string | number | null
|
|
ownerName?: string | null
|
|
}
|
|
|
|
export interface SgsGuideStopPayload {
|
|
id: string | number
|
|
name?: string | null
|
|
type?: string | null
|
|
typeName?: string | null
|
|
floorId?: string | number | null
|
|
position?: SgsPositionPayload | null
|
|
x?: number | null
|
|
y?: number | null
|
|
z?: number | null
|
|
targetType?: string | null
|
|
targetId?: string | number | null
|
|
audioUrl?: string | null
|
|
coverImageUrl?: string | null
|
|
description?: string | null
|
|
status?: string | null
|
|
located?: boolean | null
|
|
hasAudio?: boolean | null
|
|
poiId?: string | number | null
|
|
outlineId?: string | number | null
|
|
outlineName?: string | null
|
|
hallId?: string | number | null
|
|
hallName?: string | null
|
|
sort?: number | null
|
|
routeId?: string | number | null
|
|
routeName?: string | null
|
|
seqOrder?: number | null
|
|
stayMinutes?: number | null
|
|
}
|
|
|
|
export interface SgsFloorDiagnosticsPayload {
|
|
floorId: string | number
|
|
floorCode?: string | null
|
|
floorName?: string | null
|
|
status: SgsDiagnosticsStatusPayload
|
|
modelReady?: boolean
|
|
poiCount?: number
|
|
spaceCount?: number
|
|
guideStopCount?: number
|
|
navigablePlaceCount?: number
|
|
routeNodeCount?: number
|
|
routeEdgeCount?: number
|
|
routePlanningReady?: boolean
|
|
warnings?: string[]
|
|
}
|
|
|
|
export interface SgsFloorDiagnosticsSummaryPayload extends SgsFloorDiagnosticsPayload {}
|
|
|
|
export interface SgsMapDiagnosticsPayload {
|
|
mapId: string | number
|
|
mapName?: string | null
|
|
sdkVersion?: string | null
|
|
status: SgsDiagnosticsStatusPayload
|
|
floors: SgsFloorDiagnosticsSummaryPayload[]
|
|
summary?: {
|
|
floorCount?: number
|
|
modelReadyFloorCount?: number
|
|
poiCount?: number
|
|
spaceCount?: number
|
|
guideStopCount?: number
|
|
navigablePlaceCount?: number
|
|
routeNodeCount?: number
|
|
routeEdgeCount?: number
|
|
}
|
|
warnings?: string[]
|
|
}
|
|
|
|
export interface SgsFloorBundlePayload {
|
|
floor?: SgsSdkFloorSummaryPayload | null
|
|
model?: SgsModelInfoPayload | null
|
|
pois?: SgsPoiPayload[]
|
|
spaces?: SgsSpacePayload[]
|
|
guideStops?: SgsGuideStopPayload[]
|
|
routeSummary?: {
|
|
hasRouteNetwork?: boolean
|
|
nodeCount?: number
|
|
edgeCount?: number
|
|
} | null
|
|
hiddenSceneNodeNames?: string[]
|
|
dataVersion?: string | null
|
|
updatedAt?: string | null
|
|
}
|
|
|
|
export interface SgsModelInfoPayload {
|
|
modelUrl?: string | null
|
|
fallbackModelUrl?: string | null
|
|
compressionType?: string | null
|
|
modelVersion?: string | null
|
|
nodeCount?: number | null
|
|
sizeBytes?: number | null
|
|
originSizeBytes?: number | null
|
|
}
|
|
|
|
export interface SgsRoutePlanRequestPayload {
|
|
startFloorId: number | string
|
|
startX: number
|
|
startY: number
|
|
startNodeId?: number | string | null
|
|
endFloorId: number | string
|
|
endX: number
|
|
endY: number
|
|
endNodeId?: number | string | null
|
|
wheelchair: 0 | 1
|
|
}
|
|
|
|
export interface SgsRouteStepNodePayload {
|
|
id?: string | number | null
|
|
nodeName?: string | null
|
|
floorId?: string | number | null
|
|
nodeType?: string | null
|
|
x?: number | null
|
|
y?: number | null
|
|
z?: number | null
|
|
}
|
|
|
|
export interface SgsRoutePathPointPayload {
|
|
x?: number | null
|
|
y?: number | null
|
|
z?: number | null
|
|
}
|
|
|
|
export interface SgsRouteSegmentPayload {
|
|
floorId?: string | number | null
|
|
floorCode?: string | null
|
|
floorName?: string | null
|
|
startNodeId?: string | number | null
|
|
endNodeId?: string | number | null
|
|
startNodeName?: string | null
|
|
endNodeName?: string | null
|
|
segmentType?: string | null
|
|
type?: string | null
|
|
transferType?: string | null
|
|
distance?: number | null
|
|
duration?: number | null
|
|
pathGeoJson?: string | null
|
|
pathPoints?: SgsRoutePathPointPayload[]
|
|
nodePathIds?: Array<string | number | null>
|
|
}
|
|
|
|
export interface SgsRoutePlanResponsePayload {
|
|
distance?: number | null
|
|
duration?: number | null
|
|
pathGeoJson?: string | null
|
|
nodePaths?: SgsRouteStepNodePayload[]
|
|
segments?: SgsRouteSegmentPayload[]
|
|
}
|
|
|
|
export interface SgsRouteEndpointPayload {
|
|
id?: string | number | null
|
|
name?: string | null
|
|
floorId?: string | number | null
|
|
floorCode?: string | null
|
|
floorName?: string | null
|
|
x?: number | null
|
|
y?: number | null
|
|
z?: number | null
|
|
}
|
|
|
|
export interface SgsFeaturedRouteSummaryPayload {
|
|
id: string | number
|
|
mapId?: string | number | null
|
|
routeName?: string | null
|
|
routeNameEn?: string | null
|
|
routeType?: string | null
|
|
theme?: string | null
|
|
description?: string | null
|
|
coverImageUrl?: string | null
|
|
estimatedDuration?: number | null
|
|
distanceMeters?: number | null
|
|
waypointCount?: number | null
|
|
sortOrder?: number | null
|
|
status?: string | number | null
|
|
}
|
|
|
|
export interface SgsFeaturedRouteWaypointPayload {
|
|
order?: number | null
|
|
spaceId?: string | number | null
|
|
spaceName?: string | null
|
|
guideStopId?: string | number | null
|
|
guideStopName?: string | null
|
|
floorId?: string | number | null
|
|
floorCode?: string | null
|
|
floorName?: string | null
|
|
x?: number | null
|
|
y?: number | null
|
|
z?: number | null
|
|
stayMinutes?: number | null
|
|
}
|
|
|
|
export interface SgsFeaturedRouteDetailPayload extends SgsFeaturedRouteSummaryPayload {
|
|
startEntrance?: SgsRouteEndpointPayload | null
|
|
endEntrance?: SgsRouteEndpointPayload | null
|
|
waypoints?: SgsFeaturedRouteWaypointPayload[]
|
|
}
|
|
|
|
interface CommonResult<T> {
|
|
code: number
|
|
msg?: string
|
|
data?: T
|
|
}
|
|
|
|
export interface SgsSdkApiProvider {
|
|
getManifest(mapId?: string): Promise<SgsSdkManifestPayload>
|
|
getMapDiagnostics(mapId?: string): Promise<SgsMapDiagnosticsPayload>
|
|
getFloorDiagnostics(floorId: string): Promise<SgsFloorDiagnosticsPayload>
|
|
getFloorBundle(floorId: string): Promise<SgsFloorBundlePayload>
|
|
getFloorPois(floorId: string): Promise<SgsPoiPayload[]>
|
|
getFloorSpaces(floorId: string): Promise<SgsSpacePayload[]>
|
|
getGuideStops(floorId: string): Promise<SgsGuideStopPayload[]>
|
|
getGuideStopsByHall(hallId: string): Promise<SgsGuideStopPayload[]>
|
|
getNavigablePlaces(floorId: string): Promise<SgsNavigablePlacePayload[]>
|
|
getFloorBusinessPois(
|
|
floorId: string,
|
|
options?: { types?: string[]; keyword?: string; limit?: number }
|
|
): Promise<SgsPoiPayload[]>
|
|
queryPois(params: SgsPoiQueryParamsPayload): Promise<SgsPoiPayload[]>
|
|
getFeaturedRoutes(
|
|
mapId?: string,
|
|
options?: { limit?: number }
|
|
): Promise<SgsFeaturedRouteSummaryPayload[]>
|
|
getFeaturedRoute(routeId: string): Promise<SgsFeaturedRouteDetailPayload>
|
|
planRoute(payload: SgsRoutePlanRequestPayload): Promise<SgsRoutePlanResponsePayload>
|
|
}
|
|
|
|
const normalizeBaseUrl = (baseUrl: string) => baseUrl.replace(/\/+$/, '')
|
|
|
|
const resolveAppApiBaseUrl = () => {
|
|
const baseUrl = normalizeBaseUrl(dataSourceConfig.sgsApiBaseUrl || dataSourceConfig.apiBaseUrl || '/app-api')
|
|
return baseUrl.endsWith('/app-api') ? baseUrl : `${baseUrl}/app-api`
|
|
}
|
|
|
|
const getHeaderValue = (
|
|
header: Record<string, string> | undefined,
|
|
key: string
|
|
) => {
|
|
if (!header) return ''
|
|
const matchedKey = Object.keys(header).find((item) => item.toLowerCase() === key.toLowerCase())
|
|
return matchedKey ? String(header[matchedKey] || '') : ''
|
|
}
|
|
|
|
const previewPayload = (payload: unknown) => {
|
|
const text = typeof payload === 'string' ? payload : JSON.stringify(payload) || ''
|
|
return text.replace(/\s+/g, ' ').trim().slice(0, 120)
|
|
}
|
|
|
|
const parseJsonPayload = <T>(payload: unknown, requestUrl: string, contentType: string): T => {
|
|
if (typeof payload === 'string') {
|
|
const trimmedPayload = payload.trim()
|
|
const looksLikeHtml = /^<!doctype\s+html/i.test(trimmedPayload) || /^<html[\s>]/i.test(trimmedPayload)
|
|
if (looksLikeHtml || contentType.toLowerCase().includes('text/html')) {
|
|
throw new Error(`SGS 数据接口返回非 JSON: ${requestUrl} content-type=${contentType || 'unknown'} body="${previewPayload(payload)}"`)
|
|
}
|
|
|
|
try {
|
|
return JSON.parse(trimmedPayload) as T
|
|
} catch {
|
|
throw new Error(`SGS 数据接口 JSON 解析失败: ${requestUrl} content-type=${contentType || 'unknown'} body="${previewPayload(payload)}"`)
|
|
}
|
|
}
|
|
|
|
return payload as T
|
|
}
|
|
|
|
const requestJson = <T>(
|
|
path: string,
|
|
options: { method?: 'GET' | 'POST'; data?: unknown } = {}
|
|
): Promise<T> => new Promise((resolve, reject) => {
|
|
const baseUrl = resolveAppApiBaseUrl()
|
|
const requestUrl = `${baseUrl}${path}`
|
|
|
|
uni.request({
|
|
url: requestUrl,
|
|
method: options.method || 'GET',
|
|
data: options.method === 'POST' ? JSON.stringify(options.data || {}) : undefined,
|
|
header: options.method === 'POST'
|
|
? {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
: undefined,
|
|
timeout: dataSourceConfig.sgsSdkTimeoutMs,
|
|
success: (response) => {
|
|
const statusCode = Number(response.statusCode || 0)
|
|
const contentType = getHeaderValue(response.header as Record<string, string> | undefined, 'content-type')
|
|
if (statusCode < 200 || statusCode >= 300) {
|
|
reject(new Error(`SGS 数据接口请求失败: ${statusCode} ${requestUrl} content-type=${contentType || 'unknown'} body="${previewPayload(response.data)}"`))
|
|
return
|
|
}
|
|
|
|
try {
|
|
const body = parseJsonPayload<CommonResult<T>>(response.data, requestUrl, contentType)
|
|
if (!body || body.code !== 0) {
|
|
reject(new Error(`SGS 数据接口业务失败: ${requestUrl} code=${body?.code} msg=${body?.msg || ''}`))
|
|
return
|
|
}
|
|
|
|
resolve(body.data as T)
|
|
} catch (error) {
|
|
reject(error)
|
|
}
|
|
},
|
|
fail: (error) => {
|
|
reject(new Error(`SGS 数据接口网络失败: ${path} ${JSON.stringify(error)}`))
|
|
}
|
|
})
|
|
})
|
|
|
|
const buildQueryString = (params: object) => {
|
|
const query = new URLSearchParams()
|
|
|
|
Object.entries(params as Record<string, unknown>).forEach(([key, value]) => {
|
|
if (value === null || typeof value === 'undefined' || value === '') return
|
|
|
|
query.set(key, Array.isArray(value) ? value.join(',') : String(value))
|
|
})
|
|
|
|
const queryString = query.toString()
|
|
return queryString ? `?${queryString}` : ''
|
|
}
|
|
|
|
const stableCacheKey = (value: unknown) => JSON.stringify(value)
|
|
|
|
export const createSgsSdkApiProvider = (): SgsSdkApiProvider => {
|
|
const manifestCache = new Map<string, SgsSdkManifestPayload>()
|
|
const mapDiagnosticsCache = new Map<string, SgsMapDiagnosticsPayload>()
|
|
const floorDiagnosticsCache = new Map<string, SgsFloorDiagnosticsPayload>()
|
|
const floorBundleCache = new Map<string, SgsFloorBundlePayload>()
|
|
const floorPoiCache = new Map<string, SgsPoiPayload[]>()
|
|
const floorSpaceCache = new Map<string, SgsSpacePayload[]>()
|
|
const floorGuideStopCache = new Map<string, SgsGuideStopPayload[]>()
|
|
const hallGuideStopCache = new Map<string, SgsGuideStopPayload[]>()
|
|
const navigablePlaceCache = new Map<string, SgsNavigablePlacePayload[]>()
|
|
const floorBusinessPoiCache = new Map<string, SgsPoiPayload[]>()
|
|
const poiQueryCache = new Map<string, SgsPoiPayload[]>()
|
|
const featuredRoutesCache = new Map<string, SgsFeaturedRouteSummaryPayload[]>()
|
|
const featuredRouteDetailCache = new Map<string, SgsFeaturedRouteDetailPayload>()
|
|
|
|
const mapIdFor = (mapId?: string) => mapId || dataSourceConfig.sgsMapId
|
|
const floorIdFor = (floorId: string) => encodeURIComponent(floorId)
|
|
const hallIdFor = (hallId: string) => encodeURIComponent(hallId)
|
|
|
|
return {
|
|
async getManifest(mapId) {
|
|
const normalizedMapId = mapIdFor(mapId)
|
|
const cached = manifestCache.get(normalizedMapId)
|
|
if (cached) return cached
|
|
|
|
const manifest = await requestJson<SgsSdkManifestPayload>(
|
|
`/gis/sdk/maps/${encodeURIComponent(normalizedMapId)}/manifest`
|
|
)
|
|
manifestCache.set(normalizedMapId, manifest)
|
|
return manifest
|
|
},
|
|
async getMapDiagnostics(mapId) {
|
|
const normalizedMapId = mapIdFor(mapId)
|
|
const cached = mapDiagnosticsCache.get(normalizedMapId)
|
|
if (cached) return cached
|
|
|
|
const diagnostics = await requestJson<SgsMapDiagnosticsPayload>(
|
|
`/gis/sdk/maps/${encodeURIComponent(normalizedMapId)}/diagnostics`
|
|
)
|
|
mapDiagnosticsCache.set(normalizedMapId, diagnostics)
|
|
return diagnostics
|
|
},
|
|
async getFloorDiagnostics(floorId) {
|
|
const cached = floorDiagnosticsCache.get(floorId)
|
|
if (cached) return cached
|
|
|
|
const diagnostics = await requestJson<SgsFloorDiagnosticsPayload>(
|
|
`/gis/sdk/floors/${floorIdFor(floorId)}/diagnostics`
|
|
)
|
|
floorDiagnosticsCache.set(floorId, diagnostics)
|
|
return diagnostics
|
|
},
|
|
async getFloorBundle(floorId) {
|
|
const cached = floorBundleCache.get(floorId)
|
|
if (cached) return cached
|
|
|
|
const bundle = await requestJson<SgsFloorBundlePayload>(
|
|
`/gis/sdk/floors/${floorIdFor(floorId)}/bundle`
|
|
)
|
|
floorBundleCache.set(floorId, bundle)
|
|
return bundle
|
|
},
|
|
async getFloorPois(floorId) {
|
|
const cached = floorPoiCache.get(floorId)
|
|
if (cached) return cached
|
|
|
|
const pois = await requestJson<SgsPoiPayload[]>(
|
|
`/gis/sdk/floors/${floorIdFor(floorId)}/pois`
|
|
)
|
|
floorPoiCache.set(floorId, pois)
|
|
return pois
|
|
},
|
|
async getFloorSpaces(floorId) {
|
|
const cached = floorSpaceCache.get(floorId)
|
|
if (cached) return cached
|
|
|
|
const spaces = await requestJson<SgsSpacePayload[]>(
|
|
`/gis/sdk/floors/${floorIdFor(floorId)}/spaces`
|
|
)
|
|
floorSpaceCache.set(floorId, spaces)
|
|
return spaces
|
|
},
|
|
async getGuideStops(floorId) {
|
|
const cached = floorGuideStopCache.get(floorId)
|
|
if (cached) return cached
|
|
|
|
const guideStops = await requestJson<SgsGuideStopPayload[]>(
|
|
`/gis/sdk/floors/${floorIdFor(floorId)}/guide-stops`
|
|
)
|
|
floorGuideStopCache.set(floorId, guideStops)
|
|
return guideStops
|
|
},
|
|
async getGuideStopsByHall(hallId) {
|
|
const cached = hallGuideStopCache.get(hallId)
|
|
if (cached) return cached
|
|
|
|
const guideStops = await requestJson<SgsGuideStopPayload[]>(
|
|
`/gis/sdk/halls/${hallIdFor(hallId)}/guide-stops`
|
|
)
|
|
hallGuideStopCache.set(hallId, guideStops)
|
|
return guideStops
|
|
},
|
|
async getNavigablePlaces(floorId) {
|
|
const cached = navigablePlaceCache.get(floorId)
|
|
if (cached) return cached
|
|
|
|
const places = await requestJson<SgsNavigablePlacePayload[]>(
|
|
`/gis/sdk/floors/${floorIdFor(floorId)}/navigable-places`
|
|
)
|
|
navigablePlaceCache.set(floorId, places)
|
|
return places
|
|
},
|
|
async getFloorBusinessPois(floorId, options = {}) {
|
|
const cacheKey = `${floorId}:${stableCacheKey(options)}`
|
|
const cached = floorBusinessPoiCache.get(cacheKey)
|
|
if (cached) return cached
|
|
|
|
const pois = await requestJson<SgsPoiPayload[]>(
|
|
`/gis/sdk/floors/${floorIdFor(floorId)}/business-pois${buildQueryString(options)}`
|
|
)
|
|
floorBusinessPoiCache.set(cacheKey, pois)
|
|
return pois
|
|
},
|
|
async queryPois(params) {
|
|
const cacheKey = stableCacheKey(params)
|
|
const cached = poiQueryCache.get(cacheKey)
|
|
if (cached) return cached
|
|
|
|
const pois = await requestJson<SgsPoiPayload[]>(
|
|
`/gis/sdk/pois${buildQueryString(params)}`
|
|
)
|
|
poiQueryCache.set(cacheKey, pois)
|
|
return pois
|
|
},
|
|
async getFeaturedRoutes(mapId, options = {}) {
|
|
const normalizedMapId = mapIdFor(mapId)
|
|
const cacheKey = `${normalizedMapId}:${stableCacheKey(options)}`
|
|
const cached = featuredRoutesCache.get(cacheKey)
|
|
if (cached) return cached
|
|
|
|
const routes = await requestJson<SgsFeaturedRouteSummaryPayload[]>(
|
|
`/gis/sdk/maps/${encodeURIComponent(normalizedMapId)}/featured-routes${buildQueryString(options)}`
|
|
)
|
|
featuredRoutesCache.set(cacheKey, routes)
|
|
return routes
|
|
},
|
|
async getFeaturedRoute(routeId) {
|
|
const cached = featuredRouteDetailCache.get(routeId)
|
|
if (cached) return cached
|
|
|
|
const route = await requestJson<SgsFeaturedRouteDetailPayload>(
|
|
`/gis/sdk/featured-routes/${encodeURIComponent(routeId)}`
|
|
)
|
|
featuredRouteDetailCache.set(routeId, route)
|
|
return route
|
|
},
|
|
async planRoute(payload) {
|
|
return requestJson<SgsRoutePlanResponsePayload>(
|
|
'/gis/sdk/routes/plan',
|
|
{
|
|
method: 'POST',
|
|
data: payload
|
|
}
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
export const defaultSgsSdkApiProvider = createSgsSdkApiProvider()
|