Web extensions API services
The web extension has access to services that are injected into the page to facilitate communication with Skedulo’s API.
These services have their appropriate type definitions (for Typescript) defined in the src/Services/Services.ts
boilerplate file.
You can use this file to get direct references to everything injected in the web extension.
This page describes the variables and services that are injected in to your web extensions and how to use them.
Variables
Skedulo updates the injected services in your environment using environment variables.
As we update the injected services we will also periodically update the boilerplate files.
The following is a list of all variables that are injected into web extensions, and an example of the result.
Name | Type | Description | Example |
---|---|---|---|
context | string or string[] |
The reference UID of the context under which the page is loaded | referenceUID: "000195c2-1cad-409e-aa22-74181732b2c7" |
params | [paramName: string]: any |
Any parameters that have been passed to the web component | foo: "bar" |
profile | Profile |
Contains information about the user running the web extension | roles: ["administrator"] tenantId: "sk_b30d8a5952d94b47a000d254f2c9256d" userId:"000195c2-1cad-409e-aa22-74181732b2c7" username: "mwheeler@skedulo.com" |
credentials | Credentials |
Credentials of the current user and details of API server | apiAccessToken: "token" apiServer: "https://api.skedulo.com" vendor: { type: "skedulo", url: 'https://api.skedulo.com', token: null } |
navigation | Navigation |
desc | ex |
These variables can be used in your Web Extension by importing them and then referencing them (see below example)
import * as React from 'react'
import { Services, profile } from './Services/Services' //import profile variable
interface AppState {
profile: any
}
export class App extends React.PureComponent<{}, AppState> {
constructor(props: {}) {
super(props)
this.state = {
profile: profile //add it to the state
}
}
render() {
return (
<div className="App">
Current User Id: { this.state.profile.userId } //show profile.userId
</div>
)
}
}
Services
The below services are exposed to make it easier to call Skedulo’s APIs.
There are some example implementations of these services (for Typescript) defined in the src/Services/DataServices.ts
boilerplate file.
You can use these to retrieve and manipulate data and metadata within the Skedulo platform.
Name | Description | |
---|---|---|
Services.graphQL | This service allows you to send queries to Skedulo’s GraphQL API. This is the primary method of retrieving, consuming and updating data from a web extension. Refer to src/Services/DataServices.ts for usage examples. This also exposes a method for retrieving GraphQL introspection data for any given model if required. | |
Services.metadata | This service allows you to fetch data from our metadata API. | |
Services.errorClasses | This is a map that lists all possible errors that can be thrown while interacting with the available services. For example, a GraphQLExecutionError can occur if there is an error in the defined query. You can use these classes (if needed) to pattern-match (instanceof checks) in Promise catch blocks for easy and contextual error handling. |
These services can be used in your Web Extension by importing them and then referencing them (see below example)
import { Services } from './Services' //import the service
export class DataServices {
constructor(private services: Services) { }
fetchJobs() {
return this.services.graphQL //perform a fetch using it
.fetch<{ jobs: Job[] }>({
query: JobsQuery
})
.then(({ jobs }) => jobs)
}
}
//example job interface
export interface Job {
UID: string
Name: string
Description: string
}
//example job fetch query
const JobsQuery = `
{
jobs {
edges {
node {
UID
Name
Description
}
}
}
}
`
Example Services.ts
file:
interface GraphQLRequest {
query: string
variables?: Record<string, any>
operationName?: string
context?: Record<string, any>
extensions?: Record<string, any>
}
export interface GraphQLMutationResult {
data: null | { schema: { [operationName: string]: string } }
errors: null | {
message: string
path?: string[]
locations?: { line: number, column: number }[]
}[]
}
// tslint:disable:no-misused-new
interface GraphQLError {
getErrors: () => string[]
new(): GraphQLError
}
type Model = string
interface IntrospectionField {
name: string
type: {
name: null | 'Instant' | 'Boolean' | 'BigDecimal' | 'String' | Model
kind: 'SCALAR' | 'NON_NULL' | 'OBJECT' | 'LIST'
ofType: null | IntrospectionField['type']
}
}
interface IntrospectionModelType {
__type: {
name: string
fields: IntrospectionField[]
}
}
export interface Vocabulary {
[schema: string]: {
[field: string]: {
value: string,
label: string
}[]
}
}
export interface Services {
graphQL: {
fetch<T>(operation: GraphQLRequest, endpoint?: string): Promise<T>
mutate(operation: GraphQLRequest, endpoint?: string): Promise<GraphQLMutationResult>
fetchMetadataFor(model: string): Promise<IntrospectionModelType>
},
metadata: {
fetchVocabulary(): Promise<Vocabulary>
},
errorClasses: {
GraphQLNetworkError: GraphQLError,
GraphQLExecutionError: GraphQLError
},
}
export interface Profile {
tenantId: string
userId: string
username: string
roles: string[]
}
export interface Credentials {
apiServer: string
apiAccessToken: string
vendor: { type: 'skedulo', url: string, token: null } | { type: 'salesforce', url: string, token: string }
}
export interface Navigation {
registerRouteHandler: (routeHandler: (routeState: {
routes: string | string[],
params: { [paramName: string]: any }
}) => void) => void
setParentRoute: (route: string) => void
}
declare const skedInjected: {
Services: Services,
context?: string | string[],
params: { [paramName: string]: any }
profile: Profile,
credentials: Credentials
navigation: Navigation
}
export const Services = skedInjected.Services
export const context = skedInjected.context
export const params = skedInjected.params
export const profile = skedInjected.profile
export const credentials = skedInjected.credentials
export const navigation = skedInjected.navigation
Nested types
RealtimeJobChangeSet = Pick<Job, 'UID' | 'JobStatus' | 'Urgency' | 'Locked' | 'Start' | 'Duration' | 'End' | 'Address' | 'GeoLatitude' | 'GeoLongitude'>
RealtimeJobAllocationChangeSet = Pick<IJobAllocation, 'UID' | 'Status' | 'JobId' | 'ResourceId'>
ExtendedRealtimeJobAllocation = RealtimeJobAllocation & { JobId: string, ResourceId: string }
interface IRealtimeChannel {
getJobStream: () => Observable<RealtimeJobChangeSet[]>,
getJobAllocationStream: () => Observable<RealtimeJobAllocationChangeSet[]>,
getUpdatedJobStream: () => Observable<RealtimeJobChangeSet[]>,
getCreatedJobStream: () => Observable<RealtimeJobChangeSet[]>,
getUpdatedJobAllocationStream: () => Observable<RealtimeJobAllocationChangeSet[]>,
getCreatedJobAllocationStream: () => Observable<RealtimeJobAllocationChangeSet[]>
}
This approach allows you to provide credentials and context that is used to instantiate services for the page and allows you to access the Skedulo GraphQL schema.
Feedback
Was this page helpful?