Add typings for @onfleet/node-onfleet package (#39130)

* Generated template files

* Added type definition for Worker resource

* Added type definition for Webhook resource

* Added type definition for Destination resource

* Added type definition for Recipient resource

* Added type definition for Task resource

* Added type definition for API helper

* Added type definition for HttpError helper

* Added type definition for metadata helper

* Added type definition for main Onfleet class

* Added index export for resources and helpers

* Added type definition for Admin resource

* Added type definition for Hub resource

* Added type definition for Organization resource

* Added type definition for Teams resource

* Added definition for Container resource

* Fixed insertTask definition

* Lint fixes:
-sorted class members ASC
-consistent interface naming

* Set Typescript version to 3.5

* Lint fixes:
- export all module declarations
- combined overload methods with optional params

* Renamed `Admin` module to `Administrator`

* Added tests

* Convert ES2015 modules to CommonJS modules

* Renamed resource files
to match package naming convention

* Removed unnecessary API type

* Removed resource index file

* Lint fixes: prefer single quotes

* Use require for module imports

* Set Typescript version to 3.5

* Fixed  test module import

* Renamed import paths `Resources` to `resources`

* Deleted unused error module
This commit is contained in:
Marco Beltempo 2019-10-16 19:01:32 -04:00 committed by Andrew Branch
parent d067c52e79
commit 13db742b5b
16 changed files with 720 additions and 0 deletions

View File

@ -0,0 +1,44 @@
import { OnfleetMetadata } from '../metadata';
declare class Admin {
create(obj: Admin.CreateAdminProps): Promise<Admin.OnfleetAdmin>;
deleteOne(id: string): Promise<void>;
get(): Promise<Admin.OnfleetAdmin[]>;
update(id: string, obj: Admin.UpdateAdminProps): Promise<Admin.OnfleetAdmin>;
}
declare namespace Admin {
interface OnfleetAdmin {
email: string;
id: string;
isActive: boolean;
metadata: OnfleetMetadata;
name: string;
organization: string;
phone: string;
timeCreated: number;
timeLastModified: number;
type: 'super' | 'standard';
}
/**
* @prop email - The administrators complete name.
* @prop name - The administrators email address.
* @prop phone - Optional. The administrator's phone number.
* @prop isReadOnly - Optional. Whether this administrator can perform write operations.
*/
interface CreateAdminProps {
email: string;
name: string;
phone?: string;
isReadOnly?: boolean;
}
interface UpdateAdminProps {
email?: string;
metadata?: OnfleetMetadata;
name?: string;
}
}
export = Admin;

View File

@ -0,0 +1,18 @@
declare class Container {
get(id: string, group: 'organizations' | 'teams' | 'workers'): Promise<Container.OnfleetContainer>;
}
declare namespace Container {
interface OnfleetContainer {
id: string;
timeCreated: number;
timeLastModified: number;
organization: string;
type: 'ORGANIZATION' | 'TEAM' | 'WORKER';
activeTask: string | null;
tasks: string[];
worker: string;
}
}
export = Container;

View File

@ -0,0 +1,64 @@
import { OnfleetMetadata } from '../metadata';
declare class Destination {
create(destination: Destination.CreateDestinationProps): Promise<Destination.OnfleetDestination>;
get(id: string): Promise<Destination.OnfleetDestination>;
}
declare namespace Destination {
type Latitude = number;
type Longitude = number;
type Location = [Longitude, Latitude];
/**
* @prop { string } [apartment] - The suite or apartment number, or any additional relevant information.
* @prop { string } city - The name of the municipality.
* @prop { string } country - The name of the country.
* @prop { string } [name] - A name associated with this address, for example, "Transamerica Pyramid".
* @prop { string } number - The number component of this address, it may also contain letters.
* @prop { string } [postalCode] - The postal or zip code.
* @prop { string } [state] - The name of the state, province or jurisdiction.
* @prop { string } street - The name of the street.
* @prop { string } [unparsed] - A complete address specified in a single, unparsed string where the various elements are separated by commas.
* * If present, all other address properties will be ignored (with the exception of name and apartment).
* * In some countries, you may skip most address details (like city or state) if you provide a valid postalCode:
* for example, 325 Front Street W., M5V 3B5, CA will be geocoded correctly.
*/
interface DestinationAddress {
apartment?: string;
city: string;
country: string;
name?: string;
number: string;
postalCode?: string;
state?: string;
street: string;
unparsed?: string;
}
interface OnfleetDestination {
id: string;
timeCreated: number;
timeLastModified: number;
location: Location;
address: {
apartment: string;
state: string;
postalCode: string;
country: string;
city: string;
street: string;
number: string;
};
notes: string;
metadata: OnfleetMetadata[];
}
interface CreateDestinationProps {
address: DestinationAddress;
location?: Location;
notes?: string;
}
}
export = Destination;

View File

@ -0,0 +1,17 @@
import { Location, OnfleetDestination } from './Destinations';
declare class Hub {
get(): Promise<Hub.OnfleetHub[]>;
}
declare namespace Hub {
interface OnfleetHub {
address: OnfleetDestination['address'];
id: string;
location: Location;
name: string;
teams: string[];
}
}
export = Hub;

View File

@ -0,0 +1,29 @@
declare class Organization {
get(): Promise<Organization.OnfleetOrganization[]>;
get(id: string): Promise<Organization.OnfleetOrganization | Organization.Delegatee>;
insertTask(id: string, obj: { tasks: string[] }): Promise<any>;
}
declare namespace Organization {
interface OnfleetOrganization {
id: string;
timeCreated: number;
timeLastModified: number;
name: string;
email: string;
image: string;
timezone: string;
country: string;
delegatees: string[];
}
interface Delegatee {
country: string;
email: string;
id: string;
name: string;
timezone: string;
}
}
export = Organization;

View File

@ -0,0 +1,33 @@
import { OnfleetMetadata } from '../metadata';
declare class Recipient {
create(recipient: Recipient.CreateRecipientProps): Promise<Recipient.OnfleetRecipient>;
get(queryOrId: string, queryKey?: Recipient.RecipientQueryKey): Promise<Recipient.OnfleetRecipient>;
update(id: string, recipient: Partial<Recipient.CreateRecipientProps>): Promise<Recipient.OnfleetRecipient>;
}
declare namespace Recipient {
type RecipientQueryKey = 'phone' | 'name';
interface OnfleetRecipient {
id: string;
metadata: OnfleetMetadata[];
name: string;
notes: string;
organization: string;
phone: string;
skipSMSNotifications: boolean;
timeCreated: number;
timeLastModified: number;
}
interface CreateRecipientProps {
name: string;
phone: string;
metadata?: OnfleetMetadata[];
notes?: string;
skipSMSNotifications?: boolean;
skipPhoneNumberValidation?: boolean;
}
}
export = Recipient;

View File

@ -0,0 +1,140 @@
import { OnfleetDestination, CreateDestinationProps } from './Destinations';
import { OnfleetMetadata } from '../metadata';
import { OnfleetRecipient, CreateRecipientProps } from './Recipients';
declare class Task {
autoAssign(tasks: Task.OnfleetTask[]): Promise<any>; // TODO need to confirm response
batchCreate(tasks: Task.CreateTaskProps[]): Promise<Task.OnfleetTask[]>;
clone(id: string): Promise<Task.OnfleetTask>;
create(task: Task.CreateTaskProps): Promise<Task.OnfleetTask>;
deleteOne(id: string): Promise<number>;
forceComplete(id: string): Promise<void>;
get(queryOrId: string, queryKey?: Task.TaskQueryKey): Promise<Task.OnfleetTask>;
get(queryParams?: Task.TaskQueryParam): Promise<Task.OnfleetTask[]>;
update(id: string, task: Partial<Task.CreateTaskProps>): Promise<Task.UpdateTaskResult>;
}
declare namespace Task {
type TaskQueryKey = 'shortId';
interface OnfleetTask {
completeAfter: number;
completeBefore: number;
completionDetails: {
failureNotes: string;
failureReason: string;
events: any[];
actions: any[];
time: number | null;
firstLocation: any[];
lastLocation: any[];
unavailableAttachments: any[];
};
container: {
organization: string;
type: string;
};
creator: string;
dependencies: string[];
destination: OnfleetDestination;
didAutoAssign: boolean;
executor: string;
feedback: any[];
id: string;
identity: {
failedScanCount: number;
checksum: null;
};
merchant: string;
metadata: OnfleetMetadata[];
notes: string;
organization: string;
overrides: {
recipientName: string | null;
recipientNotes: string | null;
recipientSkipSMSNotifications: string | null;
useMerchantForProxy: string | null;
};
pickupTask: boolean;
quantity: number;
recipients: OnfleetRecipient[];
serviceTime: number;
shortId: string;
state: number;
timeCreated: number;
timeLastModified: number;
trackingURL: string;
trackingViewed: boolean;
worker: string | null;
}
interface CreateTaskProps {
destination: string | CreateDestinationProps;
recipients: string[] | CreateRecipientProps[];
autoAssign?: TaskAutoAssign;
capacity?: number;
completeAfter?: number;
completeBefore?: number;
dependencies?: string[];
executor?: string;
metadata?: OnfleetMetadata[];
merchant?: string;
notes?: string;
pickupTask?: boolean;
quantity?: number;
recipientName?: string;
recipientNotes?: string;
recipientSkipSMSNotifications?: boolean;
requirements?: TaskCompletionRequirements;
}
interface TaskAutoAssign {
mode: string;
considerDependencies?: boolean;
excludeWorkerIds?: string[];
maxAssignedTaskCount?: number;
team?: string;
}
interface TaskCompletionRequirements {
minimumAge?: number;
notes?: boolean;
photo?: boolean;
signature?: boolean;
}
interface TaskQueryParam {
from: number;
completeAfterAfter?: number;
completeBeforeBefore?: number;
dependencies?: string;
lastId?: string;
state?: number;
to?: number;
worker?: string;
}
interface CloneTaskOptions {
includeBarCodes: boolean;
includeDependencies: boolean;
includeMetadata: boolean;
overrides?: {
completeAfter?: number;
completeBefore?: number;
destination?: string | CreateDestinationProps;
metadata?: OnfleetMetadata[];
notes?: string;
pickupTask?: boolean;
recipients?: OnfleetRecipient | OnfleetRecipient[];
serviceTime?: number;
};
}
interface UpdateTaskResult extends OnfleetTask {
estimatedArrivalTime: number | null;
estimatedCompletionTime: number | null;
eta: number;
trackingViewed: boolean;
}
}
export = Task;

View File

@ -0,0 +1,42 @@
declare class Team {
create(obj: any): Promise<Team.OnfleetTeam>;
deleteOne(id: string): Promise<void>;
get(): Promise<Team.OnfleetTeam[]>;
get(id: string): Promise<Team.OnfleetTeam>;
insertTask(id: string, obj: { tasks: string[] }): Promise<Team.OnfleetTeam>;
update(id: string, obj: Team.UpdateTeamProps): Promise<Team.OnfleetTeam>;
}
declare namespace Team {
interface OnfleetTeam {
hub: string;
id: string;
managers: string[];
name: string;
timeCreated: number;
timeLastModified: number;
workers: string[];
}
/**
* @prop managers - An array of managing administrator IDs.
* @prop name - A unique name for the team.
* @prop workers - An array of worker IDs.
* @prop hub - Optional. The ID of the team's hub.
*/
interface CreateTeamProps {
managers: string[];
name: string;
workers: string[];
hub?: string;
}
interface UpdateTeamProps {
managers?: string[];
name?: string;
workers?: string[];
hub?: string;
}
}
export = Team;

View File

@ -0,0 +1,59 @@
declare class Webhook {
create(webhook: Webhook.OnfleetWebhook): Promise<Webhook.WebhookResult>;
deleteOne(id: string): Promise<void>;
get(): Promise<Webhook.GetWebhookResult[]>;
}
declare namespace Webhook {
interface OnfleetWebhook {
trigger: WebhookTriggerType['triggerId'];
url: string;
threshold?: number;
}
interface WebhookResult {
count: number;
id: string;
trigger: WebhookTriggerType['triggerId'];
url: string;
}
interface GetWebhookResult extends WebhookResult {
isEnabled: boolean;
}
enum WebhookTriggerName {
SmsRecipientResponseMissed = 'smsRecipientResponseMissed',
TaskArrival = 'taskArrival',
TaskAssigned = 'taskAssigned',
TaskCloned = 'taskCloned',
TaskCompleted = 'taskCompleted',
TaskCreated = 'taskCreated',
TaskDelayed = 'taskDelayed',
TaskDeleted = 'taskDeleted',
TaskEta = 'taskEta',
TaskFailed = 'taskFailed',
TaskStarted = 'taskStarted',
TaskUnassigned = 'taskUnassigned',
TaskUpdated = 'taskUpdated',
WorkerDuty = 'workerDuty',
}
type WebhookTriggerType =
| { triggerId: 0; triggerName: WebhookTriggerName.TaskStarted }
| { triggerId: 1; triggerName: WebhookTriggerName.TaskEta }
| { triggerId: 2; triggerName: WebhookTriggerName.TaskArrival }
| { triggerId: 3; triggerName: WebhookTriggerName.TaskCompleted }
| { triggerId: 4; triggerName: WebhookTriggerName.TaskFailed }
| { triggerId: 5; triggerName: WebhookTriggerName.WorkerDuty }
| { triggerId: 6; triggerName: WebhookTriggerName.TaskCreated }
| { triggerId: 7; triggerName: WebhookTriggerName.TaskUpdated }
| { triggerId: 8; triggerName: WebhookTriggerName.TaskDeleted }
| { triggerId: 9; triggerName: WebhookTriggerName.TaskAssigned }
| { triggerId: 10; triggerName: WebhookTriggerName.TaskUnassigned }
| { triggerId: 12; triggerName: WebhookTriggerName.TaskDelayed }
| { triggerId: 13; triggerName: WebhookTriggerName.TaskCloned }
| { triggerId: 14; triggerName: WebhookTriggerName.SmsRecipientResponseMissed };
}
export = Webhook;

View File

@ -0,0 +1,104 @@
import { Location } from './Destinations';
import { OnfleetMetadata } from '../metadata';
declare class Worker {
create(worker: Worker.CreateWorkerProps): Promise<Worker.OnfleetWorker>;
deleteOne(id: string): Promise<void>;
get(): Promise<Worker.OnfleetWorker[]>;
get(id: string, query?: Worker.GetWorkerQueryProps): Promise<Worker.OnfleetWorker>;
getByLocation(location: Worker.GetWorkerByLocationProps): Promise<{ workers: Worker.OnfleetWorker[] }>;
getSchedule(id: string): Promise<{ entries: Worker.WorkerSchedule[] }>;
insertTask(id: string, obj: { tasks: string[] }): Promise<Worker.OnfleetWorker>;
setSchedule(id: string, schedule: Worker.WorkerSchedule): Promise<{ entries: Worker.WorkerSchedule[] }>;
update(id: string, worker: Worker.UpdateWorkerProps): Promise<Worker.OnfleetWorker>;
}
declare namespace Worker {
interface OnfleetWorker {
id: string;
timeCreated: number;
timeLastModified: number;
organization: string;
name: string;
displayName: string;
phone: string;
activeTask: string | null;
tasks: string[];
onDuty: boolean;
timeLastSeen: number;
capacity: number;
userData: {
appVersion: string;
batteryLevel: number;
deviceDescription: string;
platform: string;
};
accountStatus: string;
metadata: OnfleetMetadata[];
imageUrl: string | null;
teams: string[];
delayTime: number | null;
location: Location;
vehicle: Vehicle | null;
}
interface Vehicle {
type: 'BICYCLE' | 'CAR' | 'MOTORCYCLE' | 'TRUCK';
color?: string;
description?: string;
licensePlate?: string;
}
/**
* @prop filter - Optional. A comma-separated list of fields to return, if all are not desired. For example, name, location
* @prop phones - Optional. A comma-separated list of workers' phone numbers.
* @prop states - Optional. A comma-separated list of worker states, where 0 is off-duty,
* 1 is idle (on-duty, no active task) and 2 is active (on-duty, active task).
* @prop teams - Optional. A comma-separated list of the team IDs that workers must be part of.
*/
interface GetWorkerQueryProps {
filter?: string;
phones?: string;
states?: string;
teams?: string;
}
interface GetWorkerByLocationProps extends Location {
radius?: number;
}
/**
* @prop name - The workers complete name.
* @prop phone - A valid phone number as per the workers organizations country.
* @prop teams - One or more team IDs of which the worker is a member.
* @prop vehicle - Optional. The workers vehicle; providing no vehicle details is equivalent to the worker being on foot.
* @prop capacity - Optional. The maximum number of units this worker can carry, for route optimization purposes.
* @prop displayName - Optional. This value is used in place of the worker's actual name within sms notifications,
* delivery tracking pages, and across organization boundaries (connections).
*/
interface CreateWorkerProps {
name: string;
phone: string;
teams: string;
vehicle?: Vehicle;
capacity?: number;
displayName?: string;
}
interface UpdateWorkerProps {
capacity?: number;
displayName?: string;
metadata?: OnfleetMetadata;
name?: string;
teams?: string;
vehicle?: Vehicle;
}
interface WorkerSchedule {
date: string;
timezone: string;
shifts: [[number, number]];
}
}
export = Worker;

View File

@ -0,0 +1,9 @@
// Type definitions for @onfleet/node-onfleet 1.0
// Project: https://github.com/onfleet/node-onfleet
// Definitions by: Marco Beltempo <https://github.com/marcobeltempo>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 3.5
import Onfleet = require('./onfleet');
export = Onfleet;

View File

@ -0,0 +1,11 @@
export type MetadataVisibility = 'api' | 'dashboard' | 'worker';
export type MetadataType = 'boolean' | 'number' | 'string' | 'object' | 'array';
export type MetadataSubType = 'boolean' | 'number' | 'string' | 'object';
export interface OnfleetMetadata {
name: string;
type: MetadataType;
subtype?: MetadataSubType;
visibility?: MetadataVisibility[];
value: any;
}

View File

@ -0,0 +1,39 @@
import Administrators = require('./Resources/Administrators');
import Containers = require('./Resources/Containers');
import Destinations = require('./Resources/Destinations');
import Hubs = require('./Resources/Hubs');
import Organization = require('./Resources/Organization');
import Recipients = require('./Resources/Recipients');
import Tasks = require('./Resources/Tasks');
import Teams = require('./Resources/Teams');
import Webhooks = require('./Resources/Webhooks');
import Workers = require('./Resources/Workers');
declare class Onfleet {
apiKey: string;
api: {
baseUrl: string;
timeout: number;
headers: {
'Content-Type': string;
'User-Agent': string;
Authorization: string;
}
};
constructor(api_key: string);
verifyKey(): boolean;
admins: Administrators;
containers: Containers;
destinations: Destinations;
hubs: Hubs;
organization: Organization;
recipients: Recipients;
tasks: Tasks;
teams: Teams;
webhooks: Webhooks;
workers: Workers;
}
export = Onfleet;

View File

@ -0,0 +1,82 @@
import Onfleet = require('@onfleet/node-onfleet');
const onfleet = new Onfleet('test-api-key');
const isValid = onfleet.verifyKey();
async function testTasks(onfleet: Onfleet) {
// test tasks.get
await onfleet.tasks.get('fake_task_id');
await onfleet.tasks.get({ from: 1455072025000 });
await onfleet.tasks.get({ from: 145507202500, lastId: 'fake_task_id' });
await onfleet.tasks.get('fake_task_id', 'shortId');
// test tasks.create
const dummyTask = await onfleet.tasks.create({
recipients: ['fake_recipient_id'],
destination: 'fake_destination_id',
});
await onfleet.tasks.create({
recipients: [
'<recipient-id-1>',
'<recipient-id-2>',
],
destination: {
address: {
city: 'Toronto',
country: 'Canada',
name: 'Test Destination',
number: '100',
street: 'Test Street Blvd.',
},
},
});
// test tasks.update
await onfleet.tasks.update(dummyTask.id, {
notes: 'Some test task notes',
});
// test tasks.clone
const clonedDummyTask = await onfleet.tasks.clone(dummyTask.id);
// test tasks.delete
await onfleet.tasks.deleteOne(clonedDummyTask.id);
// test tasks.forceComplete
await onfleet.tasks.forceComplete(dummyTask.id);
}
async function testDestination() {
// test destination.create
const testDestination = await onfleet.destinations.create({
address: {
city: 'Toronto',
country: 'Canada',
name: 'Test Destination',
number: '100',
street: 'Test Street Blvd.',
},
});
// test destination.get
await onfleet.destinations.get(testDestination.id);
}
async function testRecipient() {
const testRecipient = await onfleet.recipients.create({
name: 'Test User',
phone: '+1-416-555-5555',
notes: 'Test notes',
skipSMSNotifications: true,
skipPhoneNumberValidation: false,
});
// test recipient.get
await onfleet.recipients.get(testRecipient.id);
await onfleet.recipients.get('Test User', 'name');
await onfleet.recipients.get('+1-416-555-5555', 'phone');
// test recipient.update
await onfleet.recipients.update(testRecipient.id, { notes: 'Updated notes' });
}

View File

@ -0,0 +1,28 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"@onfleet/node-onfleet": [
"onfleet__node-onfleet"
]
}
},
"files": [
"index.d.ts",
"onfleet__node-onfleet-tests.ts"
]
}

View File

@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }