Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit 58fad6d

Browse files
authored
feat: Convenient gs:// URI retrieval (#1987)
* feat: Convenient `gs://` URI retrieval * refactor: `uri` -> `cloudStorageURI`
1 parent 8813369 commit 58fad6d

4 files changed

Lines changed: 67 additions & 2 deletions

File tree

src/bucket.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,27 @@ class Bucket extends ServiceObject {
10481048
this.instancePreconditionOpts = options?.preconditionOpts;
10491049
}
10501050

1051+
/**
1052+
* The bucket's Cloud Storage URI (`gs://`)
1053+
*
1054+
* @example
1055+
* ```ts
1056+
* const {Storage} = require('@google-cloud/storage');
1057+
* const storage = new Storage();
1058+
* const bucket = storage.bucket('my-bucket');
1059+
*
1060+
* // `gs://my-bucket`
1061+
* const href = bucket.cloudStorageURI.href;
1062+
* ```
1063+
*/
1064+
get cloudStorageURI(): URL {
1065+
const uri = new URL('gs://');
1066+
1067+
uri.host = this.name;
1068+
1069+
return uri;
1070+
}
1071+
10511072
addLifecycleRule(
10521073
rule: LifecycleRule,
10531074
options?: AddLifecycleRuleOptions
@@ -4149,7 +4170,7 @@ paginator.extend(Bucket, 'getFiles');
41494170
* that a callback is omitted.
41504171
*/
41514172
promisifyAll(Bucket, {
4152-
exclude: ['request', 'file', 'notification'],
4173+
exclude: ['cloudStorageURI', 'request', 'file', 'notification'],
41534174
});
41544175

41554176
/**

src/file.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,28 @@ class File extends ServiceObject<File> {
883883
this.instancePreconditionOpts = options?.preconditionOpts;
884884
}
885885

886+
/**
887+
* The object's Cloud Storage URI (`gs://`)
888+
*
889+
* @example
890+
* ```ts
891+
* const {Storage} = require('@google-cloud/storage');
892+
* const storage = new Storage();
893+
* const bucket = storage.bucket('my-bucket');
894+
* const file = bucket.file('image.png');
895+
*
896+
* // `gs://my-bucket/image.png`
897+
* const href = file.cloudStorageURI.href;
898+
* ```
899+
*/
900+
get cloudStorageURI(): URL {
901+
const uri = this.bucket.cloudStorageURI;
902+
903+
uri.pathname = this.name;
904+
905+
return uri;
906+
}
907+
886908
/**
887909
* A helper method for determining if a request should be retried based on preconditions.
888910
* This should only be used for methods where the idempotency is determined by
@@ -2415,7 +2437,7 @@ class File extends ServiceObject<File> {
24152437
* @param {boolean} [config.virtualHostedStyle=false] Use virtual hosted-style
24162438
* URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style
24172439
* ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs
2418-
* should generally be preferred instaed of path-style URL.
2440+
* should generally be preferred instead of path-style URL.
24192441
* Currently defaults to `false` for path-style, although this may change in a
24202442
* future major-version release.
24212443
* @param {string} [config.bucketBoundHostname] The bucket-bound hostname to return in
@@ -3855,6 +3877,7 @@ class File extends ServiceObject<File> {
38553877
*/
38563878
promisifyAll(File, {
38573879
exclude: [
3880+
'cloudStorageURI',
38583881
'publicUrl',
38593882
'request',
38603883
'save',

test/bucket.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ const fakePromisify = {
113113

114114
promisified = true;
115115
assert.deepStrictEqual(options.exclude, [
116+
'cloudStorageURI',
116117
'request',
117118
'file',
118119
'notification',
@@ -443,6 +444,15 @@ describe('Bucket', () => {
443444
});
444445
});
445446

447+
describe('cloudStorageURI', () => {
448+
it('should return the appropriate `gs://` URI', () => {
449+
const bucket = new Bucket(STORAGE, BUCKET_NAME);
450+
451+
assert(bucket.cloudStorageURI instanceof URL);
452+
assert.equal(bucket.cloudStorageURI.host, BUCKET_NAME);
453+
});
454+
});
455+
446456
describe('addLifecycleRule', () => {
447457
beforeEach(() => {
448458
bucket.getMetadata = (callback: GetBucketMetadataCallback) => {

test/file.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ const fakePromisify = {
9292

9393
promisified = true;
9494
assert.deepStrictEqual(options.exclude, [
95+
'cloudStorageURI',
9596
'publicUrl',
9697
'request',
9798
'save',
@@ -471,6 +472,16 @@ describe('File', () => {
471472
});
472473
});
473474

475+
describe('cloudStorageURI', () => {
476+
it('should return the appropriate `gs://` URI', () => {
477+
const file = new File(BUCKET, FILE_NAME);
478+
479+
assert(file.cloudStorageURI instanceof URL);
480+
assert.equal(file.cloudStorageURI.host, BUCKET.name);
481+
assert.equal(file.cloudStorageURI.pathname, `/${FILE_NAME}`);
482+
});
483+
});
484+
474485
describe('copy', () => {
475486
it('should throw if no destination is provided', () => {
476487
assert.throws(() => {

0 commit comments

Comments
 (0)