diff --git a/types/onfleet__node-onfleet/Resources/Administrators.d.ts b/types/onfleet__node-onfleet/Resources/Administrators.d.ts new file mode 100644 index 0000000000..0bcc6a8d27 --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Administrators.d.ts @@ -0,0 +1,44 @@ +import { OnfleetMetadata } from '../metadata'; + +declare class Admin { + create(obj: Admin.CreateAdminProps): Promise; + deleteOne(id: string): Promise; + get(): Promise; + update(id: string, obj: Admin.UpdateAdminProps): Promise; +} + +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 administrator’s complete name. + * @prop name - The administrator’s 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; diff --git a/types/onfleet__node-onfleet/Resources/Containers.d.ts b/types/onfleet__node-onfleet/Resources/Containers.d.ts new file mode 100644 index 0000000000..70d875abd3 --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Containers.d.ts @@ -0,0 +1,18 @@ +declare class Container { + get(id: string, group: 'organizations' | 'teams' | 'workers'): Promise; +} + +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; diff --git a/types/onfleet__node-onfleet/Resources/Destinations.d.ts b/types/onfleet__node-onfleet/Resources/Destinations.d.ts new file mode 100644 index 0000000000..ee131884c6 --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Destinations.d.ts @@ -0,0 +1,64 @@ +import { OnfleetMetadata } from '../metadata'; + +declare class Destination { + create(destination: Destination.CreateDestinationProps): Promise; + get(id: string): Promise; +} + +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; diff --git a/types/onfleet__node-onfleet/Resources/Hubs.d.ts b/types/onfleet__node-onfleet/Resources/Hubs.d.ts new file mode 100644 index 0000000000..ff32e6acaa --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Hubs.d.ts @@ -0,0 +1,17 @@ +import { Location, OnfleetDestination } from './Destinations'; + +declare class Hub { + get(): Promise; +} + +declare namespace Hub { + interface OnfleetHub { + address: OnfleetDestination['address']; + id: string; + location: Location; + name: string; + teams: string[]; + } +} + +export = Hub; diff --git a/types/onfleet__node-onfleet/Resources/Organization.d.ts b/types/onfleet__node-onfleet/Resources/Organization.d.ts new file mode 100644 index 0000000000..ff72843475 --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Organization.d.ts @@ -0,0 +1,29 @@ +declare class Organization { + get(): Promise; + get(id: string): Promise; + insertTask(id: string, obj: { tasks: string[] }): Promise; +} + +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; diff --git a/types/onfleet__node-onfleet/Resources/Recipients.d.ts b/types/onfleet__node-onfleet/Resources/Recipients.d.ts new file mode 100644 index 0000000000..9d4c781a41 --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Recipients.d.ts @@ -0,0 +1,33 @@ +import { OnfleetMetadata } from '../metadata'; + +declare class Recipient { + create(recipient: Recipient.CreateRecipientProps): Promise; + get(queryOrId: string, queryKey?: Recipient.RecipientQueryKey): Promise; + update(id: string, recipient: Partial): Promise; +} + +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; diff --git a/types/onfleet__node-onfleet/Resources/Tasks.d.ts b/types/onfleet__node-onfleet/Resources/Tasks.d.ts new file mode 100644 index 0000000000..61f90c0c20 --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Tasks.d.ts @@ -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; // TODO need to confirm response + batchCreate(tasks: Task.CreateTaskProps[]): Promise; + clone(id: string): Promise; + create(task: Task.CreateTaskProps): Promise; + deleteOne(id: string): Promise; + forceComplete(id: string): Promise; + get(queryOrId: string, queryKey?: Task.TaskQueryKey): Promise; + get(queryParams?: Task.TaskQueryParam): Promise; + update(id: string, task: Partial): Promise; +} + +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; diff --git a/types/onfleet__node-onfleet/Resources/Teams.d.ts b/types/onfleet__node-onfleet/Resources/Teams.d.ts new file mode 100644 index 0000000000..09d0fb271d --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Teams.d.ts @@ -0,0 +1,42 @@ +declare class Team { + create(obj: any): Promise; + deleteOne(id: string): Promise; + get(): Promise; + get(id: string): Promise; + insertTask(id: string, obj: { tasks: string[] }): Promise; + update(id: string, obj: Team.UpdateTeamProps): Promise; +} + +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; diff --git a/types/onfleet__node-onfleet/Resources/Webhooks.d.ts b/types/onfleet__node-onfleet/Resources/Webhooks.d.ts new file mode 100644 index 0000000000..72ce0b7ada --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Webhooks.d.ts @@ -0,0 +1,59 @@ +declare class Webhook { + create(webhook: Webhook.OnfleetWebhook): Promise; + deleteOne(id: string): Promise; + get(): Promise; +} + +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; diff --git a/types/onfleet__node-onfleet/Resources/Workers.d.ts b/types/onfleet__node-onfleet/Resources/Workers.d.ts new file mode 100644 index 0000000000..80cd7c9e37 --- /dev/null +++ b/types/onfleet__node-onfleet/Resources/Workers.d.ts @@ -0,0 +1,104 @@ +import { Location } from './Destinations'; +import { OnfleetMetadata } from '../metadata'; + +declare class Worker { + create(worker: Worker.CreateWorkerProps): Promise; + deleteOne(id: string): Promise; + get(): Promise; + get(id: string, query?: Worker.GetWorkerQueryProps): Promise; + getByLocation(location: Worker.GetWorkerByLocationProps): Promise<{ workers: Worker.OnfleetWorker[] }>; + getSchedule(id: string): Promise<{ entries: Worker.WorkerSchedule[] }>; + insertTask(id: string, obj: { tasks: string[] }): Promise; + setSchedule(id: string, schedule: Worker.WorkerSchedule): Promise<{ entries: Worker.WorkerSchedule[] }>; + update(id: string, worker: Worker.UpdateWorkerProps): Promise; +} + +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 worker’s complete name. + * @prop phone - A valid phone number as per the worker’s organization’s country. + * @prop teams - One or more team IDs of which the worker is a member. + * @prop vehicle - Optional. The worker’s 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; diff --git a/types/onfleet__node-onfleet/index.d.ts b/types/onfleet__node-onfleet/index.d.ts new file mode 100644 index 0000000000..9d524004e0 --- /dev/null +++ b/types/onfleet__node-onfleet/index.d.ts @@ -0,0 +1,9 @@ +// Type definitions for @onfleet/node-onfleet 1.0 +// Project: https://github.com/onfleet/node-onfleet +// Definitions by: Marco Beltempo +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 3.5 + +import Onfleet = require('./onfleet'); + +export = Onfleet; diff --git a/types/onfleet__node-onfleet/metadata.d.ts b/types/onfleet__node-onfleet/metadata.d.ts new file mode 100644 index 0000000000..f382c51c30 --- /dev/null +++ b/types/onfleet__node-onfleet/metadata.d.ts @@ -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; +} diff --git a/types/onfleet__node-onfleet/onfleet.d.ts b/types/onfleet__node-onfleet/onfleet.d.ts new file mode 100644 index 0000000000..821814e8de --- /dev/null +++ b/types/onfleet__node-onfleet/onfleet.d.ts @@ -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; diff --git a/types/onfleet__node-onfleet/onfleet__node-onfleet-tests.ts b/types/onfleet__node-onfleet/onfleet__node-onfleet-tests.ts new file mode 100644 index 0000000000..903729cd85 --- /dev/null +++ b/types/onfleet__node-onfleet/onfleet__node-onfleet-tests.ts @@ -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: [ + '', + '', + ], + 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' }); +} diff --git a/types/onfleet__node-onfleet/tsconfig.json b/types/onfleet__node-onfleet/tsconfig.json new file mode 100644 index 0000000000..76fd8a254d --- /dev/null +++ b/types/onfleet__node-onfleet/tsconfig.json @@ -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" + ] +} \ No newline at end of file diff --git a/types/onfleet__node-onfleet/tslint.json b/types/onfleet__node-onfleet/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/onfleet__node-onfleet/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }