diff --git a/lib/utils/patterns.ts b/lib/utils/patterns.ts index 3b61d557..2d01b684 100644 --- a/lib/utils/patterns.ts +++ b/lib/utils/patterns.ts @@ -18,13 +18,11 @@ import _ = require('lodash'); import Promise = require('bluebird'); import form = require('resin-cli-form'); import visuals = require('resin-cli-visuals'); -import ResinSdk = require('resin-sdk'); +import resin = require('resin-sdk-preconfigured'); import chalk from 'chalk'; import validation = require('./validation'); import messages = require('./messages'); -const resin = ResinSdk.fromSharedOptions(); - export function authenticate(options: {}): Promise { return form .run( @@ -132,10 +130,8 @@ export function confirm( }); } -export function selectApplication( - filter: (app: ResinSdk.Application) => boolean, -) { - resin.models.application +export function selectApplication(filter: (app: resin.Application) => boolean) { + return resin.models.application .hasAny() .then(function(hasAnyApplications) { if (!hasAnyApplications) { @@ -165,7 +161,7 @@ export function selectOrCreateApplication() { return resin.models.application.getAll().then(applications => { const appOptions = _.map< - ResinSdk.Application, + resin.Application, { name: string; value: string | null } >(applications, application => ({ name: `${application.app_name} (${application.device_type})`, @@ -227,7 +223,7 @@ export function awaitDevice(uuid: string) { export function inferOrSelectDevice(preferredUuid: string) { return resin.models.device .getAll() - .filter(device => device.is_online) + .filter(device => device.is_online) .then(onlineDevices => { if (_.isEmpty(onlineDevices)) { throw new Error("You don't have any devices online"); diff --git a/package.json b/package.json index 6e38fd02..8d3c16b8 100644 --- a/package.json +++ b/package.json @@ -133,8 +133,8 @@ "resin-doodles": "0.0.1", "resin-image-fs": "^2.3.0", "resin-image-manager": "^5.0.0", - "resin-preload": "^5.0.0", - "resin-sdk": "^7.0.0", + "resin-preload": "^6.0.0-beta", + "resin-sdk": "^9.0.0-beta", "resin-sdk-preconfigured": "^6.9.0", "resin-settings-client": "^3.6.1", "resin-stream-logger": "^0.1.0", diff --git a/typings/resin-sdk-preconfigured.d.ts b/typings/resin-sdk-preconfigured.d.ts index 57afac5e..0f3f4dd3 100644 --- a/typings/resin-sdk-preconfigured.d.ts +++ b/typings/resin-sdk-preconfigured.d.ts @@ -1,5 +1,809 @@ declare module 'resin-sdk-preconfigured' { - import { ResinSDK } from 'resin-sdk'; - let sdk: ResinSDK; - export = sdk; + import * as Promise from 'bluebird'; + import { EventEmitter } from 'events'; + import * as ResinErrors from 'resin-errors'; + import { Readable } from 'stream'; + + /* tslint:disable:no-namespace */ + + namespace Pine { + // based on https://github.com/resin-io/pinejs-client-js/blob/master/core.d.ts + + type RawFilter = + | string + | Array> + | { + $string: string; + [index: string]: Filter | string; + }; + type Lambda = { + $alias: string; + $expr: Filter; + }; + + type OrderByValues = 'asc' | 'desc'; + type OrderBy = + | string + | string[] + | { + [index: string]: OrderByValues; + }; + + type ResourceObjFilter = { [k in keyof T]?: object | number | string }; + + interface FilterArray extends Array> {} + + type FilterExpressions = { + $raw?: RawFilter; + + $?: string | string[]; + + $and?: Filter | FilterArray; + $or?: Filter | FilterArray; + + $in?: Filter | FilterArray; + + $not?: Filter | FilterArray; + + $any?: Lambda; + $all?: Lambda; + }; + + type Filter = ResourceObjFilter & FilterExpressions; + + type BaseExpandFor = { [k in keyof T]?: object } | keyof T; + + export type Expand = BaseExpandFor | Array>; + } + + namespace ResinRequest { + interface ResinRequestOptions { + method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'; + url: string; + apiKey?: string; + body?: any; + } + + interface ResinRequestResponse extends Response { + body: any; + } + + interface ResinRequest { + send: (options: ResinRequestOptions) => Promise; + } + } + + namespace ResinSdk { + interface Interceptor { + request?(response: any): Promise; + response?(response: any): Promise; + requestError?(error: Error): Promise; + responseError?(error: Error): Promise; + } + + interface Config { + deployment: string | null; + deviceUrlsBase: string; + adminUrl: string; + apiUrl: string; + actionsUrl: string; + gitServerUrl: string; + pubnub: { + subscribe_key: string; + publish_key: string; + }; + ga?: GaConfig; + mixpanelToken?: string; + intercomAppId?: string; + recurlyPublicKey?: string; + deviceTypes: DeviceType[]; + DEVICE_ONLINE_ICON: string; + DEVICE_OFFLINE_ICON: string; + signupCodeRequired: boolean; + supportedSocialProviders: string[]; + } + + interface GaConfig { + site: string; + id: string; + } + + interface DeviceType { + slug: string; + name: string; + + arch: string; + state?: string; + + isDependent?: boolean; + instructions?: string[] | DeviceTypeInstructions; + gettingStartedLink?: string | DeviceTypeGettingStartedLink; + stateInstructions?: { [key: string]: string[] }; + options?: DeviceTypeOptions[]; + initialization?: { + options?: DeviceInitializationOptions[]; + operations: Array<{ + command: string; + }>; + }; + supportsBlink?: boolean; + yocto: { + fstype?: string; + deployArtifact: string; + }; + } + + interface DeviceTypeInstructions { + linux: string[]; + osx: string[]; + windows: string[]; + } + + interface DeviceTypeGettingStartedLink { + linux: string; + osx: string; + windows: string; + [key: string]: string; + } + + interface DeviceTypeOptions { + options: DeviceTypeOptionsGroup[]; + collapsed: boolean; + isCollapsible: boolean; + isGroup: boolean; + message: string; + name: string; + } + + interface DeviceInitializationOptions { + message: string; + type: string; + name: string; + } + + interface DeviceTypeOptionsGroup { + default: number | string; + message: string; + name: string; + type: string; + min?: number; + choices?: string[] | number[]; + choicesLabels?: { [key: string]: string }; + } + + interface WithId { + id: number; + } + + interface PineParams { + resource: string; + id?: number; + body?: object; + options?: PineOptions; + } + + interface PineOptions { + filter?: object; + expand?: object | string; + orderBy?: Pine.OrderBy; + top?: string; + skip?: string; + select?: string | string[]; + } + + interface PineParamsFor extends PineParams { + body?: Partial; + options?: PineOptionsFor; + } + + interface PineParamsWithIdFor extends PineParamsFor { + id: number; + } + + type PineFilterFor = Pine.Filter; + type PineExpandFor = Pine.Expand; + + interface PineOptionsFor extends PineOptions { + filter?: PineFilterFor; + expand?: PineExpandFor; + select?: Array | keyof T; + } + + interface PineDeferred { + __id: number; + } + + /** + * When not selected-out holds a deferred. + * When expanded hold an array with a single element. + */ + type NavigationResource = T[] | PineDeferred; + + /** + * When expanded holds an array, otherwise the property is not present. + * Selecting is not suggested, + * in that case it holds a deferred to the original resource. + */ + type ReverseNavigationResource = T[] | undefined; + + interface SocialServiceAccount { + provider: string; + display_name: string; + created_at: string; + id: number; + remote_id: string; + } + + interface User { + id: number; + username: string; + email?: string; + first_name?: string; + last_name?: string; + company?: string; + account_type?: string; + has_disabled_newsletter?: boolean; + jwt_secret: string; + created_at: string; + twoFactorRequired?: boolean; + hasPasswordSet?: boolean; + needsPasswordReset?: boolean; + public_key?: boolean; + features?: string[]; + intercomUserName?: string; + intercomUserHash?: string; + permissions?: string[]; + loginAs?: boolean; + actualUser?: number; + + // this is what the api route returns + social_service_account: ReverseNavigationResource; + } + + interface Application { + app_name: string; + device_type: string; + git_repository: string; + commit: string; + id: number; + device_type_info?: any; + has_dependent?: boolean; + should_track_latest_release: boolean; + + user: NavigationResource; + + application_tag: ReverseNavigationResource; + } + + type BuildStatus = + | 'cancelled' + | 'error' + | 'interrupted' + | 'local' + | 'running' + | 'success' + | 'timeout' + | null; + + interface Build { + log: string; + commit_hash: string; + created_at: string; + end_timestamp: string; + id: number; + message: string | null; + project_type: string; + push_timestamp: string | null; + start_timestamp: string; + status: BuildStatus; + update_timestamp: string | null; + } + + interface BillingAccountAddressInfo { + address1: string; + address2: string; + city: string; + state: string; + zip: string; + country: string; + phone: string; + } + + interface BillingAccountInfo { + account_state: string; + first_name: string; + last_name: string; + company_name: string; + cc_emails: string; + vat_number: string; + address: BillingAccountAddressInfo; + } + + type BillingInfoType = 'bank_account' | 'credit_card' | 'paypal'; + + interface BillingInfo { + full_name: string; + + first_name: string; + last_name: string; + company: string; + vat_number: string; + address1: string; + address2: string; + city: string; + state: string; + zip: string; + country: string; + phone: string; + + type?: BillingInfoType; + } + + interface CardBillingInfo extends BillingInfo { + card_type: string; + year: string; + month: string; + first_one: string; + last_four: string; + } + + interface BankAccountBillingInfo extends BillingInfo { + account_type: string; + last_four: string; + name_on_account: string; + routing_number: string; + } + + interface TokenBillingSubmitInfo { + token_id: string; + } + + interface BillingPlanInfo { + name: string; + billing?: BillingPlanBillingInfo; + } + + interface BillingPlanBillingInfo { + currency: string; + currencySymbol?: string; + } + + interface InvoiceInfo { + closed_at: string; + created_at: string; + currency: string; + invoice_number: string; + subtotal_in_cents: string; + total_in_cents: string; + uuid: string; + } + + interface Device { + created_at: string; + device_type: string; + id: number; + name: string; + os_version: string; + os_variant?: string; + status_sort_index?: number; + uuid: string; + ip_address: string | null; + vpn_address: string | null; + last_connectivity_event: string; + is_in_local_mode?: boolean; + app_name?: string; + state?: { key: string; name: string }; + status: string; + provisioning_state: string; + is_online: boolean; + is_connected_to_vpn: boolean; + supervisor_version: string; + is_web_accessible: boolean; + has_dependent: boolean; + note: string; + location: string; + latitude?: string; + longitude?: string; + custom_latitude?: string; + custom_longitude?: string; + download_progress?: number; + provisioning_progress?: number; + local_id?: string; + + device_environment_variable: ReverseNavigationResource< + DeviceEnvironmentVariable + >; + device_tag: ReverseNavigationResource; + } + + interface LogMessage { + message: string; + isSystem: boolean; + timestamp: number | null; + serviceId: number | null; + } + + interface LogsSubscription extends EventEmitter { + unsubscribe(): void; + } + + interface SSHKey { + title: string; + public_key: string; + id: number; + created_at: string; + } + + type ImgConfigOptions = { + network?: 'ethernet' | 'wifi'; + appUpdatePollInterval?: number; + wifiKey?: string; + wifiSsid?: string; + ip?: string; + gateway?: string; + netmask?: string; + version?: string; + }; + + type OsVersions = { + latest: string; + recommended: string; + default: string; + versions: string[]; + }; + + interface EnvironmentVariableBase { + id: number; + name: string; + value: string; + } + + interface EnvironmentVariable extends EnvironmentVariableBase { + application: NavigationResource; + } + + interface DeviceEnvironmentVariable extends EnvironmentVariableBase { + env_var_name?: string; + + device: NavigationResource; + } + + interface ResourceTagBase { + id: number; + tag_key: string; + value: string; + } + + interface ApplicationTag extends ResourceTagBase { + application: NavigationResource; + } + + interface DeviceTag extends ResourceTagBase { + device: NavigationResource; + } + + type LogsPromise = Promise; + + interface ResinSDK { + auth: { + register: ( + credentials: { email: string; password: string }, + ) => Promise; + authenticate: ( + credentials: { email: string; password: string }, + ) => Promise; + login: ( + credentials: { email: string; password: string }, + ) => Promise; + loginWithToken: (authToken: string) => Promise; + logout: () => Promise; + getToken: () => Promise; + whoami: () => Promise; + isLoggedIn: () => Promise; + getUserId: () => Promise; + getEmail: () => Promise; + twoFactor: { + isEnabled: () => Promise; + isPassed: () => Promise; + challenge: (code: string) => Promise; + }; + }; + + settings: { + get(key: string): Promise; + getAll(): Promise<{ [key: string]: string }>; + }; + + request: ResinRequest.ResinRequest; + + errors: { + ResinAmbiguousApplication: ResinErrors.ResinAmbiguousApplication; + ResinAmbiguousDevice: ResinErrors.ResinAmbiguousDevice; + ResinApplicationNotFound: ResinErrors.ResinApplicationNotFound; + ResinBuildNotFound: ResinErrors.ResinBuildNotFound; + ResinDeviceNotFound: ResinErrors.ResinDeviceNotFound; + ResinExpiredToken: ResinErrors.ResinExpiredToken; + ResinInvalidDeviceType: ResinErrors.ResinInvalidDeviceType; + ResinInvalidParameterError: ResinErrors.ResinInvalidParameterError; + ResinKeyNotFound: ResinErrors.ResinKeyNotFound; + ResinMalformedToken: ResinErrors.ResinMalformedToken; + ResinNotLoggedIn: ResinErrors.ResinNotLoggedIn; + ResinRequestError: ResinErrors.ResinRequestError; + ResinSupervisorLockedError: ResinErrors.ResinSupervisorLockedError; + }; + + models: { + application: { + create( + name: string, + deviceType: string, + parentNameOrId?: number | string, + ): Promise; + get( + nameOrId: string | number, + options?: PineOptionsFor, + ): Promise; + getAppByOwner( + appName: string, + owner: string, + options?: PineOptionsFor, + ): Promise; + getAll(options?: PineOptionsFor): Promise; + has(name: string): Promise; + hasAny(): Promise; + remove(nameOrId: string | number): Promise; + restart(nameOrId: string | number): Promise; + enableDeviceUrls(nameOrId: string | number): Promise; + disableDeviceUrls(nameOrId: string | number): Promise; + grantSupportAccess( + nameOrId: string | number, + expiryTimestamp: number, + ): Promise; + revokeSupportAccess(nameOrId: string | number): Promise; + reboot(appId: number, { force }: { force?: boolean }): Promise; + shutdown( + appId: number, + { force }: { force?: boolean }, + ): Promise; + purge(appId: number): Promise; + generateApiKey(nameOrId: string | number): Promise; + generateProvisioningKey(nameOrId: string | number): Promise; + tags: { + getAllByApplication( + nameOrId: string | number, + options?: PineOptionsFor, + ): Promise; + getAll( + options?: PineOptionsFor, + ): Promise; + set( + nameOrId: string | number, + tagKey: string, + value: string, + ): Promise; + remove(nameOrId: string | number, tagKey: string): Promise; + }; + }; + build: { + get(id: number, options?: PineOptionsFor): Promise; + getAllByApplication( + nameOrId: string | number, + options?: PineOptionsFor, + ): Promise; + }; + billing: { + getAccount(): Promise; + getPlan(): Promise; + getBillingInfo(): Promise; + updateBillingInfo( + billingInfo: TokenBillingSubmitInfo, + ): Promise; + getInvoices(): Promise; + downloadInvoice(invoiceNumber: string): Promise; + }; + device: { + get( + uuidOrId: string | number, + options?: PineOptionsFor, + ): Promise; + getByName( + nameOrId: string | number, + options?: PineOptionsFor, + ): Promise; + getAll(options?: PineOptionsFor): Promise; + getAllByApplication( + nameOrId: string | number, + options?: PineOptionsFor, + ): Promise; + getAllByParentDevice( + parentUuidOrId: string | number, + options?: PineOptionsFor, + ): Promise; + getName(uuidOrId: string | number): Promise; + getApplicationName(uuidOrId: string | number): Promise; + getApplicationInfo( + uuidOrId: string | number, + ): Promise<{ + appId: string; + commit: string; + containerId: string; + env: { [key: string]: string | number }; + imageId: string; + }>; + has(uuidOrId: string | number): Promise; + isOnline(uuidOrId: string | number): Promise; + getLocalIPAddressess(uuidOrId: string | number): Promise; + getDashboardUrl(uuid: string): string; + getSupportedDeviceTypes(): Promise; + getManifestBySlug(slugOrName: string): Promise; + getManifestByApplication( + nameOrId: string | number, + ): Promise; + move( + uuidOrId: string | number, + applicationNameOrId: string | number, + ): Promise; + note(uuidOrId: string | number, note: string): Promise; + remove(uuidOrId: string | number): Promise; + rename(uuidOrId: string | number, newName: string): Promise; + setCustomLocation( + uuidOrId: string | number, + location: { latitude: number; longitude: number }, + ): Promise; + unsetCustomLocation(uuidOrId: string | number): Promise; + identify(uuidOrId: string | number): Promise; + startApplication(uuidOrId: string | number): Promise; + stopApplication(uuidOrId: string | number): Promise; + restartApplication(uuidOrId: string | number): Promise; + grantSupportAccess( + uuidOrId: string | number, + expiryTimestamp: number, + ): Promise; + revokeSupportAccess(uuidOrId: string | number): Promise; + reboot( + uuidOrId: string | number, + { force }?: { force?: boolean }, + ): Promise; + shutdown( + uuidOrId: string | number, + { force }?: { force?: boolean }, + ): Promise; + purge(uuidOrId: string | number): Promise; + update( + uuidOrId: string | number, + { force }?: { force?: boolean }, + ): Promise; + getDisplayName(deviceTypeName: string): string; + getDeviceSlug(deviceTypeName: string): string; + generateUniqueKey(): string; + register( + applicationNameOrId: string | number, + uuid?: string, + ): Promise; + generateDeviceKey(uuidOrId: string | number): Promise; + enableDeviceUrl(uuidOrId: string | number): Promise; + disableDeviceUrl(uuidOrId: string | number): Promise; + hasDeviceUrl(uuidOrId: string | number): Promise; + getDeviceUrl(uuidOrId: string | number): Promise; + enableTcpPing(uuidOrId: string | number): Promise; + disableTcpPing(uuidOrId: string | number): Promise; + ping(uuidOrId: string | number): Promise; + getStatus(device: object): string; + lastOnline(device: Device): string; + tags: { + getAllByApplication( + nameOrId: string | number, + options?: PineOptionsFor, + ): Promise; + getAllByDevice( + uuidOrId: string | number, + options?: PineOptionsFor, + ): Promise; + getAll(options?: PineOptionsFor): Promise; + set( + uuidOrId: string | number, + tagKey: string, + value: string, + ): Promise; + remove(uuidOrId: string | number, tagKey: string): Promise; + }; + }; + environmentVariables: { + device: { + getAll(id: number): Promise; + getAllByApplication( + applicationNameOrId: number | string, + ): Promise; + update(id: number, value: string): Promise; + create( + uuidOrId: number | string, + name: string, + value: string, + ): Promise; + remove(id: number): Promise; + }; + getAllByApplication( + applicationNameOrId: number | string, + ): Promise; + update(id: number, value: string): Promise; + create( + applicationNameOrId: number | string, + name: string, + value: string, + ): Promise; + remove(id: number): Promise; + isSystemVariable(variable: { name: string }): boolean; + }; + config: { + getAll: () => Promise; + getDeviceTypes: () => Promise; + getDeviceOptions( + deviceType: string, + ): Promise>; + }; + key: { + getAll(options?: PineOptionsFor): Promise; + get(id: string | number): Promise; + remove(id: string | number): Promise; + create(title: string, key: string): Promise; + }; + os: { + getConfig( + nameOrId: string | number, + options?: ImgConfigOptions, + ): Promise; + getDownloadSize(slug: string, version?: string): Promise; + getSupportedVersions(slug: string): Promise; + getMaxSatisfyingVersion( + deviceType: string, + versionOrRange: string, + ): string; + getLastModified(deviceType: string, version?: string): Promise; + download(deviceType: string, version?: string): Promise; + }; + }; + + logs: { + history(uuid: string): LogsPromise; + historySinceLastClear(uuid: string): LogsPromise; + subscribe(uuid: string): Promise; + clear(uuid: string): void; + }; + + pine: { + delete( + params: PineParamsWithIdFor | PineParamsFor, + ): Promise; + get(params: PineParamsWithIdFor): Promise; + get(params: PineParamsFor): Promise; + get(params: PineParamsFor): Promise; + post(params: PineParams): Promise; + patch(params: PineParamsWithIdFor): Promise; + }; + interceptors: Interceptor[]; + } + } + + interface SdkOptions { + apiUrl?: string; + /** + * @deprecated Use resin.auth.loginWithToken(apiKey) instead + */ + apiKey?: string; + imageMakerUrl?: string; + dataDirectory?: string; + isBrowser?: boolean; + debug?: boolean; + } + + interface SdkConstructor { + (options?: SdkOptions): ResinSdk.ResinSDK; + + setSharedOptions(options: SdkOptions): void; + fromSharedOptions: () => ResinSdk.ResinSDK; + } + + const ResinSdk: ResinSdk.ResinSDK; + + export = ResinSdk; }