diff --git a/packages/skygear-core/src/container.ts b/packages/skygear-core/src/container.ts index b1957820..0ac60ad2 100644 --- a/packages/skygear-core/src/container.ts +++ b/packages/skygear-core/src/container.ts @@ -49,14 +49,32 @@ export function generateOTPAuthURI(options: GenerateOTPAuthURIOptions): string { } /** + * Skygear Auth APIs. + * * @public */ export class AuthContainer { parent: Container; mfa: MFAContainer; + + /** + * Current logged in user. + */ currentUser: User | null; + + /** + * Identity of current logged in user. + */ currentIdentity: Identity | null; + + /** + * Session ID of current logged in user. + */ currentSessionID: string | null; + + /** + * Extra session information to be submitted to server. + */ extraSessionInfoOptions: ExtraSessionInfoOptions = { ...defaultExtraSessionInfoOptions, }; @@ -70,6 +88,13 @@ export class AuthContainer { this.mfa = new MFAContainer(this); } + /** + * Save extra session information. + * + * @remarks + * The SDK would populate extra session information from storage + * when calling {@link Container.configure | configure}. + */ async saveExtraSessionInfoOptions() { return this.parent.storage.setExtraSessionInfoOptions( this.parent.name, @@ -241,6 +266,32 @@ export class AuthContainer { } } + /** + * Sign up new user. + * + * @example + * ```ts + * // Signup with email and password + * await signup({"email": "test@example.com"}, "password"); + * + * // Signup with email, username, and password + * await signup( + * [{"email": "test@example.com"}, {"username": "test"}], + * "password" + * ); + * + * // Signup with email, password, and custom metadata + * await signup( + * {"email": "test@example.com"}, + * "password", + * {"metadata": {"accepted_tos": true}} + * ); + * ``` + * + * @param loginIDs - Login IDs + * @param password - Password + * @param options - Sign up options + */ async signup( loginIDs: { [key: string]: string }[] | { [key: string]: string }, password: string, @@ -254,7 +305,10 @@ export class AuthContainer { } /** - * signupWithEmail is a shorthand of {@link AuthContainer.signup | the signup() method}. + * Sign up new user with email. + * + * @remarks + * Equivalent to {@link AuthContainer.signup}: `signup({"email": email}, password, options)`. */ async signupWithEmail( email: string, @@ -273,7 +327,10 @@ export class AuthContainer { } /** - * signupWithUsername is a shorthand of {@link AuthContainer.signup | the signup() method}. + * Sign up new user with username. + * + * @remarks + * Equivalent to {@link AuthContainer.signup}: `signup({"username": username}, password, options)`. */ async signupWithUsername( username: string, @@ -291,6 +348,20 @@ export class AuthContainer { ); } + /** + * Login user with password. + * + * @example + * ```ts + * // Login with email + * await login("test\@example.com", "password"); + * // Login with username + * await login("test", "password"); + * ``` + * @param loginID - Login ID + * @param password - Password + * @param options - Login options + */ async login( loginID: string, password: string, @@ -301,6 +372,15 @@ export class AuthContainer { ); } + /** + * Logout current session. + * + * @remarks + * If `force` parameter is set to `true`, all potential errors (e.g. network + * error) would be ignored. + * + * @param options - Logout options + */ async logout(options: { force?: boolean } = {}): Promise { const { force = false } = options; try { @@ -382,10 +462,19 @@ export class AuthContainer { return true; } + /** + * Refreshes and returns current user information. + */ async me(): Promise { return this.handleAuthResponse(this.parent.apiClient.me()); } + /** + * Changes user password. + * + * @param newPassword - New password + * @param oldPassword - Old password + */ async changePassword( newPassword: string, oldPassword: string @@ -395,16 +484,34 @@ export class AuthContainer { ); } + /** + * Updates custom metadata of user. + * + * @remarks + * The provided new metadata object would replace the old metadata. + * + * @param metadata - New custom metadata object + */ async updateMetadata(metadata: JSONObject): Promise { return this.handleAuthResponse( this.parent.apiClient.updateMetadata(metadata) ); } + /** + * Requests password reset email. + * + * @param email - Registered email address of the user + */ async requestForgotPasswordEmail(email: string): Promise { return this.parent.apiClient.requestForgotPasswordEmail(email); } + /** + * Performs password reset. + * + * @param form - Information from password reset email + */ async resetPassword(form: { userID: string; code: string; @@ -414,18 +521,39 @@ export class AuthContainer { return this.parent.apiClient.resetPassword(form); } + /** + * Requests user email verification. + * + * @param email - Registered email address of the user + */ async requestEmailVerification(email: string): Promise { return this.parent.apiClient.requestEmailVerification(email); } - async requestPhoneVerification(email: string): Promise { - return this.parent.apiClient.requestPhoneVerification(email); + /** + * Requests user phone SMS verification. + * + * @param phone - Registered phone number of the user + */ + async requestPhoneVerification(phone: string): Promise { + return this.parent.apiClient.requestPhoneVerification(phone); } + /** + * Performs user verification. + * + * @param code - Verification code sent to user + */ async verifyWithCode(code: string): Promise { return this.parent.apiClient.verifyWithCode(code); } + /** + * Login user with custom token. + * + * @param token - Custom authentication token + * @param options - SSO login options + */ async loginWithCustomToken( token: string, options?: SSOLoginOptions @@ -435,10 +563,25 @@ export class AuthContainer { ); } + /** + * Deletes OAuth SSO provider. + * + * @param providerID - SSO provider ID + */ async deleteOAuthProvider(providerID: string): Promise { return this.parent.apiClient.deleteOAuthProvider(providerID); } + /** + * Login with OAuth SSO provider using access token. + * + * @remarks + * This feature must be enabled in configuration, otherwise it will fail. + * + * @param providerID - SSO provider ID + * @param accessToken - SSO provider access token + * @param options - SSO login options + */ async loginOAuthProviderWithAccessToken( providerID: string, accessToken: string, @@ -453,6 +596,15 @@ export class AuthContainer { ); } + /** + * Links with OAuth SSO provider using access token. + * + * @remarks + * This feature must be enabled in configuration, otherwise it will fail. + * + * @param providerID - SSO provider ID + * @param accessToken - SSO provider access token + */ async linkOAuthProviderWithAccessToken( providerID: string, accessToken: string @@ -465,24 +617,40 @@ export class AuthContainer { ); } + /** + * Lists all active user sessions. + */ async listSessions(): Promise { return this.parent.apiClient.listSessions(); } + /** + * Gets information on specified active user session. + */ async getSession(id: string): Promise { return this.parent.apiClient.getSession(id); } + /** + * Revokes the specified user session. + * + * @param id - Session ID + */ async revokeSession(id: string): Promise { return this.parent.apiClient.revokeSession(id); } + /** + * Revokes all other active user sessions. + */ async revokeOtherSessions(): Promise { return this.parent.apiClient.revokeOtherSessions(); } } /** + * Skygear Auth Multi-Factor-Authentication APIs. + * * @public */ export class MFAContainer { @@ -492,38 +660,77 @@ export class MFAContainer { this.parent = parent; } + /** + * Returns a list of MFA recovery code. + * + * @remarks + * This feature must be enabled in configuration, otherwise it will fail. + */ async listRecoveryCode(): Promise { return this.parent.parent.apiClient.listRecoveryCode(); } + /** + * Regenerates MFA recovery codes. + * + * @returns The newly generated recovery codes + */ async regenerateRecoveryCode(): Promise { return this.parent.parent.apiClient.regenerateRecoveryCode(); } + /** + * Perform MFA using recovery code. + * + * @param code - MFA recovery code + */ async authenticateWithRecoveryCode(code: string): Promise { return this.parent.handleAuthResponse( this.parent.parent.apiClient.authenticateWithRecoveryCode(code) ); } + /** + * Returns a list of configured MFA authenticators. + */ async getAuthenticators(): Promise { return this.parent.parent.apiClient.getAuthenticators(); } + /** + * Delete the MFA authenticator with specified ID. + * + * @param id - Authenticator ID + */ async deleteAuthenticator(id: string): Promise { return this.parent.parent.apiClient.deleteAuthenticator(id); } + /** + * Creates new time-based one time password (TOTP) MFA authenticator. + * + * @param options - TOTP configuration + */ async createNewTOTP( options: CreateNewTOTPOptions ): Promise { return this.parent.parent.apiClient.createNewTOTP(options); } + /** + * Activates time-based one time password (TOTP) MFA authenticator. + * + * @param otp - TOTP code + */ async activateTOTP(otp: string): Promise { return this.parent.parent.apiClient.activateTOTP(otp); } + /** + * Perform MFA using time-based one time password (TOTP) MFA authenticator. + * + * @param options - Authentication options + */ async authenticateWithTOTP( options: AuthenticateWithTOTPOptions ): Promise { @@ -532,20 +739,40 @@ export class MFAContainer { ); } + /** + * Creates new out-of-band (OOB) MFA authenticator. + * + * @param options - OOB configuration + */ async createNewOOB( options: CreateNewOOBOptions ): Promise { return this.parent.parent.apiClient.createNewOOB(options); } + /** + * Activates out-of-band (OOB) MFA authenticator. + * + * @param code - MFA code + */ async activateOOB(code: string): Promise { return this.parent.parent.apiClient.activateOOB(code); } + /** + * Triggers out-of-band (OOB) MFA. + * + * @param authenticatorID - Authenticator ID + */ async triggerOOB(authenticatorID?: string): Promise { return this.parent.parent.apiClient.triggerOOB(authenticatorID); } + /** + * Performs MFA using out-of-band (OOB) MFA authenticator. + * + * @param options - Authentication options + */ async authenticateWithOOB( options: AuthenticateWithOOBOptions ): Promise { @@ -554,15 +781,28 @@ export class MFAContainer { ); } + /** + * Revokes all MFA trusted devices. + */ async revokeAllTrustedDevices(): Promise { await this.parent.parent.apiClient.revokeAllBearerToken(); } } /** + * Skygear APIs container. + * + * @remarks + * This is the base class to Skygear APIs. + * Consumers should use platform-specific containers instead. + * * @public */ export class Container { + /** + * Unique ID for this container. + * @defaultValue "default" + */ name: string; apiClient: T; storage: ContainerStorage; @@ -583,6 +823,11 @@ export class Container { this.auth = new AuthContainer(this); } + /** + * Configure this container with connection information. + * + * @param options - Skygear connection information + */ async configure(options: { apiKey: string; endpoint: string; @@ -623,6 +868,14 @@ export class Container { ); } + /** + * `fetch` function for calling microservices. + * + * @remarks + * This function has same behavior as the standard `fetch` function, except + * it will also handle Skygear authorization mechanism automatically (e.g. + * attaching API key, access token, refreshing access token). + */ async fetch(input: string, init?: RequestInit): Promise { return this.apiClient.fetch(input, init); } diff --git a/packages/skygear-core/src/error.ts b/packages/skygear-core/src/error.ts index 928b28a7..21bade99 100644 --- a/packages/skygear-core/src/error.ts +++ b/packages/skygear-core/src/error.ts @@ -21,10 +21,39 @@ export const SkygearErrorNames = { export type SkygearErrorName = (typeof SkygearErrorNames)[keyof (typeof SkygearErrorNames)]; /** + * Skygear API error. + * + * @remarks + * All Skygear APIs (e.g. Auth, Asset) functions would throw errors of this + * type if server returns failure. + * * @public */ export class SkygearError extends Error { + /** + * Error name. + * + * @remarks + * See {@link SkygearErrorNames} for possible values. + * New error names may be added in future. + */ + name: string; + /** + * Error message. + * + * @remarks + * Error messages are provided for convenience, and not stable APIs; + * Consumers should use {@link SkygearError.name} or + * {@link SkygearError.reason} to distinguish between different errors. + */ + message!: string; + /** + * Error reason. + */ reason: string; + /** + * Additional error information. + */ info?: JSONObject; constructor( @@ -34,7 +63,6 @@ export class SkygearError extends Error { info?: JSONObject ) { super(message); - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/name this.name = name; this.reason = reason; this.info = info; @@ -92,6 +120,12 @@ export function _extractAuthenticationSession( } /** + * Check if the provided error indicates Multi-Factor-Authentication is + * required during authentication. + * + * @remarks + * The error may be thrown when attempting to login/signup if configured. + * * @public */ export function isMFARequiredError(e: unknown): boolean { diff --git a/packages/skygear-core/src/imageprocessing.ts b/packages/skygear-core/src/imageprocessing.ts index c94bfcb8..412515a2 100644 --- a/packages/skygear-core/src/imageprocessing.ts +++ b/packages/skygear-core/src/imageprocessing.ts @@ -29,6 +29,7 @@ interface ResizeOperation extends ImageProcessingPipelineBuilderResizeOptions { } /** + * Image processing pipeline builder. * @public */ export class ImageProcessingPipelineBuilder { @@ -38,6 +39,10 @@ export class ImageProcessingPipelineBuilder { this._ops = []; } + /** + * Specifies the output format of the image. + * @param format - Image format + */ format(format: "jpg" | "png" | "webp"): this { this._ops.push({ op: "format", @@ -46,6 +51,10 @@ export class ImageProcessingPipelineBuilder { return this; } + /** + * Specifies the quality of the output image. + * @param absoluteQuality - Quality (1 - 100) + */ quality(absoluteQuality: number): this { this._ops.push({ op: "quality", @@ -54,6 +63,11 @@ export class ImageProcessingPipelineBuilder { return this; } + /** + * Specifies image resizing operation. + * + * @param options - Resize options + */ resize(options: ImageProcessingPipelineBuilderResizeOptions): this { this._ops.push({ op: "resize", @@ -62,10 +76,16 @@ export class ImageProcessingPipelineBuilder { return this; } + /** + * Returns the query parameter name to be used. + */ getName(): string { return "pipeline"; } + /** + * Returns the built pipeline string to be used as query parameter value. + */ getValue(): string { const parts = ["image"]; for (const op of this._ops) { @@ -86,6 +106,18 @@ export class ImageProcessingPipelineBuilder { return parts.join("/"); } + /** + * Returns the provided URL with added pipeline parameter. + * + * @example + * ```ts + * new ImageProcessingPipelineBuilder() + * .format("jpg") + * .setToURLString("https://example.com"); + * // http://example.com?pipeline=image%2Fformat%2Cjpg + * ``` + * @param urlStr - input URL + */ setToURLString(urlStr: string): string { const fragmentIndex = urlStr.indexOf("#"); const queryIndex = urlStr.indexOf("?"); diff --git a/packages/skygear-core/src/types.ts b/packages/skygear-core/src/types.ts index 58efb05f..d8a15395 100644 --- a/packages/skygear-core/src/types.ts +++ b/packages/skygear-core/src/types.ts @@ -12,11 +12,29 @@ export type JSONObject = object; * @public */ export interface User { + /** + * User ID. + */ id: string; + /** + * User creation time. + */ createdAt: Date; + /** + * User last login time. + */ lastLoginAt: Date; + /** + * Indicates whether the user is verified. + */ isVerified: boolean; + /** + * Indicates whether the user is disabled. + */ isDisabled: boolean; + /** + * User custom metadata. + */ metadata: JSONObject; } @@ -29,11 +47,30 @@ export type Identity = PasswordIdentity | OAuthIdentity | CustomTokenIdentity; * @public */ export interface PasswordIdentity { + /** + * Identity ID. + */ id: string; + /** + * Identity type. + */ type: "password"; + /** + * Login ID key. + */ loginIDKey: string; + /** + * Login ID. + */ loginID: string; + /** + * Identity claims. + */ claims: { + /** + * The email of this identity. Present only if the login ID key is of email + * type. + */ email?: string; }; } @@ -42,12 +79,34 @@ export interface PasswordIdentity { * @public */ export interface OAuthIdentity { + /** + * Identity ID. + */ id: string; + /** + * Identity type. + */ type: "oauth"; + /** + * OAuth SSO provider type. + */ providerType: string; + /** + * OAuth SSO provider ID. + */ providerUserID: string; + /** + * Raw user profile from the provider. + */ rawProfile: JSONObject; + /** + * Identity claims. + */ claims: { + /** + * Email of this identity. Present only if email exists in the provider + * user profile. + */ email?: string; }; } @@ -56,11 +115,30 @@ export interface OAuthIdentity { * @public */ export interface CustomTokenIdentity { + /** + * Identity ID. + */ id: string; + /** + * Identity type. + */ type: "custom_token"; + /** + * User ID at the provider. + */ providerUserID: string; + /** + * Raw user profile from the provider. + */ rawProfile: JSONObject; + /** + * Identity claims. + */ claims: { + /** + * Email of this identity. Present only if a "email" field exists in the + * provider user profile. + */ email?: string; }; } @@ -69,14 +147,41 @@ export interface CustomTokenIdentity { * @public */ export interface Session { + /** + * Session ID. + */ id: string; + /** + * Identity ID. + */ identityID: string; + /** + * Session creation time. + */ createdAt: Date; + /** + * Session last active time. + */ lastAccessedAt: Date; + /** + * IP of session creator. + */ createdByIP: string; + /** + * IP of session last accessor. + */ lastAccessedByIP: string; + /** + * User agent of the session. + */ userAgent: SessionUserAgent; + /** + * Session name. + */ name: string; + /** + * Custom data of session. + */ data: JSONObject; } @@ -84,12 +189,33 @@ export interface Session { * @public */ export interface SessionUserAgent { + /** + * Raw user agent string. + */ raw: string; + /** + * User agent name. + */ name: string; + /** + * User agent version. + */ version: string; + /** + * User agent operating system. + */ os: string; + /** + * User agent operating system version. + */ osVersion: string; + /** + * User agent device name. + */ deviceName: string; + /** + * User agent device model. + */ deviceModel: string; } @@ -168,6 +294,12 @@ export interface StorageDriver { * @public */ export interface SSOLoginOptions { + /** + * Configures behavior when a duplicated user is detected. + * + * @remarks + * This feature must be enabled in configuration, otherwise it will fail. + */ onUserDuplicate?: "abort" | "merge" | "create"; } @@ -217,6 +349,9 @@ export interface ContainerOptions { * @public */ export interface ExtraSessionInfoOptions { + /** + * Device name. + */ deviceName?: string; } @@ -232,10 +367,25 @@ export type Authenticator = * @public */ export interface TOTPAuthenticator { + /** + * Authenticator ID. + */ id: string; + /** + * Authenticator type. + */ type: "totp"; + /** + * Authenticator creation time. + */ createdAt: Date; + /** + * Authenticator activation time. + */ activatedAt: Date; + /** + * Authenticator display name. + */ displayName: string; } @@ -243,11 +393,30 @@ export interface TOTPAuthenticator { * @public */ export interface OOBSMSAuthenticator { + /** + * Authenticator ID. + */ id: string; + /** + * Authenticator type. + */ type: "oob"; + /** + * Authenticator creation time. + */ createdAt: Date; + /** + * Authenticator activation time. + */ activatedAt: Date; + /** + * OOB channel. + */ channel: "sms"; + /** + * Masked SMS phone number, in E.164 format. + * @example "+8522345****" + */ maskedPhone: string; } @@ -255,11 +424,30 @@ export interface OOBSMSAuthenticator { * @public */ export interface OOBEmailAuthenticator { + /** + * Authenticator ID. + */ id: string; + /** + * Authenticator type. + */ type: "oob"; + /** + * Authenticator creation time. + */ createdAt: Date; + /** + * Authenticator activation time. + */ activatedAt: Date; + /** + * OOB channel. + */ channel: "email"; + /** + * Masked email address, in RFC 5322 format. + * @example "joh****\@example.com" + */ maskedEmail: string; } @@ -276,8 +464,23 @@ export interface GenerateOTPAuthURIOptions { * @public */ export interface CreateNewTOTPOptions { + /** + * Authenticator display name. + */ displayName: string; + /** + * Authenticator issuer. + * + * @remarks + * It is not persisted and only used for the result QR code. + */ issuer: string; + /** + * Authenticator account name. + * + * @remarks + * It is not persisted and only used for the result QR code. + */ accountName: string; } @@ -285,10 +488,29 @@ export interface CreateNewTOTPOptions { * @public */ export interface CreateNewTOTPResult { + /** + * Authenticator ID. + */ authenticatorID: string; + /** + * Authenticator type. + */ authenticatorType: "totp"; + /** + * TOTP secret. + * + * @remarks + * This cannot be retrieved using APIs; users should provide it to TOTP + * authenticator. + */ secret: string; + /** + * Generated OTPAuth URI. + */ otpauthURI: string; + /** + * URI of QR code image for generated OTPAuth URI. + */ qrCodeImageURI: string; } @@ -296,6 +518,10 @@ export interface CreateNewTOTPResult { * @public */ export interface ActivateTOTPResult { + /** + * List of recovery codes. Present only if it is the first activated + * authenticator. + */ recoveryCodes?: string[]; } @@ -303,7 +529,14 @@ export interface ActivateTOTPResult { * @public */ export interface AuthenticateWithTOTPOptions { + /** + * TOTP code. + */ otp: string; + /** + * Mark the current device as trusted device. MFA would be skipped for + * this device for a period. + */ skipMFAForCurrentDevice?: boolean; } @@ -318,7 +551,13 @@ export type CreateNewOOBOptions = * @public */ export interface CreateNewOOBSMSOptions { + /** + * OOB channel. + */ channel: "sms"; + /** + * SMS phone number in E.164 format. + */ phone: string; } @@ -326,7 +565,13 @@ export interface CreateNewOOBSMSOptions { * @public */ export interface CreateNewOOBEmailOptions { + /** + * OOB channel. + */ channel: "email"; + /** + * Email address in RFC 5322 format. + */ email: string; } @@ -334,8 +579,17 @@ export interface CreateNewOOBEmailOptions { * @public */ export interface CreateNewOOBResult { + /** + * Authenticator ID. + */ authenticatorID: string; + /** + * Authenticator type. + */ authenticatorType: "oob"; + /** + * OOB channel. + */ channel: "sms" | "email"; } @@ -343,6 +597,10 @@ export interface CreateNewOOBResult { * @public */ export interface ActivateOOBResult { + /** + * List of recovery codes. Present only if it is the first activated + * authenticator. + */ recoveryCodes?: string[]; } @@ -350,7 +608,14 @@ export interface ActivateOOBResult { * @public */ export interface AuthenticateWithOOBOptions { + /** + * MFA code. + */ code: string; + /** + * Mark the current device as trusted device. MFA would be skipped for + * this device for a period. + */ skipMFAForCurrentDevice?: boolean; } @@ -358,7 +623,16 @@ export interface AuthenticateWithOOBOptions { * @public */ export interface AuthenticationSession { + /** + * Authentication session token. + * + * @remarks + * This is an opaque token. Clients should not attempt to interpret it. + */ token: string; + /** + * Current step in authentication session. + */ step: "identity" | "mfa"; } @@ -366,7 +640,6 @@ export interface AuthenticationSession { * @internal */ export interface _PresignUploadRequest { - exact_name?: string; prefix?: string; access?: "public" | "private"; headers?: { diff --git a/packages/skygear-core/src/validation.ts b/packages/skygear-core/src/validation.ts index ad63df13..35919f8a 100644 --- a/packages/skygear-core/src/validation.ts +++ b/packages/skygear-core/src/validation.ts @@ -4,8 +4,14 @@ import { SkygearError } from "./error"; * @public */ export interface ValidationError extends SkygearError { + /** + * {@inheritdoc SkygearError.reason} + */ reason: "ValidationFailed"; info: { + /** + * Error causes. + */ causes: ValidationErrorCause[]; }; } @@ -35,9 +41,29 @@ export type ValidationErrorKind = (typeof ValidationErrorKinds)[keyof (typeof Va * @public */ export interface ValidationErrorCauseBase { + /** + * Validation error kind. + */ kind: Kind; + /** + * JSON pointer to field causing the error. + */ pointer: string; + /** + * Error message. + * + * @remarks + * Error messages are provided for convenience, and not stable APIs; + * Consumers should use {@link ValidationErrorCauseBase.kind} to distinguish + * between different error causes. + */ message: string; + /** + * Error details. + * + * @remarks + * Error details are specific to each error cause kind. + */ details: Details; } @@ -127,6 +153,12 @@ export type ValidationErrorCause = | ValidationInvalidNumberRangeCause; /** + * Check if the provided error indicates the server failed to validate input + * parameters to API. + * + * @remarks + * The error may be thrown when calling any of the Skygear APIs. + * * @public */ export function isValidationError(err: unknown): err is ValidationError { diff --git a/packages/skygear-node-client/src/index.ts b/packages/skygear-node-client/src/index.ts index 1639470c..420127a0 100644 --- a/packages/skygear-node-client/src/index.ts +++ b/packages/skygear-node-client/src/index.ts @@ -49,6 +49,11 @@ export class MemoryStorageDriver implements StorageDriver { } /** + * Returns name of the device. + * + * @remarks + * On Node.js platform, it returns `hostname` of the platform. + * * @public */ export async function getDeviceName(): Promise { @@ -79,16 +84,29 @@ async function uploadData( * @public */ export interface UploadAssetOptions { - exactName?: string; + /** + * The asset name prefix. + */ prefix?: string; + /** + * The access control type of asset. + */ access?: "public" | "private"; + /** + * Additional HTTP headers to be returned with the asset. + */ headers?: { [name: string]: string; }; + /** + * Asset size in bytes. + */ size?: number; } /** + * Skygear Asset APIs (for Node.js). + * * @public */ export class NodeAssetContainer { @@ -98,6 +116,14 @@ export class NodeAssetContainer { this.parent = parent; } + /** + * Uploads new asset. + * + * @param data - Asset data + * @param options - Upload options + * + * @returns Asset name + */ async upload( data: Buffer | Readable, options?: UploadAssetOptions @@ -105,9 +131,6 @@ export class NodeAssetContainer { // Prepare presignRequest const presignRequest: _PresignUploadRequest = {}; if (options != null) { - if (options.exactName != null) { - presignRequest.exact_name = options.exactName; - } presignRequest.prefix = options.prefix; presignRequest.access = options.access; if (options.headers != null) { @@ -157,6 +180,8 @@ export class NodeAssetContainer { } /** + * Skygear APIs container (for Node.js). + * * @public */ export class NodeContainer extends Container { @@ -177,6 +202,11 @@ export class NodeContainer extends Container { } /** + * Default Skygear APIs container. + * + * @remarks + * This is a global shared container, provided for convenience. + * * @public */ const defaultContainer: NodeContainer = new NodeContainer(); diff --git a/packages/skygear-react-native/src/index.ts b/packages/skygear-react-native/src/index.ts index 1bf958fe..798a8aa7 100644 --- a/packages/skygear-react-native/src/index.ts +++ b/packages/skygear-react-native/src/index.ts @@ -95,16 +95,29 @@ async function uploadForm( * @public */ export interface UploadAssetOptions { - exactName?: string; + /** + * The asset name prefix. + */ prefix?: string; + /** + * The access control type of asset. + */ access?: "public" | "private"; + /** + * Additional HTTP headers to be returned with the asset. + */ headers?: { [name: string]: string; }; + /** + * Callback for reporting upload progress. + */ onUploadProgress?: (e: ProgressEvent) => void; } /** + * Skygear Asset APIs (for React Native). + * * @public */ export class ReactNativeAssetContainer { @@ -114,13 +127,18 @@ export class ReactNativeAssetContainer { this.parent = parent; } + /** + * Uploads new asset. + * + * @param uri - Asset data URI + * @param options - Upload options + * + * @returns Asset name + */ async upload(uri: string, options?: UploadAssetOptions): Promise { // Prepare presignRequest const presignRequest: _PresignUploadRequest = {}; if (options != null) { - if (options.exactName != null) { - presignRequest.exact_name = options.exactName; - } presignRequest.prefix = options.prefix; presignRequest.access = options.access; if (options.headers != null) { @@ -146,6 +164,8 @@ export class ReactNativeAssetContainer { } /** + * Skygear APIs container (for React Native). + * * @public */ export class ReactNativeContainer< @@ -170,6 +190,11 @@ export class ReactNativeContainer< } /** + * Default Skygear APIs container. + * + * @remarks + * This is a global shared container, provided for convenience. + * * @public */ const defaultContainer: ReactNativeContainer< diff --git a/packages/skygear-web/src/container.ts b/packages/skygear-web/src/container.ts index 0f4b796c..2875acab 100644 --- a/packages/skygear-web/src/container.ts +++ b/packages/skygear-web/src/container.ts @@ -92,6 +92,8 @@ function uploadForm( } /** + * Skygear Auth APIs (for web platforms). + * * @public */ export class WebAuthContainer extends AuthContainer { @@ -173,6 +175,12 @@ export class WebAuthContainer extends AuthContainer { } } + /** + * Login user with OAuth SSO provider using popup window. + * + * @param providerID - SSO provider ID + * @param options - SSO login options + */ async loginOAuthProviderWithPopup( providerID: string, options?: SSOLoginOptions @@ -188,6 +196,11 @@ export class WebAuthContainer extends AuthContainer { return this.handleAuthResponse(f()); } + /** + * Links user with OAuth SSO provider using popup window. + * + * @param providerID - SSO provider ID + */ async linkOAuthProviderWithPopup(providerID: string): Promise { const f = async () => { const authorizationCode = await this._oauthProviderPopupFlow( @@ -199,6 +212,13 @@ export class WebAuthContainer extends AuthContainer { return this.handleAuthResponse(f()); } + /** + * Login user with OAuth SSO provider by redirecting user. + * + * @param providerID - SSO provider ID + * @param callbackURL - URL to return when authentication completed + * @param options - SSO login options + */ async loginOAuthProviderWithRedirect( providerID: string, callbackURL: string, @@ -222,6 +242,12 @@ export class WebAuthContainer extends AuthContainer { window.location.href = url; } + /** + * Links user with OAuth SSO provider by redirecting user. + * + * @param providerID - SSO provider ID + * @param callbackURL - URL to return when authentication completed + */ async linkOAuthProviderWithRedirect( providerID: string, callbackURL: string @@ -268,6 +294,13 @@ export class WebAuthContainer extends AuthContainer { return j.result.result; } + /** + * Gets SSO login result. + * + * @remarks + * This function should be called by the page at `callbackURL`, + * after calling {@link WebAuthContainer.loginOAuthProviderWithRedirect}. + */ async getLoginRedirectResult(): Promise { const f = async () => { const authorizationCode = await this._getRedirectResult("login"); @@ -279,6 +312,13 @@ export class WebAuthContainer extends AuthContainer { return this.handleMaybeAuthResponse(f()); } + /** + * Gets SSO link result. + * + * @remarks + * This function should be called by the page at `callbackURL`, + * after calling {@link WebAuthContainer.linkOAuthProviderWithRedirect}. + */ async getLinkRedirectResult(): Promise { const f = async () => { const authorizationCode = await this._getRedirectResult("link"); @@ -295,16 +335,29 @@ export class WebAuthContainer extends AuthContainer { * @public */ export interface UploadAssetOptions { - exactName?: string; + /** + * The asset name prefix. + */ prefix?: string; + /** + * The access control type of asset. + */ access?: "public" | "private"; + /** + * Additional HTTP headers to be returned with the asset. + */ headers?: { [name: string]: string; }; + /** + * Callback for reporting upload progress. + */ onUploadProgress?: (e: ProgressEvent) => void; } /** + * Skygear Asset APIs (for web platforms). + * * @public */ export class WebAssetContainer { @@ -314,13 +367,18 @@ export class WebAssetContainer { this.parent = parent; } + /** + * Uploads new asset. + * + * @param blob - Asset data + * @param options - Upload options + * + * @returns Asset name + */ async upload(blob: Blob, options?: UploadAssetOptions): Promise { // Prepare presignRequest const presignRequest: _PresignUploadRequest = {}; if (options != null) { - if (options.exactName != null) { - presignRequest.exact_name = options.exactName; - } presignRequest.prefix = options.prefix; presignRequest.access = options.access; if (options.headers != null) { @@ -360,6 +418,8 @@ export class WebAssetContainer { } /** + * Skygear APIs container (for web platforms). + * * @public */ export class WebContainer extends Container { diff --git a/packages/skygear-web/src/index.ts b/packages/skygear-web/src/index.ts index f76d3c90..154b75a6 100644 --- a/packages/skygear-web/src/index.ts +++ b/packages/skygear-web/src/index.ts @@ -6,6 +6,11 @@ import { WebContainer } from "./container"; export * from "./container"; /** + * Default Skygear APIs container. + * + * @remarks + * This is a global shared container, provided for convenience. + * * @public */ const defaultContainer: WebContainer = new WebContainer();