From 9468706c342192e60a6b51d30f28ebbfc104d0c4 Mon Sep 17 00:00:00 2001 From: Dave Gramlich Date: Sat, 2 Mar 2019 12:40:33 -0500 Subject: [PATCH 1/2] fix(typescript): export all the types --- src/iam.ts | 2 +- src/index.ts | 1050 +---------------------------------------- src/publisher.ts | 2 +- src/pubsub.ts | 1052 ++++++++++++++++++++++++++++++++++++++++++ src/snapshot.ts | 3 +- src/subscription.ts | 2 +- src/topic.ts | 2 +- test/iam.ts | 2 +- test/index.ts | 2 +- test/snapshot.ts | 3 +- test/subscriber.ts | 2 +- test/subscription.ts | 2 +- test/topic.ts | 2 +- 13 files changed, 1075 insertions(+), 1051 deletions(-) create mode 100644 src/pubsub.ts diff --git a/src/iam.ts b/src/iam.ts index 8e0e91dd0..b9bef871f 100644 --- a/src/iam.ts +++ b/src/iam.ts @@ -24,7 +24,7 @@ import {CallOptions} from 'google-gax'; import {google} from '../proto/iam'; -import {Omit, PubSub, RequestCallback, ResourceCallback} from '.'; +import {Omit, PubSub, RequestCallback, ResourceCallback} from './pubsub'; export type Policy = { etag?: string|Buffer diff --git a/src/index.ts b/src/index.ts index 5d8a3db02..479d6cb57 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,1044 +21,6 @@ * @namespace google.protobuf */ -import {paginator} from '@google-cloud/paginator'; -import {replaceProjectIdToken} from '@google-cloud/projectify'; -import {promisifyAll} from '@google-cloud/promisify'; -import * as extend from 'extend'; -import {GoogleAuth} from 'google-auth-library'; -import * as gax from 'google-gax'; -import * as is from 'is'; - -const PKG = require('../../package.json'); -const v1 = require('./v1'); - -import {Snapshot} from './snapshot'; -import {Subscription, SubscriptionMetadata, SubscriptionOptions, CreateSubscriptionOptions, CreateSubscriptionCallback, CreateSubscriptionResponse} from './subscription'; -import {Topic, GetTopicSubscriptionsCallback, GetTopicSubscriptionsResponse, CreateTopicCallback, CreateTopicResponse} from './topic'; -import {PublishOptions} from './publisher'; -import {CallOptions} from 'google-gax'; -import {Transform} from 'stream'; -import {google} from '../proto/pubsub'; -import {ServiceError, ChannelCredentials} from 'grpc'; -import {FlowControlOptions} from './lease-manager'; -import {BatchPublishOptions} from './publisher'; - -const opts = {} as gax.GrpcClientOptions; -const {grpc} = new gax.GrpcClient(opts); - -/** - * Project ID placeholder. - * @type {string} - * @private - */ -const PROJECT_ID_PLACEHOLDER = '{{projectId}}'; - -export type Omit = Pick>; - -export interface ClientConfig extends gax.GrpcClientOptions { - apiEndpoint?: string; - servicePath?: string; - port?: string|number; - sslCreds?: ChannelCredentials; -} - -export interface PageOptions { - gaxOpts?: CallOptions; - pageSize?: number; - pageToken?: string; - autoPaginate?: boolean; -} - -export type GetSnapshotsCallback = - RequestCallback; - -export type GetSnapshotsResponse = - PagedResponse; - -export type GetSubscriptionsOptions = PageOptions&{topic?: string | Topic}; - -type GetAllSubscriptionsCallback = - RequestCallback; - -type GetAllSubscriptionsResponse = - PagedResponse; - -export type GetSubscriptionsCallback = - GetAllSubscriptionsCallback|GetTopicSubscriptionsCallback; - -export type GetSubscriptionsResponse = - GetAllSubscriptionsResponse|GetTopicSubscriptionsResponse; - -export type GetTopicsCallback = - RequestCallback; - -export type GetTopicsResponse = - PagedResponse; - -export type EmptyCallback = RequestCallback; -export type EmptyResponse = [google.protobuf.IEmpty]; - -export type ExistsCallback = RequestCallback; -export type ExistsResponse = [boolean]; - -export interface GetClientConfig { - client: 'PublisherClient'|'SubscriberClient'; -} - -export interface RequestConfig extends GetClientConfig { - method: string; - reqOpts?: object; - gaxOpts?: CallOptions; -} - -export interface ResourceCallback { - (err: ServiceError|null, resource?: Resource|null, - response?: Response|null): void; -} - -export type RequestCallback = - R extends void ? NormalCallback: PagedCallback; - -export interface NormalCallback { - (err: ServiceError|null, res?: TResponse|null): void; -} - -export interface PagedCallback { - (err: ServiceError|null, results?: Item[]|null, nextQuery?: {}|null, - response?: Response|null): void; -} - -export type PagedResponse = - [Item[]]|[Item[], {} | null, Response]; - -export type ObjectStream = { - addListener(event: 'data', listener: (data: O) => void): ObjectStream; - emit(event: 'data', data: O): boolean; - on(event: 'data', listener: (data: O) => void): ObjectStream; - once(event: 'data', listener: (data: O) => void): ObjectStream; - prependListener(event: 'data', listener: (data: O) => void): ObjectStream; - prependOnceListener(event: 'data', listener: (data: O) => void): - ObjectStream; -}&Transform; - -interface GetClientCallback { - (err: Error|null, gaxClient?: gax.ClientStub): void; -} - -/** - * @typedef {object} ClientConfig - * @property {string} [projectId] The project ID from the Google Developer's - * Console, e.g. 'grape-spaceship-123'. We will also check the environment - * variable `GCLOUD_PROJECT` for your project ID. If your app is running in - * an environment which supports {@link - * https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application - * Application Default Credentials}, your project ID will be detected - * automatically. - * @property {string} [keyFilename] Full path to the a .json, .pem, or .p12 key - * downloaded from the Google Developers Console. If you provide a path to a - * JSON file, the `projectId` option above is not necessary. NOTE: .pem and - * .p12 require you to specify the `email` option as well. - * @property {string} [apiEndpoint] The `apiEndpoint` from options will set the - * host. If not set, the `PUBSUB_EMULATOR_HOST` environment variable from - * the gcloud SDK is honored, otherwise the actual API endpoint will be - * used. - * @property {string} [email] Account email address. Required when using a .pem - * or .p12 keyFilename. - * @property {object} [credentials] Credentials object. - * @property {string} [credentials.client_email] - * @property {string} [credentials.private_key] - * @property {boolean} [autoRetry=true] Automatically retry requests if the - * response is related to rate limits or certain intermittent server errors. - * We will exponentially backoff subsequent requests by default. - * @property {number} [maxRetries=3] Maximum number of automatic retries - * attempted before returning the error. - * @property {Constructor} [promise] Custom promise module to use instead of - * native Promises. - */ -/** - * [Cloud Pub/Sub](https://developers.google.com/pubsub/overview) is a - * reliable, many-to-many, asynchronous messaging service from Cloud - * Platform. - * - * @class - * - * @see [Cloud Pub/Sub overview]{@link https://developers.google.com/pubsub/overview} - * - * @param {ClientConfig} [options] Configuration options. - * - * @example Import the client library - * const {PubSub} = require('@google-cloud/pubsub'); - * - * @example Create a client that uses Application - * Default Credentials (ADC): const pubsub = new PubSub(); - * - * @example Create a client with explicit - * credentials: const pubsub = new PubSub({ projectId: - * 'your-project-id', keyFilename: '/path/to/keyfile.json' - * }); - * - * @example include:samples/quickstart.js - * region_tag:pubsub_quickstart_create_topic - * Full quickstart example: - */ -export class PubSub { - options: ClientConfig; - isEmulator: boolean; - api: {[key: string]: gax.ClientStub}; - auth: GoogleAuth; - projectId: string; - // tslint:disable-next-line variable-name - Promise?: PromiseConstructor; - getSubscriptionsStream = paginator.streamify('getSubscriptions') as() => - ObjectStream; - getSnapshotsStream = paginator.streamify('getSnapshots') as() => - ObjectStream; - getTopicsStream = paginator.streamify('getTopics') as() => - ObjectStream; - - constructor(options?: ClientConfig) { - options = options || {}; - // Determine what scopes are needed. - // It is the union of the scopes on both clients. - const clientClasses = [v1.SubscriberClient, v1.PublisherClient]; - const allScopes: {[key: string]: boolean} = {}; - for (const clientClass of clientClasses) { - for (const scope of clientClass.scopes) { - allScopes[scope] = true; - } - } - this.options = Object.assign( - { - 'grpc.keepalive_time_ms': 300000, - 'grpc.max_send_message_length': -1, - 'grpc.max_receive_message_length': 20000001, - libName: 'gccl', - libVersion: PKG.version, - scopes: Object.keys(allScopes), - }, - options); - /** - * @name PubSub#isEmulator - * @type {boolean} - */ - this.isEmulator = false; - this.determineBaseUrl_(); - this.api = {}; - this.auth = new GoogleAuth(this.options); - this.projectId = this.options.projectId || PROJECT_ID_PLACEHOLDER; - if (this.options.promise) { - this.Promise = this.options.promise; - } - } - - createSubscription( - topic: Topic|string, name: string, - options?: CreateSubscriptionOptions): Promise; - createSubscription( - topic: Topic|string, name: string, options: CreateSubscriptionOptions, - callback: CreateSubscriptionCallback): void; - createSubscription( - topic: Topic|string, name: string, - callback: CreateSubscriptionCallback): void; - /** - * @typedef {array} CreateSubscriptionResponse - * @property {Subscription} 0 The new {@link Subscription}. - * @property {object} 1 The full API response. - */ - /** - * @callback CreateSubscriptionCallback - * @param {?Error} err Request error, if any. - * @param {Subscription} Subscription - * @param {object} apiResponse The full API response. - */ - /** - * Options for creating a subscription. - * - * See a [Subscription - * resource](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions). - * - * @typedef {object} CreateSubscriptionRequest - * @property {object} [flowControl] Flow control configurations for - * receiving messages. Note that these options do not persist across - * subscription instances. - * @property {number} [flowControl.maxBytes] The maximum number of bytes - * in un-acked messages to allow before the subscription pauses incoming - * messages. Defaults to 20% of free memory. - * @property {number} [flowControl.maxMessages=Infinity] The maximum number - * of un-acked messages to allow before the subscription pauses incoming - * messages. - * @property {object} [gaxOpts] Request configuration options, outlined - * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. - * @property {number|date} [messageRetentionDuration] Set this to override - * the default duration of 7 days. This value is expected in seconds. - * Acceptable values are in the range of 10 minutes and 7 days. - * @property {string} [pushEndpoint] A URL to a custom endpoint that - * messages should be pushed to. - * @property {boolean} [retainAckedMessages=false] If set, acked messages - * are retained in the subscription's backlog for the length of time - * specified by `options.messageRetentionDuration`. - * @property {ExpirationPolicy} [expirationPolicy] A policy that specifies - * the conditions for this subscription's expiration. - */ - /** - * Create a subscription to a topic. - * - * @see [Subscriptions: create API Documentation]{@link https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/create} - * @see {@link Topic#createSubscription} - * - * @throws {Error} If a Topic instance or topic name is not provided. - * @throws {Error} If a subscription name is not provided. - * - * @param {Topic|string} topic The Topic to create a - * subscription to. - * @param {string} name The name of the subscription. - * @param {CreateSubscriptionRequest} [options] See a - * [Subscription - * resource](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions). - * @param {CreateSubscriptionCallback} [callback] Callback function. - * @returns {Promise} - * - * @example Subscribe to a topic. - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * const topic = 'messageCenter'; - * const name = 'newMessages'; - * - * const callback = function(err, subscription, apiResponse) {}; - * - * pubsub.createSubscription(topic, name, callback); - * - * @example If the callback is omitted, we'll return a - * Promise. pubsub.createSubscription(topic, - * name).then(function(data) { const subscription = data[0]; const apiResponse - * = data[1]; - * }); - */ - createSubscription( - topic: Topic|string, name: string, - optionsOrCallback?: CreateSubscriptionOptions|CreateSubscriptionCallback, - callback?: CreateSubscriptionCallback): - Promise|void { - if (!is.string(topic) && !(topic instanceof Topic)) { - throw new Error('A Topic is required for a new subscription.'); - } - if (!is.string(name)) { - throw new Error('A subscription name is required.'); - } - if (typeof topic === 'string') { - topic = this.topic(topic); - } - let options = typeof optionsOrCallback === 'object' ? - optionsOrCallback : - {} as CreateSubscriptionOptions; - callback = - typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; - - // Make a deep copy of options to not pollute caller object. - options = extend(true, {}, options); - - const gaxOpts = options.gaxOpts; - const flowControl = options.flowControl; - delete options.gaxOpts; - delete options.flowControl; - - const metadata = - Subscription.formatMetadata_(options as SubscriptionMetadata); - - let subscriptionCtorOptions = flowControl ? {flowControl} : {}; - subscriptionCtorOptions = Object.assign(subscriptionCtorOptions, metadata); - const subscription = this.subscription(name, subscriptionCtorOptions); - - const reqOpts = Object.assign(metadata, { - topic: topic.name, - name: subscription.name, - }); - - this.request( - { - client: 'SubscriberClient', - method: 'createSubscription', - reqOpts, - gaxOpts, - }, - (err, resp) => { - if (err) { - callback!(err, null, resp); - return; - } - subscription.metadata = resp!; - callback!(null, subscription, resp!); - }); - } - - createTopic(name: string, gaxOpts: CallOptions): Promise; - createTopic( - name: string, gaxOpts: CallOptions, callback?: CreateTopicCallback): void; - createTopic(name: string, callback: CreateTopicCallback): void; - /** - * @typedef {array} CreateTopicResponse - * @property {Topic} 0 The new {@link Topic}. - * @property {object} 1 The full API response. - */ - /** - * @callback CreateTopicCallback - * @param {?Error} err Request error, if any. - * @param {Topic} topic The new {@link Topic}. - * @param {object} apiResponse The full API response. - */ - /** - * Create a topic with the given name. - * - * @see [Topics: create API Documentation]{@link https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create} - * - * @param {string} name Name of the topic. - * @param {object} [gaxOpts] Request configuration options, outlined - * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. - * @param {CreateTopicCallback} [callback] Callback function. - * @returns {Promise} - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * pubsub.createTopic('my-new-topic', function(err, topic, apiResponse) { - * if (!err) { - * // The topic was created successfully. - * } - * }); - * - * //- - * // If the callback is omitted, we'll return a Promise. - * //- - * pubsub.createTopic('my-new-topic').then(function(data) { - * const topic = data[0]; - * const apiResponse = data[1]; - * }); - */ - createTopic( - name: string, gaxOptsOrCallback?: CallOptions|CreateTopicCallback, - callback?: CreateTopicCallback): Promise|void { - const topic = this.topic(name); - const reqOpts = { - name: topic.name, - }; - - const gaxOpts = - typeof gaxOptsOrCallback === 'object' ? gaxOptsOrCallback : {}; - callback = - typeof gaxOptsOrCallback === 'function' ? gaxOptsOrCallback : callback; - - this.request( - { - client: 'PublisherClient', - method: 'createTopic', - reqOpts, - gaxOpts, - }, - (err, resp) => { - if (err) { - callback!(err, null, resp); - return; - } - topic.metadata = resp!; - callback!(null, topic, resp!); - }); - } - /** - * Determine the appropriate endpoint to use for API requests, first trying - * the local `apiEndpoint` parameter. If the `apiEndpoint` parameter is null - * we try Pub/Sub emulator environment variable (PUBSUB_EMULATOR_HOST), - * otherwise the default JSON API. - * - * @private - */ - determineBaseUrl_() { - const apiEndpoint = this.options.apiEndpoint; - if (!apiEndpoint && !process.env.PUBSUB_EMULATOR_HOST) { - return; - } - const baseUrl = apiEndpoint || process.env.PUBSUB_EMULATOR_HOST; - const leadingProtocol = new RegExp('^https*://'); - const trailingSlashes = new RegExp('/*$'); - const baseUrlParts = baseUrl!.replace(leadingProtocol, '') - .replace(trailingSlashes, '') - .split(':'); - this.options.servicePath = baseUrlParts[0]; - this.options.port = baseUrlParts[1]; - this.options.sslCreds = grpc.credentials.createInsecure(); - this.isEmulator = true; - } - - getSnapshots(option?: PageOptions): Promise; - getSnapshots(callback: GetSnapshotsCallback): void; - getSnapshots(option: PageOptions, callback: GetSnapshotsCallback): void; - /** - * Query object for listing snapshots. - * - * @typedef {object} GetSnapshotsRequest - * @property {boolean} [autoPaginate=true] Have pagination handled - * automatically. - * @property {object} [options.gaxOpts] Request configuration options, outlined - * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. - * @property {number} [options.pageSize] Maximum number of results to return. - * @property {string} [options.pageToken] Page token. - */ - /** - * @typedef {array} GetSnapshotsResponse - * @property {Snapshot[]} 0 Array of {@link Snapshot} instances. - * @property {object} 1 The full API response. - */ - /** - * @callback GetSnapshotsCallback - * @param {?Error} err Request error, if any. - * @param {Snapshot[]} snapshots Array of {@link Snapshot} instances. - * @param {object} apiResponse The full API response. - */ - /** - * Get a list of snapshots. - * - * @param {GetSnapshotsRequest} [query] Query object for listing snapshots. - * @param {GetSnapshotsCallback} [callback] Callback function. - * @returns {Promise} - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * pubsub.getSnapshots(function(err, snapshots) { - * if (!err) { - * // snapshots is an array of Snapshot objects. - * } - * }); - * - * //- - * // If the callback is omitted, we'll return a Promise. - * //- - * pubsub.getSnapshots().then(function(data) { - * const snapshots = data[0]; - * }); - */ - getSnapshots( - optionsOrCallback?: PageOptions|GetSnapshotsCallback, - callback?: GetSnapshotsCallback): void|Promise { - const self = this; - const options = - typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; - callback = - typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; - const reqOpts = Object.assign( - { - project: 'projects/' + this.projectId, - }, - options); - delete reqOpts.gaxOpts; - delete reqOpts.autoPaginate; - const gaxOpts = Object.assign( - { - autoPaginate: options.autoPaginate, - }, - options.gaxOpts); - this.request< - google.pubsub.v1.ISnapshot, google.pubsub.v1.IListSnapshotsResponse>( - { - client: 'SubscriberClient', - method: 'listSnapshots', - reqOpts, - gaxOpts, - }, - (err, rawSnapshots, ...args) => { - let snapshots: Snapshot[]; - - if (rawSnapshots) { - snapshots = rawSnapshots.map(snapshot => { - const snapshotInstance = self.snapshot(snapshot.name!); - snapshotInstance.metadata = snapshot; - return snapshotInstance; - }); - } - - callback!(err, snapshots!, ...args); - }); - } - - getSubscriptions(options?: GetSubscriptionsOptions): - Promise; - getSubscriptions(callback: GetSubscriptionsCallback): void; - getSubscriptions( - options: GetSubscriptionsOptions, - callback: GetSubscriptionsCallback): void; - /** - * Query object for listing subscriptions. - * - * @typedef {object} GetSubscriptionsRequest - * @property {boolean} [autoPaginate=true] Have pagination handled - * automatically. - * @property {object} [options.gaxOpts] Request configuration options, outlined - * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. - * @property {number} [options.pageSize] Maximum number of results to return. - * @property {string} [options.pageToken] Page token. - * @param {string|Topic} options.topic - The name of the topic to - * list subscriptions from. - */ - /** - * @typedef {array} GetSubscriptionsResponse - * @property {Subscription[]} 0 Array of {@link Subscription} instances. - * @property {object} 1 The full API response. - */ - /** - * @callback GetSubscriptionsCallback - * @param {?Error} err Request error, if any. - * @param {Subscription[]} subscriptions Array of {@link Subscription} instances. - * @param {object} apiResponse The full API response. - */ - /** - * Get a list of the subscriptions registered to all of your project's topics. - * You may optionally provide a query object as the first argument to - * customize the response. - * - * Your provided callback will be invoked with an error object if an API error - * occurred or an array of {@link Subscription} objects. - * - * To get subscriptions for a topic, see {@link Topic}. - * - * @see [Subscriptions: list API Documentation]{@link https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/list} - * - * @param {GetSubscriptionsRequest} [query] Query object for listing subscriptions. - * @param {GetSubscriptionsCallback} [callback] Callback function. - * @returns {Promise} - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * pubsub.getSubscriptions(function(err, subscriptions) { - * if (!err) { - * // subscriptions is an array of Subscription objects. - * } - * }); - * - * //- - * // If the callback is omitted, we'll return a Promise. - * //- - * pubsub.getSubscriptions().then(function(data) { - * const subscriptions = data[0]; - * }); - */ - getSubscriptions( - optionsOrCallback?: GetSubscriptionsOptions|GetSubscriptionsCallback, - callback?: GetSubscriptionsCallback): - void|Promise { - const self = this; - const options = - typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; - callback = - typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; - - let topic = options.topic; - if (topic) { - if (!(topic instanceof Topic)) { - topic = this.topic(topic); - } - return topic.getSubscriptions( - options, callback as GetTopicSubscriptionsCallback); - } - const reqOpts = Object.assign({}, options) as - google.pubsub.v1.IListSubscriptionsRequest; - reqOpts.project = 'projects/' + this.projectId; - - delete (reqOpts as GetSubscriptionsOptions).gaxOpts; - delete (reqOpts as GetSubscriptionsOptions).autoPaginate; - - const gaxOpts = Object.assign( - { - autoPaginate: options.autoPaginate, - }, - options.gaxOpts); - - this.request< - google.pubsub.v1.ISubscription, - google.pubsub.v1.IListSubscriptionsResponse>( - { - client: 'SubscriberClient', - method: 'listSubscriptions', - reqOpts, - gaxOpts, - }, - (err, rawSubs, ...args) => { - let subscriptions: Subscription[]; - - if (rawSubs) { - subscriptions = rawSubs.map(sub => { - const subscriptionInstance = self.subscription(sub.name!); - subscriptionInstance.metadata = sub; - return subscriptionInstance; - }); - } - - (callback as GetAllSubscriptionsCallback)( - err, subscriptions!, ...args); - }); - } - - getTopics(options: PageOptions): Promise; - getTopics(callback: GetTopicsCallback): void; - getTopics(options: PageOptions, callback: GetTopicsCallback): void; - /** - * Query object for listing topics. - * - * @typedef {object} GetTopicsRequest - * @property {boolean} [autoPaginate=true] Have pagination handled - * automatically. - * @property {object} [options.gaxOpts] Request configuration options, outlined - * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. - * @property {number} [options.pageSize] Maximum number of results to return. - * @property {string} [options.pageToken] Page token. - */ - /** - * @typedef {array} GetTopicsResponse - * @property {Topic[]} 0 Array of {@link Topic} instances. - * @property {object} 1 The full API response. - */ - /** - * @callback GetTopicsCallback - * @param {?Error} err Request error, if any. - * @param {Topic[]} topics Array of {@link Topic} instances. - * @param {object} apiResponse The full API response. - */ - /** - * Get a list of the topics registered to your project. You may optionally - * provide a query object as the first argument to customize the response. - * - * @see [Topics: list API Documentation]{@link https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/list} - * - * @param {GetTopicsRequest} [query] Query object for listing topics. - * @param {GetTopicsCallback} [callback] Callback function. - * @returns {Promise} - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * pubsub.getTopics(function(err, topics) { - * if (!err) { - * // topics is an array of Topic objects. - * } - * }); - * - * //- - * // Customize the query. - * //- - * pubsub.getTopics({ - * pageSize: 3 - * }, function(err, topics) {}); - * - * //- - * // If the callback is omitted, we'll return a Promise. - * //- - * pubsub.getTopics().then(function(data) { - * const topics = data[0]; - * }); - */ - getTopics( - optionsOrCallback?: PageOptions|GetTopicsCallback, - callback?: GetTopicsCallback): void|Promise { - const self = this; - const options = - typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; - callback = - typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; - - const reqOpts = Object.assign( - { - project: 'projects/' + this.projectId, - }, - options); - delete reqOpts.gaxOpts; - delete reqOpts.autoPaginate; - const gaxOpts = Object.assign( - { - autoPaginate: options.autoPaginate, - }, - options.gaxOpts); - this.request( - { - client: 'PublisherClient', - method: 'listTopics', - reqOpts, - gaxOpts, - }, - (err, rawTopics, ...args) => { - let topics: Topic[]; - - if (rawTopics) { - topics = rawTopics.map(topic => { - const topicInstance = self.topic(topic.name); - topicInstance.metadata = topic; - return topicInstance; - }); - } - - callback!(err, topics!, ...args); - }); - } - /** - * Callback function to PubSub.getClient_(). - * @private - * @callback GetClientCallback - * @param err - Error, if any. - * @param gaxClient - The gax client specified in RequestConfig.client. - * Typed any since it's importing Javascript source. - */ - /** - * Get the PubSub client object. - * - * @private - * - * @param {object} config Configuration object. - * @param {object} config.gaxOpts GAX options. - * @param {function} config.method The gax method to call. - * @param {object} config.reqOpts Request options. - * @param {function} [callback] The callback function. - */ - getClient_(config: GetClientConfig, callback: GetClientCallback) { - const hasProjectId = - this.projectId && this.projectId !== PROJECT_ID_PLACEHOLDER; - if (!hasProjectId && !this.isEmulator) { - this.auth.getProjectId((err, projectId) => { - if (err) { - callback(err); - return; - } - this.projectId = projectId!; - this.options.projectId = projectId!; - - this.getClient_(config, callback); - }); - return; - } - let gaxClient = this.api[config.client]; - if (!gaxClient) { - // Lazily instantiate client. - gaxClient = new v1[config.client](this.options) as gax.ClientStub; - this.api[config.client] = gaxClient; - } - callback(null, gaxClient); - } - /** - * Funnel all API requests through this method, to be sure we have a project - * ID. - * - * @private - * - * @param {object} config Configuration object. - * @param {object} config.gaxOpts GAX options. - * @param {function} config.method The gax method to call. - * @param {object} config.reqOpts Request options. - * @param {function} [callback] The callback function. - */ - request(config: RequestConfig, callback: RequestCallback) { - const self = this; - this.getClient_(config, (err, client) => { - if (err) { - callback(err); - return; - } - let reqOpts = extend(true, {}, config.reqOpts); - reqOpts = replaceProjectIdToken(reqOpts, self.projectId); - client![config.method](reqOpts, config.gaxOpts, callback); - }); - } - /** - * Create a Snapshot object. See {@link Subscription#createSnapshot} to - * create a snapshot. - * - * @throws {Error} If a name is not provided. - * - * @param {string} name The name of the snapshot. - * @returns {Snapshot} A {@link Snapshot} instance. - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * const snapshot = pubsub.snapshot('my-snapshot'); - */ - snapshot(name: string): Snapshot { - if (!is.string(name)) { - throw new Error('You must supply a valid name for the snapshot.'); - } - return new Snapshot(this, name); - } - /** - * Create a Subscription object. This command by itself will not run any API - * requests. You will receive a {@link Subscription} object, - * which will allow you to interact with a subscription. - * - * @throws {Error} If subscription name is omitted. - * - * @param {string} name Name of the subscription. - * @param {SubscriberOptions} [options] Subscription options. - * @returns {Subscription} A {@link Subscription} instance. - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * const subscription = pubsub.subscription('my-subscription'); - * - * // Register a listener for `message` events. - * subscription.on('message', function(message) { - * // Called every time a message is received. - * // message.id = ID of the message. - * // message.ackId = ID used to acknowledge the message receival. - * // message.data = Contents of the message. - * // message.attributes = Attributes of the message. - * // message.publishTime = Date when Pub/Sub received the message. - * }); - */ - subscription(name: string, options?: SubscriptionOptions): Subscription { - if (!name) { - throw new Error('A name must be specified for a subscription.'); - } - return new Subscription(this, name, options); - } - /** - * Create a Topic object. See {@link PubSub#createTopic} to create a topic. - * - * @throws {Error} If a name is not provided. - * - * @param {string} name The name of the topic. - * @returns {Topic} A {@link Topic} instance. - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * const topic = pubsub.topic('my-topic'); - */ - topic(name: string, options?: PublishOptions): Topic { - if (!name) { - throw new Error('A name must be specified for a topic.'); - } - return new Topic(this, name, options); - } -} - -/** - * Get a list of the {@link Snapshot} objects as a readable object stream. - * - * @method PubSub#getSnapshotsStream - * @param {GetSnapshotsRequest} [options] Configuration object. See - * {@link PubSub#getSnapshots} for a complete list of options. - * @returns {ReadableStream} A readable stream of {@link Snapshot} instances. - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * pubsub.getSnapshotsStream() - * .on('error', console.error) - * .on('data', function(snapshot) { - * // snapshot is a Snapshot object. - * }) - * .on('end', function() { - * // All snapshots retrieved. - * }); - * - * //- - * // If you anticipate many results, you can end a stream early to prevent - * // unnecessary processing and API requests. - * //- - * pubsub.getSnapshotsStream() - * .on('data', function(snapshot) { - * this.end(); - * }); - */ - -/** - * Get a list of the {@link Subscription} objects registered to all of - * your project's topics as a readable object stream. - * - * @method PubSub#getSubscriptionsStream - * @param {GetSubscriptionsRequest} [options] Configuration object. See - * {@link PubSub#getSubscriptions} for a complete list of options. - * @returns {ReadableStream} A readable stream of {@link Subscription} instances. - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * pubsub.getSubscriptionsStream() - * .on('error', console.error) - * .on('data', function(subscription) { - * // subscription is a Subscription object. - * }) - * .on('end', function() { - * // All subscriptions retrieved. - * }); - * - * //- - * // If you anticipate many results, you can end a stream early to prevent - * // unnecessary processing and API requests. - * //- - * pubsub.getSubscriptionsStream() - * .on('data', function(subscription) { - * this.end(); - * }); - */ - -/** - * Get a list of the {module:pubsub/topic} objects registered to your project as - * a readable object stream. - * - * @method PubSub#getTopicsStream - * @param {GetTopicsRequest} [options] Configuration object. See - * {@link PubSub#getTopics} for a complete list of options. - * @returns {ReadableStream} A readable stream of {@link Topic} instances. - * - * @example - * const {PubSub} = require('@google-cloud/pubsub'); - * const pubsub = new PubSub(); - * - * pubsub.getTopicsStream() - * .on('error', console.error) - * .on('data', function(topic) { - * // topic is a Topic object. - * }) - * .on('end', function() { - * // All topics retrieved. - * }); - * - * //- - * // If you anticipate many results, you can end a stream early to prevent - * // unnecessary processing and API requests. - * //- - * pubsub.getTopicsStream() - * .on('data', function(topic) { - * this.end(); - * }); - */ - -/*! Developer Documentation - * - * These methods can be agto-paginated. - */ -paginator.extend(PubSub, ['getSnapshots', 'getSubscriptions', 'getTopics']); - -/*! Developer Documentation - * - * All async methods (except for streams) will return a Promise in the event - * that a callback is omitted. - */ -promisifyAll(PubSub, { - exclude: ['request', 'snapshot', 'subscription', 'topic'], -}); - -export {Subscription, Topic, PublishOptions}; - /** * The default export of the `@google-cloud/pubsub` package is the * {@link PubSub} class. @@ -1112,4 +74,14 @@ export {Subscription, Topic, PublishOptions}; * @property {constructor} SubscriberClient * Reference to {@link v1.SubscriberClient}. */ -module.exports.v1 = v1; +module.exports.v1 = require('./v1'); + +export {CallOptions} from 'google-gax'; +export {ServiceError} from 'grpc'; +export {Policy, GetPolicyCallback, SetPolicyCallback, SetPolicyResponse, GetPolicyResponse, IamPermissionsMap, TestIamPermissionsResponse, TestIamPermissionsCallback, IAM} from './iam'; +export {Attributes, PublishCallback} from './publisher'; +export {PageOptions, GetSnapshotsCallback, GetSnapshotsResponse, GetSubscriptionsCallback, GetSubscriptionsResponse, GetTopicsCallback, GetTopicsResponse, EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, PubSub} from './pubsub'; +export {CreateSnapshotCallback, CreateSnapshotResponse, SeekCallback, SeekResponse, Snapshot} from './snapshot'; +export {Message} from './subscriber'; +export {SubscriptionMetadata, SubscriptionOptions, SubscriptionCloseCallback, CreateSubscriptionOptions, CreateSubscriptionCallback, CreateSubscriptionResponse, GetSubscriptionOptions, GetSubscriptionCallback, GetSubscriptionResponse, GetSubscriptionMetadataCallback, GetSubscriptionMetadataResponse, SetSubscriptionMetadataCallback, SetSubscriptionMetadataResponse, Subscription} from './subscription'; +export {CreateTopicCallback, CreateTopicResponse, GetTopicCallback, GetTopicResponse, GetTopicOptions, GetTopicMetadataCallback, GetTopicMetadataResponse, GetTopicSubscriptionsCallback, GetTopicSubscriptionsResponse, Topic} from './topic'; diff --git a/src/publisher.ts b/src/publisher.ts index fe434b2e8..bdeecd072 100644 --- a/src/publisher.ts +++ b/src/publisher.ts @@ -23,7 +23,7 @@ const each = require('async-each'); import * as extend from 'extend'; import * as is from 'is'; import {Topic} from './topic'; -import {RequestCallback} from '.'; +import {RequestCallback} from './pubsub'; import {ServiceError} from 'grpc'; interface Inventory { diff --git a/src/pubsub.ts b/src/pubsub.ts new file mode 100644 index 000000000..136134aac --- /dev/null +++ b/src/pubsub.ts @@ -0,0 +1,1052 @@ +/*! + * Copyright 2014 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import {paginator} from '@google-cloud/paginator'; +import {replaceProjectIdToken} from '@google-cloud/projectify'; +import {promisifyAll} from '@google-cloud/promisify'; +import * as extend from 'extend'; +import {GoogleAuth} from 'google-auth-library'; +import * as gax from 'google-gax'; +import * as is from 'is'; + +const PKG = require('../../package.json'); +const v1 = require('./v1'); + +import {Snapshot} from './snapshot'; +import {Subscription, SubscriptionMetadata, SubscriptionOptions, CreateSubscriptionOptions, CreateSubscriptionCallback, CreateSubscriptionResponse} from './subscription'; +import {Topic, GetTopicSubscriptionsCallback, GetTopicSubscriptionsResponse, CreateTopicCallback, CreateTopicResponse} from './topic'; +import {PublishOptions} from './publisher'; +import {CallOptions} from 'google-gax'; +import {Transform} from 'stream'; +import {google} from '../proto/pubsub'; +import {ServiceError, ChannelCredentials} from 'grpc'; +import {FlowControlOptions} from './lease-manager'; +import {BatchPublishOptions} from './publisher'; + +const opts = {} as gax.GrpcClientOptions; +const {grpc} = new gax.GrpcClient(opts); + +/** + * Project ID placeholder. + * @type {string} + * @private + */ +const PROJECT_ID_PLACEHOLDER = '{{projectId}}'; + +export type Omit = Pick>; + +export interface ClientConfig extends gax.GrpcClientOptions { + apiEndpoint?: string; + servicePath?: string; + port?: string|number; + sslCreds?: ChannelCredentials; +} + +export interface PageOptions { + gaxOpts?: CallOptions; + pageSize?: number; + pageToken?: string; + autoPaginate?: boolean; +} + +export type GetSnapshotsCallback = + RequestCallback; + +export type GetSnapshotsResponse = + PagedResponse; + +export type GetSubscriptionsOptions = PageOptions&{topic?: string | Topic}; + +type GetAllSubscriptionsCallback = + RequestCallback; + +type GetAllSubscriptionsResponse = + PagedResponse; + +export type GetSubscriptionsCallback = + GetAllSubscriptionsCallback|GetTopicSubscriptionsCallback; + +export type GetSubscriptionsResponse = + GetAllSubscriptionsResponse|GetTopicSubscriptionsResponse; + +export type GetTopicsCallback = + RequestCallback; + +export type GetTopicsResponse = + PagedResponse; + +export type EmptyCallback = RequestCallback; +export type EmptyResponse = [google.protobuf.IEmpty]; + +export type ExistsCallback = RequestCallback; +export type ExistsResponse = [boolean]; + +export interface GetClientConfig { + client: 'PublisherClient'|'SubscriberClient'; +} + +export interface RequestConfig extends GetClientConfig { + method: string; + reqOpts?: object; + gaxOpts?: CallOptions; +} + +export interface ResourceCallback { + (err: ServiceError|null, resource?: Resource|null, + response?: Response|null): void; +} + +export type RequestCallback = + R extends void ? NormalCallback: PagedCallback; + +export interface NormalCallback { + (err: ServiceError|null, res?: TResponse|null): void; +} + +export interface PagedCallback { + (err: ServiceError|null, results?: Item[]|null, nextQuery?: {}|null, + response?: Response|null): void; +} + +export type PagedResponse = + [Item[]]|[Item[], {} | null, Response]; + +export type ObjectStream = { + addListener(event: 'data', listener: (data: O) => void): ObjectStream; + emit(event: 'data', data: O): boolean; + on(event: 'data', listener: (data: O) => void): ObjectStream; + once(event: 'data', listener: (data: O) => void): ObjectStream; + prependListener(event: 'data', listener: (data: O) => void): ObjectStream; + prependOnceListener(event: 'data', listener: (data: O) => void): + ObjectStream; +}&Transform; + +interface GetClientCallback { + (err: Error|null, gaxClient?: gax.ClientStub): void; +} + +/** + * @typedef {object} ClientConfig + * @property {string} [projectId] The project ID from the Google Developer's + * Console, e.g. 'grape-spaceship-123'. We will also check the environment + * variable `GCLOUD_PROJECT` for your project ID. If your app is running in + * an environment which supports {@link + * https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application + * Application Default Credentials}, your project ID will be detected + * automatically. + * @property {string} [keyFilename] Full path to the a .json, .pem, or .p12 key + * downloaded from the Google Developers Console. If you provide a path to a + * JSON file, the `projectId` option above is not necessary. NOTE: .pem and + * .p12 require you to specify the `email` option as well. + * @property {string} [apiEndpoint] The `apiEndpoint` from options will set the + * host. If not set, the `PUBSUB_EMULATOR_HOST` environment variable from + * the gcloud SDK is honored, otherwise the actual API endpoint will be + * used. + * @property {string} [email] Account email address. Required when using a .pem + * or .p12 keyFilename. + * @property {object} [credentials] Credentials object. + * @property {string} [credentials.client_email] + * @property {string} [credentials.private_key] + * @property {boolean} [autoRetry=true] Automatically retry requests if the + * response is related to rate limits or certain intermittent server errors. + * We will exponentially backoff subsequent requests by default. + * @property {number} [maxRetries=3] Maximum number of automatic retries + * attempted before returning the error. + * @property {Constructor} [promise] Custom promise module to use instead of + * native Promises. + */ +/** + * [Cloud Pub/Sub](https://developers.google.com/pubsub/overview) is a + * reliable, many-to-many, asynchronous messaging service from Cloud + * Platform. + * + * @class + * + * @see [Cloud Pub/Sub overview]{@link https://developers.google.com/pubsub/overview} + * + * @param {ClientConfig} [options] Configuration options. + * + * @example Import the client library + * const {PubSub} = require('@google-cloud/pubsub'); + * + * @example Create a client that uses Application + * Default Credentials (ADC): const pubsub = new PubSub(); + * + * @example Create a client with explicit + * credentials: const pubsub = new PubSub({ projectId: + * 'your-project-id', keyFilename: '/path/to/keyfile.json' + * }); + * + * @example include:samples/quickstart.js + * region_tag:pubsub_quickstart_create_topic + * Full quickstart example: + */ +export class PubSub { + options: ClientConfig; + isEmulator: boolean; + api: {[key: string]: gax.ClientStub}; + auth: GoogleAuth; + projectId: string; + // tslint:disable-next-line variable-name + Promise?: PromiseConstructor; + getSubscriptionsStream = paginator.streamify('getSubscriptions') as() => + ObjectStream; + getSnapshotsStream = paginator.streamify('getSnapshots') as() => + ObjectStream; + getTopicsStream = paginator.streamify('getTopics') as() => + ObjectStream; + + constructor(options?: ClientConfig) { + options = options || {}; + // Determine what scopes are needed. + // It is the union of the scopes on both clients. + const clientClasses = [v1.SubscriberClient, v1.PublisherClient]; + const allScopes: {[key: string]: boolean} = {}; + for (const clientClass of clientClasses) { + for (const scope of clientClass.scopes) { + allScopes[scope] = true; + } + } + this.options = Object.assign( + { + 'grpc.keepalive_time_ms': 300000, + 'grpc.max_send_message_length': -1, + 'grpc.max_receive_message_length': 20000001, + libName: 'gccl', + libVersion: PKG.version, + scopes: Object.keys(allScopes), + }, + options); + /** + * @name PubSub#isEmulator + * @type {boolean} + */ + this.isEmulator = false; + this.determineBaseUrl_(); + this.api = {}; + this.auth = new GoogleAuth(this.options); + this.projectId = this.options.projectId || PROJECT_ID_PLACEHOLDER; + if (this.options.promise) { + this.Promise = this.options.promise; + } + } + + createSubscription( + topic: Topic|string, name: string, + options?: CreateSubscriptionOptions): Promise; + createSubscription( + topic: Topic|string, name: string, options: CreateSubscriptionOptions, + callback: CreateSubscriptionCallback): void; + createSubscription( + topic: Topic|string, name: string, + callback: CreateSubscriptionCallback): void; + /** + * @typedef {array} CreateSubscriptionResponse + * @property {Subscription} 0 The new {@link Subscription}. + * @property {object} 1 The full API response. + */ + /** + * @callback CreateSubscriptionCallback + * @param {?Error} err Request error, if any. + * @param {Subscription} Subscription + * @param {object} apiResponse The full API response. + */ + /** + * Options for creating a subscription. + * + * See a [Subscription + * resource](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions). + * + * @typedef {object} CreateSubscriptionRequest + * @property {object} [flowControl] Flow control configurations for + * receiving messages. Note that these options do not persist across + * subscription instances. + * @property {number} [flowControl.maxBytes] The maximum number of bytes + * in un-acked messages to allow before the subscription pauses incoming + * messages. Defaults to 20% of free memory. + * @property {number} [flowControl.maxMessages=Infinity] The maximum number + * of un-acked messages to allow before the subscription pauses incoming + * messages. + * @property {object} [gaxOpts] Request configuration options, outlined + * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. + * @property {number|date} [messageRetentionDuration] Set this to override + * the default duration of 7 days. This value is expected in seconds. + * Acceptable values are in the range of 10 minutes and 7 days. + * @property {string} [pushEndpoint] A URL to a custom endpoint that + * messages should be pushed to. + * @property {boolean} [retainAckedMessages=false] If set, acked messages + * are retained in the subscription's backlog for the length of time + * specified by `options.messageRetentionDuration`. + * @property {ExpirationPolicy} [expirationPolicy] A policy that specifies + * the conditions for this subscription's expiration. + */ + /** + * Create a subscription to a topic. + * + * @see [Subscriptions: create API Documentation]{@link https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/create} + * @see {@link Topic#createSubscription} + * + * @throws {Error} If a Topic instance or topic name is not provided. + * @throws {Error} If a subscription name is not provided. + * + * @param {Topic|string} topic The Topic to create a + * subscription to. + * @param {string} name The name of the subscription. + * @param {CreateSubscriptionRequest} [options] See a + * [Subscription + * resource](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions). + * @param {CreateSubscriptionCallback} [callback] Callback function. + * @returns {Promise} + * + * @example Subscribe to a topic. + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * const topic = 'messageCenter'; + * const name = 'newMessages'; + * + * const callback = function(err, subscription, apiResponse) {}; + * + * pubsub.createSubscription(topic, name, callback); + * + * @example If the callback is omitted, we'll return a + * Promise. pubsub.createSubscription(topic, + * name).then(function(data) { const subscription = data[0]; const apiResponse + * = data[1]; + * }); + */ + createSubscription( + topic: Topic|string, name: string, + optionsOrCallback?: CreateSubscriptionOptions|CreateSubscriptionCallback, + callback?: CreateSubscriptionCallback): + Promise|void { + if (!is.string(topic) && !(topic instanceof Topic)) { + throw new Error('A Topic is required for a new subscription.'); + } + if (!is.string(name)) { + throw new Error('A subscription name is required.'); + } + if (typeof topic === 'string') { + topic = this.topic(topic); + } + let options = typeof optionsOrCallback === 'object' ? + optionsOrCallback : + {} as CreateSubscriptionOptions; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + + // Make a deep copy of options to not pollute caller object. + options = extend(true, {}, options); + + const gaxOpts = options.gaxOpts; + const flowControl = options.flowControl; + delete options.gaxOpts; + delete options.flowControl; + + const metadata = + Subscription.formatMetadata_(options as SubscriptionMetadata); + + let subscriptionCtorOptions = flowControl ? {flowControl} : {}; + subscriptionCtorOptions = Object.assign(subscriptionCtorOptions, metadata); + const subscription = this.subscription(name, subscriptionCtorOptions); + + const reqOpts = Object.assign(metadata, { + topic: topic.name, + name: subscription.name, + }); + + this.request( + { + client: 'SubscriberClient', + method: 'createSubscription', + reqOpts, + gaxOpts, + }, + (err, resp) => { + if (err) { + callback!(err, null, resp); + return; + } + subscription.metadata = resp!; + callback!(null, subscription, resp!); + }); + } + + createTopic(name: string, gaxOpts: CallOptions): Promise; + createTopic( + name: string, gaxOpts: CallOptions, callback?: CreateTopicCallback): void; + createTopic(name: string, callback: CreateTopicCallback): void; + /** + * @typedef {array} CreateTopicResponse + * @property {Topic} 0 The new {@link Topic}. + * @property {object} 1 The full API response. + */ + /** + * @callback CreateTopicCallback + * @param {?Error} err Request error, if any. + * @param {Topic} topic The new {@link Topic}. + * @param {object} apiResponse The full API response. + */ + /** + * Create a topic with the given name. + * + * @see [Topics: create API Documentation]{@link https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create} + * + * @param {string} name Name of the topic. + * @param {object} [gaxOpts] Request configuration options, outlined + * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. + * @param {CreateTopicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * pubsub.createTopic('my-new-topic', function(err, topic, apiResponse) { + * if (!err) { + * // The topic was created successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * pubsub.createTopic('my-new-topic').then(function(data) { + * const topic = data[0]; + * const apiResponse = data[1]; + * }); + */ + createTopic( + name: string, gaxOptsOrCallback?: CallOptions|CreateTopicCallback, + callback?: CreateTopicCallback): Promise|void { + const topic = this.topic(name); + const reqOpts = { + name: topic.name, + }; + + const gaxOpts = + typeof gaxOptsOrCallback === 'object' ? gaxOptsOrCallback : {}; + callback = + typeof gaxOptsOrCallback === 'function' ? gaxOptsOrCallback : callback; + + this.request( + { + client: 'PublisherClient', + method: 'createTopic', + reqOpts, + gaxOpts, + }, + (err, resp) => { + if (err) { + callback!(err, null, resp); + return; + } + topic.metadata = resp!; + callback!(null, topic, resp!); + }); + } + /** + * Determine the appropriate endpoint to use for API requests, first trying + * the local `apiEndpoint` parameter. If the `apiEndpoint` parameter is null + * we try Pub/Sub emulator environment variable (PUBSUB_EMULATOR_HOST), + * otherwise the default JSON API. + * + * @private + */ + determineBaseUrl_() { + const apiEndpoint = this.options.apiEndpoint; + if (!apiEndpoint && !process.env.PUBSUB_EMULATOR_HOST) { + return; + } + const baseUrl = apiEndpoint || process.env.PUBSUB_EMULATOR_HOST; + const leadingProtocol = new RegExp('^https*://'); + const trailingSlashes = new RegExp('/*$'); + const baseUrlParts = baseUrl!.replace(leadingProtocol, '') + .replace(trailingSlashes, '') + .split(':'); + this.options.servicePath = baseUrlParts[0]; + this.options.port = baseUrlParts[1]; + this.options.sslCreds = grpc.credentials.createInsecure(); + this.isEmulator = true; + } + + getSnapshots(option?: PageOptions): Promise; + getSnapshots(callback: GetSnapshotsCallback): void; + getSnapshots(option: PageOptions, callback: GetSnapshotsCallback): void; + /** + * Query object for listing snapshots. + * + * @typedef {object} GetSnapshotsRequest + * @property {boolean} [autoPaginate=true] Have pagination handled + * automatically. + * @property {object} [options.gaxOpts] Request configuration options, outlined + * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. + * @property {number} [options.pageSize] Maximum number of results to return. + * @property {string} [options.pageToken] Page token. + */ + /** + * @typedef {array} GetSnapshotsResponse + * @property {Snapshot[]} 0 Array of {@link Snapshot} instances. + * @property {object} 1 The full API response. + */ + /** + * @callback GetSnapshotsCallback + * @param {?Error} err Request error, if any. + * @param {Snapshot[]} snapshots Array of {@link Snapshot} instances. + * @param {object} apiResponse The full API response. + */ + /** + * Get a list of snapshots. + * + * @param {GetSnapshotsRequest} [query] Query object for listing snapshots. + * @param {GetSnapshotsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * pubsub.getSnapshots(function(err, snapshots) { + * if (!err) { + * // snapshots is an array of Snapshot objects. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * pubsub.getSnapshots().then(function(data) { + * const snapshots = data[0]; + * }); + */ + getSnapshots( + optionsOrCallback?: PageOptions|GetSnapshotsCallback, + callback?: GetSnapshotsCallback): void|Promise { + const self = this; + const options = + typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const reqOpts = Object.assign( + { + project: 'projects/' + this.projectId, + }, + options); + delete reqOpts.gaxOpts; + delete reqOpts.autoPaginate; + const gaxOpts = Object.assign( + { + autoPaginate: options.autoPaginate, + }, + options.gaxOpts); + this.request< + google.pubsub.v1.ISnapshot, google.pubsub.v1.IListSnapshotsResponse>( + { + client: 'SubscriberClient', + method: 'listSnapshots', + reqOpts, + gaxOpts, + }, + (err, rawSnapshots, ...args) => { + let snapshots: Snapshot[]; + + if (rawSnapshots) { + snapshots = rawSnapshots.map(snapshot => { + const snapshotInstance = self.snapshot(snapshot.name!); + snapshotInstance.metadata = snapshot; + return snapshotInstance; + }); + } + + callback!(err, snapshots!, ...args); + }); + } + + getSubscriptions(options?: GetSubscriptionsOptions): + Promise; + getSubscriptions(callback: GetSubscriptionsCallback): void; + getSubscriptions( + options: GetSubscriptionsOptions, + callback: GetSubscriptionsCallback): void; + /** + * Query object for listing subscriptions. + * + * @typedef {object} GetSubscriptionsRequest + * @property {boolean} [autoPaginate=true] Have pagination handled + * automatically. + * @property {object} [options.gaxOpts] Request configuration options, outlined + * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. + * @property {number} [options.pageSize] Maximum number of results to return. + * @property {string} [options.pageToken] Page token. + * @param {string|Topic} options.topic - The name of the topic to + * list subscriptions from. + */ + /** + * @typedef {array} GetSubscriptionsResponse + * @property {Subscription[]} 0 Array of {@link Subscription} instances. + * @property {object} 1 The full API response. + */ + /** + * @callback GetSubscriptionsCallback + * @param {?Error} err Request error, if any. + * @param {Subscription[]} subscriptions Array of {@link Subscription} instances. + * @param {object} apiResponse The full API response. + */ + /** + * Get a list of the subscriptions registered to all of your project's topics. + * You may optionally provide a query object as the first argument to + * customize the response. + * + * Your provided callback will be invoked with an error object if an API error + * occurred or an array of {@link Subscription} objects. + * + * To get subscriptions for a topic, see {@link Topic}. + * + * @see [Subscriptions: list API Documentation]{@link https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/list} + * + * @param {GetSubscriptionsRequest} [query] Query object for listing subscriptions. + * @param {GetSubscriptionsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * pubsub.getSubscriptions(function(err, subscriptions) { + * if (!err) { + * // subscriptions is an array of Subscription objects. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * pubsub.getSubscriptions().then(function(data) { + * const subscriptions = data[0]; + * }); + */ + getSubscriptions( + optionsOrCallback?: GetSubscriptionsOptions|GetSubscriptionsCallback, + callback?: GetSubscriptionsCallback): + void|Promise { + const self = this; + const options = + typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + + let topic = options.topic; + if (topic) { + if (!(topic instanceof Topic)) { + topic = this.topic(topic); + } + return topic.getSubscriptions( + options, callback as GetTopicSubscriptionsCallback); + } + const reqOpts = Object.assign({}, options) as + google.pubsub.v1.IListSubscriptionsRequest; + reqOpts.project = 'projects/' + this.projectId; + + delete (reqOpts as GetSubscriptionsOptions).gaxOpts; + delete (reqOpts as GetSubscriptionsOptions).autoPaginate; + + const gaxOpts = Object.assign( + { + autoPaginate: options.autoPaginate, + }, + options.gaxOpts); + + this.request< + google.pubsub.v1.ISubscription, + google.pubsub.v1.IListSubscriptionsResponse>( + { + client: 'SubscriberClient', + method: 'listSubscriptions', + reqOpts, + gaxOpts, + }, + (err, rawSubs, ...args) => { + let subscriptions: Subscription[]; + + if (rawSubs) { + subscriptions = rawSubs.map(sub => { + const subscriptionInstance = self.subscription(sub.name!); + subscriptionInstance.metadata = sub; + return subscriptionInstance; + }); + } + + (callback as GetAllSubscriptionsCallback)( + err, subscriptions!, ...args); + }); + } + + getTopics(options: PageOptions): Promise; + getTopics(callback: GetTopicsCallback): void; + getTopics(options: PageOptions, callback: GetTopicsCallback): void; + /** + * Query object for listing topics. + * + * @typedef {object} GetTopicsRequest + * @property {boolean} [autoPaginate=true] Have pagination handled + * automatically. + * @property {object} [options.gaxOpts] Request configuration options, outlined + * here: https://googleapis.github.io/gax-nodejs/CallSettings.html. + * @property {number} [options.pageSize] Maximum number of results to return. + * @property {string} [options.pageToken] Page token. + */ + /** + * @typedef {array} GetTopicsResponse + * @property {Topic[]} 0 Array of {@link Topic} instances. + * @property {object} 1 The full API response. + */ + /** + * @callback GetTopicsCallback + * @param {?Error} err Request error, if any. + * @param {Topic[]} topics Array of {@link Topic} instances. + * @param {object} apiResponse The full API response. + */ + /** + * Get a list of the topics registered to your project. You may optionally + * provide a query object as the first argument to customize the response. + * + * @see [Topics: list API Documentation]{@link https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/list} + * + * @param {GetTopicsRequest} [query] Query object for listing topics. + * @param {GetTopicsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * pubsub.getTopics(function(err, topics) { + * if (!err) { + * // topics is an array of Topic objects. + * } + * }); + * + * //- + * // Customize the query. + * //- + * pubsub.getTopics({ + * pageSize: 3 + * }, function(err, topics) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * pubsub.getTopics().then(function(data) { + * const topics = data[0]; + * }); + */ + getTopics( + optionsOrCallback?: PageOptions|GetTopicsCallback, + callback?: GetTopicsCallback): void|Promise { + const self = this; + const options = + typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + + const reqOpts = Object.assign( + { + project: 'projects/' + this.projectId, + }, + options); + delete reqOpts.gaxOpts; + delete reqOpts.autoPaginate; + const gaxOpts = Object.assign( + { + autoPaginate: options.autoPaginate, + }, + options.gaxOpts); + this.request( + { + client: 'PublisherClient', + method: 'listTopics', + reqOpts, + gaxOpts, + }, + (err, rawTopics, ...args) => { + let topics: Topic[]; + + if (rawTopics) { + topics = rawTopics.map(topic => { + const topicInstance = self.topic(topic.name); + topicInstance.metadata = topic; + return topicInstance; + }); + } + + callback!(err, topics!, ...args); + }); + } + /** + * Callback function to PubSub.getClient_(). + * @private + * @callback GetClientCallback + * @param err - Error, if any. + * @param gaxClient - The gax client specified in RequestConfig.client. + * Typed any since it's importing Javascript source. + */ + /** + * Get the PubSub client object. + * + * @private + * + * @param {object} config Configuration object. + * @param {object} config.gaxOpts GAX options. + * @param {function} config.method The gax method to call. + * @param {object} config.reqOpts Request options. + * @param {function} [callback] The callback function. + */ + getClient_(config: GetClientConfig, callback: GetClientCallback) { + const hasProjectId = + this.projectId && this.projectId !== PROJECT_ID_PLACEHOLDER; + if (!hasProjectId && !this.isEmulator) { + this.auth.getProjectId((err, projectId) => { + if (err) { + callback(err); + return; + } + this.projectId = projectId!; + this.options.projectId = projectId!; + + this.getClient_(config, callback); + }); + return; + } + let gaxClient = this.api[config.client]; + if (!gaxClient) { + // Lazily instantiate client. + gaxClient = new v1[config.client](this.options) as gax.ClientStub; + this.api[config.client] = gaxClient; + } + callback(null, gaxClient); + } + /** + * Funnel all API requests through this method, to be sure we have a project + * ID. + * + * @private + * + * @param {object} config Configuration object. + * @param {object} config.gaxOpts GAX options. + * @param {function} config.method The gax method to call. + * @param {object} config.reqOpts Request options. + * @param {function} [callback] The callback function. + */ + request(config: RequestConfig, callback: RequestCallback) { + const self = this; + this.getClient_(config, (err, client) => { + if (err) { + callback(err); + return; + } + let reqOpts = extend(true, {}, config.reqOpts); + reqOpts = replaceProjectIdToken(reqOpts, self.projectId); + client![config.method](reqOpts, config.gaxOpts, callback); + }); + } + /** + * Create a Snapshot object. See {@link Subscription#createSnapshot} to + * create a snapshot. + * + * @throws {Error} If a name is not provided. + * + * @param {string} name The name of the snapshot. + * @returns {Snapshot} A {@link Snapshot} instance. + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * const snapshot = pubsub.snapshot('my-snapshot'); + */ + snapshot(name: string): Snapshot { + if (!is.string(name)) { + throw new Error('You must supply a valid name for the snapshot.'); + } + return new Snapshot(this, name); + } + /** + * Create a Subscription object. This command by itself will not run any API + * requests. You will receive a {@link Subscription} object, + * which will allow you to interact with a subscription. + * + * @throws {Error} If subscription name is omitted. + * + * @param {string} name Name of the subscription. + * @param {SubscriberOptions} [options] Subscription options. + * @returns {Subscription} A {@link Subscription} instance. + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * const subscription = pubsub.subscription('my-subscription'); + * + * // Register a listener for `message` events. + * subscription.on('message', function(message) { + * // Called every time a message is received. + * // message.id = ID of the message. + * // message.ackId = ID used to acknowledge the message receival. + * // message.data = Contents of the message. + * // message.attributes = Attributes of the message. + * // message.publishTime = Date when Pub/Sub received the message. + * }); + */ + subscription(name: string, options?: SubscriptionOptions): Subscription { + if (!name) { + throw new Error('A name must be specified for a subscription.'); + } + return new Subscription(this, name, options); + } + /** + * Create a Topic object. See {@link PubSub#createTopic} to create a topic. + * + * @throws {Error} If a name is not provided. + * + * @param {string} name The name of the topic. + * @returns {Topic} A {@link Topic} instance. + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * const topic = pubsub.topic('my-topic'); + */ + topic(name: string, options?: PublishOptions): Topic { + if (!name) { + throw new Error('A name must be specified for a topic.'); + } + return new Topic(this, name, options); + } +} + +/** + * Get a list of the {@link Snapshot} objects as a readable object stream. + * + * @method PubSub#getSnapshotsStream + * @param {GetSnapshotsRequest} [options] Configuration object. See + * {@link PubSub#getSnapshots} for a complete list of options. + * @returns {ReadableStream} A readable stream of {@link Snapshot} instances. + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * pubsub.getSnapshotsStream() + * .on('error', console.error) + * .on('data', function(snapshot) { + * // snapshot is a Snapshot object. + * }) + * .on('end', function() { + * // All snapshots retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * pubsub.getSnapshotsStream() + * .on('data', function(snapshot) { + * this.end(); + * }); + */ + +/** + * Get a list of the {@link Subscription} objects registered to all of + * your project's topics as a readable object stream. + * + * @method PubSub#getSubscriptionsStream + * @param {GetSubscriptionsRequest} [options] Configuration object. See + * {@link PubSub#getSubscriptions} for a complete list of options. + * @returns {ReadableStream} A readable stream of {@link Subscription} instances. + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * pubsub.getSubscriptionsStream() + * .on('error', console.error) + * .on('data', function(subscription) { + * // subscription is a Subscription object. + * }) + * .on('end', function() { + * // All subscriptions retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * pubsub.getSubscriptionsStream() + * .on('data', function(subscription) { + * this.end(); + * }); + */ + +/** + * Get a list of the {module:pubsub/topic} objects registered to your project as + * a readable object stream. + * + * @method PubSub#getTopicsStream + * @param {GetTopicsRequest} [options] Configuration object. See + * {@link PubSub#getTopics} for a complete list of options. + * @returns {ReadableStream} A readable stream of {@link Topic} instances. + * + * @example + * const {PubSub} = require('@google-cloud/pubsub'); + * const pubsub = new PubSub(); + * + * pubsub.getTopicsStream() + * .on('error', console.error) + * .on('data', function(topic) { + * // topic is a Topic object. + * }) + * .on('end', function() { + * // All topics retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * pubsub.getTopicsStream() + * .on('data', function(topic) { + * this.end(); + * }); + */ + +/*! Developer Documentation + * + * These methods can be agto-paginated. + */ +paginator.extend(PubSub, ['getSnapshots', 'getSubscriptions', 'getTopics']); + +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +promisifyAll(PubSub, { + exclude: ['request', 'snapshot', 'subscription', 'topic'], +}); diff --git a/src/snapshot.ts b/src/snapshot.ts index 164827500..1f9b8aa82 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -18,8 +18,7 @@ import {promisifyAll} from '@google-cloud/promisify'; import {CallOptions} from 'google-gax'; import {google} from '../proto/pubsub'; - -import {EmptyCallback, EmptyResponse, RequestCallback, ResourceCallback} from '.'; +import {EmptyCallback, EmptyResponse, RequestCallback, ResourceCallback} from './pubsub'; import {PubSub} from './index'; import {Subscription} from './subscription'; import * as util from './util'; diff --git a/src/subscription.ts b/src/subscription.ts index a1a6ec69d..94d0234a7 100644 --- a/src/subscription.ts +++ b/src/subscription.ts @@ -23,7 +23,7 @@ import * as snakeCase from 'lodash.snakecase'; import {google} from '../proto/pubsub'; -import {EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, Omit, PubSub, RequestCallback, ResourceCallback} from '.'; +import {EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, Omit, PubSub, RequestCallback, ResourceCallback} from './pubsub'; import {IAM} from './iam'; import {FlowControlOptions} from './lease-manager'; import {CreateSnapshotCallback, CreateSnapshotResponse, SeekCallback, SeekResponse, Snapshot} from './snapshot'; diff --git a/src/topic.ts b/src/topic.ts index 906aa88ff..e400fc17d 100644 --- a/src/topic.ts +++ b/src/topic.ts @@ -22,7 +22,7 @@ import {Readable} from 'stream'; import {google} from '../proto/pubsub'; -import {EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, ObjectStream, PagedResponse, PageOptions, PubSub, RequestCallback, ResourceCallback} from '.'; +import {EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, ObjectStream, PagedResponse, PageOptions, PubSub, RequestCallback, ResourceCallback} from './pubsub'; import {IAM} from './iam'; import {Attributes, PublishCallback, Publisher, PublishOptions} from './publisher'; import {CreateSubscriptionCallback, CreateSubscriptionOptions, CreateSubscriptionResponse, Subscription, SubscriptionOptions} from './subscription'; diff --git a/test/iam.ts b/test/iam.ts index 67d32ec50..b5b9f6ff5 100644 --- a/test/iam.ts +++ b/test/iam.ts @@ -18,7 +18,7 @@ import * as promisify from '@google-cloud/promisify'; import * as assert from 'assert'; import * as proxyquire from 'proxyquire'; -import {PubSub, RequestConfig} from '../src'; +import {PubSub, RequestConfig} from '../src/pubsub'; import * as iamTypes from '../src/iam'; import * as util from '../src/util'; diff --git a/test/index.ts b/test/index.ts index 34a9c30f3..4680592e3 100644 --- a/test/index.ts +++ b/test/index.ts @@ -149,7 +149,7 @@ describe('PubSub', () => { before(() => { delete process.env.PUBSUB_EMULATOR_HOST; - PubSub = proxyquire('../src', { + PubSub = proxyquire('../src/pubsub', { '@google-cloud/paginator': { paginator: fakePaginator, }, diff --git a/test/snapshot.ts b/test/snapshot.ts index fe7fd7e3a..1f6e5c84c 100644 --- a/test/snapshot.ts +++ b/test/snapshot.ts @@ -19,8 +19,9 @@ import * as assert from 'assert'; import * as proxyquire from 'proxyquire'; import * as sinon from 'sinon'; -import {PubSub, RequestConfig, Subscription} from '../src'; +import {PubSub, RequestConfig} from '../src/pubsub'; import * as snapTypes from '../src/snapshot'; +import {Subscription} from '../src/subscription'; import * as util from '../src/util'; let promisified = false; diff --git a/test/subscriber.ts b/test/subscriber.ts index 4204d1277..761548fb6 100644 --- a/test/subscriber.ts +++ b/test/subscriber.ts @@ -21,7 +21,7 @@ import * as proxyquire from 'proxyquire'; import * as sinon from 'sinon'; import {PassThrough} from 'stream'; import * as uuid from 'uuid'; -import {Subscription} from '../src'; +import {Subscription} from '../src/subscription'; import {HistogramOptions} from '../src/histogram'; import {FlowControlOptions} from '../src/lease-manager'; import {BatchOptions} from '../src/message-queues'; diff --git a/test/subscription.ts b/test/subscription.ts index 39843883e..61a860c89 100644 --- a/test/subscription.ts +++ b/test/subscription.ts @@ -23,7 +23,7 @@ import * as proxyquire from 'proxyquire'; import * as sinon from 'sinon'; import {google} from '../proto/pubsub'; -import {ExistsCallback, RequestCallback, RequestConfig} from '../src'; +import {ExistsCallback, RequestCallback, RequestConfig} from '../src/pubsub'; import {SeekCallback, Snapshot} from '../src/snapshot'; import {Message, SubscriberOptions} from '../src/subscriber'; import {CreateSubscriptionCallback, CreateSubscriptionOptions, GetSubscriptionMetadataCallback, Subscription, SubscriptionMetadata} from '../src/subscription'; diff --git a/test/topic.ts b/test/topic.ts index d130aae74..b35f4919a 100644 --- a/test/topic.ts +++ b/test/topic.ts @@ -22,7 +22,7 @@ import * as proxyquire from 'proxyquire'; import * as sinon from 'sinon'; import {google} from '../proto/pubsub'; -import {ExistsCallback, RequestCallback, RequestConfig} from '../src'; +import {ExistsCallback, RequestCallback, RequestConfig} from '../src/pubsub'; import {CreateSubscriptionCallback, CreateSubscriptionOptions, Subscription, SubscriptionOptions} from '../src/subscription'; import {CreateTopicCallback, GetTopicMetadataCallback, Topic} from '../src/topic'; import * as util from '../src/util'; From af514cd0f2b0c41990623435ad2108514d11a710 Mon Sep 17 00:00:00 2001 From: Dave Gramlich Date: Sat, 2 Mar 2019 14:18:15 -0500 Subject: [PATCH 2/2] fixy --- src/snapshot.ts | 3 ++- src/subscription.ts | 2 +- src/topic.ts | 2 +- test/iam.ts | 2 +- test/subscriber.ts | 3 ++- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/snapshot.ts b/src/snapshot.ts index 1f9b8aa82..cfacb29ac 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -18,8 +18,9 @@ import {promisifyAll} from '@google-cloud/promisify'; import {CallOptions} from 'google-gax'; import {google} from '../proto/pubsub'; -import {EmptyCallback, EmptyResponse, RequestCallback, ResourceCallback} from './pubsub'; + import {PubSub} from './index'; +import {EmptyCallback, EmptyResponse, RequestCallback, ResourceCallback} from './pubsub'; import {Subscription} from './subscription'; import * as util from './util'; diff --git a/src/subscription.ts b/src/subscription.ts index 94d0234a7..838e38e35 100644 --- a/src/subscription.ts +++ b/src/subscription.ts @@ -23,9 +23,9 @@ import * as snakeCase from 'lodash.snakecase'; import {google} from '../proto/pubsub'; -import {EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, Omit, PubSub, RequestCallback, ResourceCallback} from './pubsub'; import {IAM} from './iam'; import {FlowControlOptions} from './lease-manager'; +import {EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, Omit, PubSub, RequestCallback, ResourceCallback} from './pubsub'; import {CreateSnapshotCallback, CreateSnapshotResponse, SeekCallback, SeekResponse, Snapshot} from './snapshot'; import {Message, Subscriber, SubscriberOptions} from './subscriber'; import {Topic} from './topic'; diff --git a/src/topic.ts b/src/topic.ts index e400fc17d..9f625b9b1 100644 --- a/src/topic.ts +++ b/src/topic.ts @@ -22,9 +22,9 @@ import {Readable} from 'stream'; import {google} from '../proto/pubsub'; -import {EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, ObjectStream, PagedResponse, PageOptions, PubSub, RequestCallback, ResourceCallback} from './pubsub'; import {IAM} from './iam'; import {Attributes, PublishCallback, Publisher, PublishOptions} from './publisher'; +import {EmptyCallback, EmptyResponse, ExistsCallback, ExistsResponse, ObjectStream, PagedResponse, PageOptions, PubSub, RequestCallback, ResourceCallback} from './pubsub'; import {CreateSubscriptionCallback, CreateSubscriptionOptions, CreateSubscriptionResponse, Subscription, SubscriptionOptions} from './subscription'; import * as util from './util'; diff --git a/test/iam.ts b/test/iam.ts index b5b9f6ff5..830122e02 100644 --- a/test/iam.ts +++ b/test/iam.ts @@ -18,8 +18,8 @@ import * as promisify from '@google-cloud/promisify'; import * as assert from 'assert'; import * as proxyquire from 'proxyquire'; -import {PubSub, RequestConfig} from '../src/pubsub'; import * as iamTypes from '../src/iam'; +import {PubSub, RequestConfig} from '../src/pubsub'; import * as util from '../src/util'; let promisified = false; diff --git a/test/subscriber.ts b/test/subscriber.ts index 761548fb6..5d40c29a7 100644 --- a/test/subscriber.ts +++ b/test/subscriber.ts @@ -21,12 +21,13 @@ import * as proxyquire from 'proxyquire'; import * as sinon from 'sinon'; import {PassThrough} from 'stream'; import * as uuid from 'uuid'; -import {Subscription} from '../src/subscription'; + import {HistogramOptions} from '../src/histogram'; import {FlowControlOptions} from '../src/lease-manager'; import {BatchOptions} from '../src/message-queues'; import {MessageStreamOptions} from '../src/message-stream'; import * as s from '../src/subscriber'; +import {Subscription} from '../src/subscription'; const stubs = new Map();