Skip to content

Commit d749e13

Browse files
committed
Feat(storage): add Object Contexts samples and system tests
- Add `setObjectContexts.js` to demonstrate CRUD and deletion of contexts. - Add `getObjectContexts.js` to show retrieval of structured metadata. - Add `listObjectsWithContextFilter.js` to demonstrate server-side filtering. - Implement comprehensive system tests in `files.test.js` covering presence, absence (-), and existence (:) filter operators. - Ensure samples use correct 'contexts' field with 'custom' map structure.
1 parent ed87c9f commit d749e13

4 files changed

Lines changed: 413 additions & 0 deletions

File tree

storage/getObjectContexts.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// sample-metadata:
18+
// title: Get Object Contexts
19+
// description: Retrieves the structured Object Contexts from an object.
20+
// usage: node getObjectContexts.js <BUCKET_NAME> <FILE_NAME>
21+
22+
/**
23+
* This application demonstrates how to retrieve the 'contexts' field from a file
24+
* in Google Cloud Storage.
25+
*/
26+
27+
function main(bucketName = 'my-bucket', fileName = 'test.txt') {
28+
// [START storage_get_object_contexts]
29+
/**
30+
* TODO(developer): Uncomment the following lines before running the sample.
31+
*/
32+
// The ID of your GCS bucket
33+
// const bucketName = 'your-unique-bucket-name';
34+
35+
// The ID of your GCS file
36+
// const fileName = 'your-file-name';
37+
38+
// Imports the Google Cloud client library
39+
const {Storage} = require('@google-cloud/storage');
40+
41+
// Creates a client
42+
const storage = new Storage();
43+
44+
async function getObjectContexts() {
45+
// Gets the metadata for the file
46+
const [metadata] = await storage
47+
.bucket(bucketName)
48+
.file(fileName)
49+
.getMetadata();
50+
51+
// Contexts are stored in metadata.contexts.custom
52+
if (metadata.contexts && metadata.contexts.custom) {
53+
console.log(`Object Contexts for ${fileName}:`);
54+
55+
// Iterate through the custom contexts to show values and timestamps
56+
for (const [key, details] of Object.entries(metadata.contexts.custom)) {
57+
console.log(`- Key: ${key}`);
58+
console.log(` Value: ${details.value}`);
59+
console.log(` Created: ${details.createTime}`);
60+
console.log(` Updated: ${details.updateTime}`);
61+
}
62+
} else {
63+
console.log(`No Object Contexts found for ${fileName}.`);
64+
}
65+
}
66+
67+
getObjectContexts().catch(console.error);
68+
// [END storage_get_object_contexts]
69+
}
70+
71+
main(...process.argv.slice(2));

storage/listObjectContexts.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// sample-metadata:
18+
// title: List Objects with Context Filter
19+
// description: Lists objects in a bucket that match specific custom contexts.
20+
// usage: node listObjectsWithContextFilter.js <BUCKET_NAME>
21+
22+
/**
23+
* This application demonstrates how to list objects in a bucket while filtering
24+
* by their custom 'contexts' metadata.
25+
*/
26+
27+
function main(bucketName = 'my-bucket') {
28+
// [START storage_list_object_contexts]
29+
/**
30+
* TODO(developer): Uncomment the following lines before running the sample.
31+
*/
32+
// The ID of your GCS bucket
33+
// const bucketName = 'your-unique-bucket-name';
34+
35+
// Imports the Google Cloud client library
36+
const {Storage} = require('@google-cloud/storage');
37+
38+
// Creates a client
39+
const storage = new Storage();
40+
41+
async function listObjectContexts() {
42+
// Define the filter for contexts.
43+
const bucket = storage.bucket(bucketName);
44+
45+
/**
46+
* List any object that has a context with the specified key attached.
47+
* Syntax: contexts."<key>"="<value>"
48+
*/
49+
const filterByValue = 'contexts."priority"="high"';
50+
const [filesByValue] = await bucket.getFiles({
51+
filter: filterByValue,
52+
});
53+
54+
console.log(`\nFiles matching filter [${filterByValue}]:`);
55+
filesByValue.forEach(file => console.log(` - ${file.name}`));
56+
57+
/**
58+
* List any object that has a context with the specified key attached.
59+
* Syntax: contexts."<key>":*
60+
*/
61+
const filterByExistence = 'contexts."team-owner":*';
62+
const [filesWithKey] = await bucket.getFiles({
63+
filter: filterByExistence,
64+
});
65+
66+
console.log(
67+
`\nFiles with the "team-owner" context key [${filterByExistence}]:`
68+
);
69+
filesWithKey.forEach(file => console.log(` - ${file.name}`));
70+
71+
/**
72+
* List any object that does not have a context with the specified key and value attached.
73+
* Syntax: -contexts."<key>"="<value>"
74+
*/
75+
const absenceOfValuePair = '-contexts."priority"="high"';
76+
const [filesNoHighPriority] = await bucket.getFiles({
77+
filter: absenceOfValuePair,
78+
});
79+
80+
console.log(
81+
`\nFiles matching absence of value pair [${absenceOfValuePair}]:`
82+
);
83+
filesNoHighPriority.forEach(file => console.log(` - ${file.name}`));
84+
85+
/**
86+
* List any object that that does not have a context with the specified key attached.
87+
* Syntax: -contexts."<key>":*
88+
*/
89+
const absenceOfKey = '-contexts."team-owner":*';
90+
const [filesNoTeamOwner] = await bucket.getFiles({
91+
filter: absenceOfKey,
92+
});
93+
94+
console.log(
95+
`\nFiles matching absence of key regardless of value [${absenceOfKey}]:`
96+
);
97+
filesNoTeamOwner.forEach(file => console.log(` - ${file.name}`));
98+
}
99+
100+
listObjectContexts().catch(console.error);
101+
// [END storage_list_object_contexts]
102+
}
103+
104+
main(...process.argv.slice(2));

storage/setObjectContexts.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
// sample-metadata:
18+
// title: Set Object Contexts
19+
// description: Sets custom metadata (contexts) on an object.
20+
// usage: node setObjectContexts.js <BUCKET_NAME> <FILE_NAME>
21+
22+
/**
23+
* This application demonstrates how to set, update, and delete object contexts (metadata) on a file
24+
* in Google Cloud Storage.
25+
*/
26+
27+
function main(bucketName = 'my-bucket', fileName = 'test.txt') {
28+
// [START storage_set_object_contexts]
29+
/**
30+
* TODO(developer): Uncomment the following lines before running the sample.
31+
*/
32+
// The ID of your GCS bucket
33+
// const bucketName = 'your-unique-bucket-name';
34+
35+
// The ID of your GCS file
36+
// const fileName = 'your-file-name';
37+
38+
// Imports the Google Cloud client library
39+
const {Storage} = require('@google-cloud/storage');
40+
41+
// Creates a client
42+
const storage = new Storage();
43+
44+
async function setObjectContexts() {
45+
const file = storage.bucket(bucketName).file(fileName);
46+
try {
47+
// Create/Update Object Contexts
48+
// Object Contexts live in the 'contexts' field, not the 'metadata' field.
49+
const [metadata] = await file.setMetadata({
50+
contexts: {
51+
custom: {
52+
'team-owner': {value: 'storage-team'},
53+
priority: {value: 'high'},
54+
},
55+
},
56+
});
57+
58+
console.log(`Updated Object Contexts for ${fileName}:`);
59+
console.log(JSON.stringify(metadata.contexts, null, 2));
60+
} catch (error) {
61+
console.error(
62+
'Error executing set object contexts:',
63+
error.message || error
64+
);
65+
}
66+
// Delete a specific key from the context:
67+
// We send 'null' for the specific key we want to remove.
68+
await file.setMetadata({
69+
contexts: {
70+
custom: {
71+
'team-owner': null,
72+
},
73+
},
74+
});
75+
console.log(`Deleted 'team-owner' key from contexts for ${fileName}.`);
76+
77+
// Delete all keys from the context:
78+
// We set the 'custom' property to null to wipe the entire map.
79+
await file.setMetadata({
80+
contexts: {
81+
custom: null,
82+
},
83+
});
84+
console.log(`Cleared all custom contexts for ${fileName}.`);
85+
}
86+
87+
setObjectContexts().catch(console.error);
88+
// [END storage_set_object_contexts]
89+
}
90+
91+
main(...process.argv.slice(2));

0 commit comments

Comments
 (0)