Skip to content

Commit

Permalink
fix!: keyToLegacyUrlsafe is now an async method (#496)
Browse files Browse the repository at this point in the history
  • Loading branch information
laljikanjareeya authored and crwilcox committed Nov 14, 2019
1 parent 6c8cc74 commit bbd1ebe
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 16 deletions.
92 changes: 82 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {entity} from './entity';
import {Query} from './query';
import {DatastoreRequest} from './request';
import {Transaction} from './transaction';
import {promisifyAll} from '@google-cloud/promisify';

const {grpc} = new GrpcClient();

Expand Down Expand Up @@ -730,6 +731,16 @@ class Datastore extends DatastoreRequest {
return Datastore.isKey(value);
}

keyToLegacyUrlSafe(key: entity.Key, locationPrefix?: string): Promise<string>;
keyToLegacyUrlSafe(
key: entity.Key,
callback: KeyToLegacyUrlSafeCallback
): void;
keyToLegacyUrlSafe(
key: entity.Key,
locationPrefix: string,
callback: KeyToLegacyUrlSafeCallback
): void;
/**
* Helper to create a URL safe key.
*
Expand All @@ -744,26 +755,62 @@ class Datastore extends DatastoreRequest {
* The location prefix of an App Engine project ID.
* Often this value is 's~', but may also be 'e~', or other location prefixes
* currently unknown.
* @returns {string} base64 endocded urlsafe key.
* @param {function} callback The callback function.
* @param {?error} callback.err An error returned while making this request
* @param {string} callback.urlSafeKey A Base64-encoded URL-safe key.
*
* @example
* const {Datastore} = require('@google-cloud/datastore');
* const datastore = new Datastore();
* const key = datastore.key(['Company', 'Google']);
*
* datastore.keyToLegacyUrlsafe(key) //ag9ncmFzcy1jbHVtcC00NzlyEwsSB0NvbXBhbnkiBkdvb2dsZQw
* datastore.keyToLegacyUrlSafe(key, (err, urlSafeKey) => {
* if (err) {
* // Error handling omitted.
* }
* console.log(urlSafeKey);
* });
*
* @example
* <caption>Create a complete url safe key using location prefix </caption>
* const {Datastore} = require('@google-cloud/datastore');
* const datastore = new Datastore();
* const key = datastore.key(['Task', 123]);
* //-
* // Create a complete URL-safe key using a location prefix.
* //-
* const locationPrefix = 's~';
*
* datastore.keyToLegacyUrlsafe(key, locationPrefix) //ahFzfmdyYXNzLWNsdW1wLTQ3OXIKCxIEVGFzaxh7DA
* datastore.keyToLegacyUrlSafe(key, locationPrefix, (err, urlSafeKey) => {
* if (err) {
* // Error handling omitted.
* }
* console.log(urlSafeKey);
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* datastore.keyToLegacyUrlSafe(key).then((data) => {
* const urlSafeKey = data[0];
* console.log(urlSafeKey);
* });
*/
keyToLegacyUrlsafe(key: entity.Key, locationPrefix?: string): string {
return urlSafeKey.legacyEncode(this.projectId, key, locationPrefix);
keyToLegacyUrlSafe(
key: entity.Key,
locationPrefixOrCallback?: string | KeyToLegacyUrlSafeCallback,
callback?: KeyToLegacyUrlSafeCallback
): Promise<string> | void {
const locationPrefix =
typeof locationPrefixOrCallback === 'string'
? locationPrefixOrCallback
: '';
callback =
typeof locationPrefixOrCallback === 'function'
? locationPrefixOrCallback
: callback;
this.auth.getProjectId((err, projectId) => {
if (err) {
callback!(err);
return;
}
callback!(null, urlSafeKey.legacyEncode(projectId!, key, locationPrefix));
});
}

/**
Expand Down Expand Up @@ -870,6 +917,27 @@ class Datastore extends DatastoreRequest {
Transaction = Transaction;
}

/*! Developer Documentation
*
* All async methods (except for streams) will return a Promise in the event
* that a callback is omitted.
*/
promisifyAll(Datastore, {
exclude: [
'double',
'isDouble',
'geoPoint',
'isGeoPoint',
'int',
'isInt',
'createQuery',
'key',
'isKey',
'keyFromLegacyUrlsafe',
'transaction',
],
});

export {Datastore};

/**
Expand Down Expand Up @@ -932,3 +1000,7 @@ export interface DatastoreOptions extends GoogleAuthOptions {
apiEndpoint?: string;
sslCreds?: ChannelCredentials;
}

export interface KeyToLegacyUrlSafeCallback {
(err?: Error | null, urlSafeKey?: string): void;
}
46 changes: 40 additions & 6 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,15 +625,49 @@ describe('Datastore', () => {
});
});

describe('keyToLegacyUrlsafe', () => {
it('should convert key to url safe base64 string', () => {
describe('keyToLegacyUrlSafe', () => {
it('should convert key to URL-safe base64 string', () => {
const key = new entity.Key({
path: ['Task', 'Test'],
});
assert.strictEqual(
datastore.keyToLegacyUrlsafe(key),
'agpwcm9qZWN0LWlkcg4LEgRUYXNrIgRUZXN0DA'
);
const base64EndocdedUrlSafeKey = 'agpwcm9qZWN0LWlkcg4LEgRUYXNrIgRUZXN0DA';
// tslint:disable-next-line: no-any
(datastore.auth as any).getProjectId = (callback: Function) => {
callback(null, 'project-id');
};
datastore.keyToLegacyUrlSafe(key, (err, urlSafeKey) => {
assert.ifError(err);
assert.strictEqual(urlSafeKey, base64EndocdedUrlSafeKey);
});
});

it('should convert key to URL-safe base64 string with location prefix', () => {
const key = new entity.Key({
path: ['Task', 'Test'],
});
const locationPrefix = 's~';
const base64EndocdedUrlSafeKey =
'agxzfnByb2plY3QtaWRyDgsSBFRhc2siBFRlc3QM';
// tslint:disable-next-line: no-any
(datastore.auth as any).getProjectId = (callback: Function) => {
callback(null, 'project-id');
};
datastore.keyToLegacyUrlSafe(key, locationPrefix, (err, urlSafeKey) => {
assert.ifError(err);
assert.strictEqual(urlSafeKey, base64EndocdedUrlSafeKey);
});
});

it('should not return URL-safe key to user if auth.getProjectId errors', () => {
const error = new Error('Error.');
// tslint:disable-next-line: no-any
(datastore.auth as any).getProjectId = (callback: Function) => {
callback(error);
};
datastore.keyToLegacyUrlSafe({} as entity.Key, (err, urlSafeKey) => {
assert.strictEqual(err, error);
assert.strictEqual(urlSafeKey, undefined);
});
});
});

Expand Down

0 comments on commit bbd1ebe

Please sign in to comment.