├── .eslintignore ├── .eslintrc.json ├── .gitattributes ├── .github ├── .OwlBot.lock.yaml ├── .OwlBot.yaml ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── documentation_request.yml │ ├── feature_request.yml │ ├── processs_request.md │ └── questions.md ├── PULL_REQUEST_TEMPLATE.md ├── auto-approve.yml ├── auto-label.yaml ├── flakybot.yaml ├── generated-files-bot.yml ├── release-please.yml ├── release-trigger.yml ├── scripts │ ├── close-invalid-link.cjs │ ├── close-unresponsive.cjs │ ├── fixtures │ │ ├── invalidIssueBody.txt │ │ ├── validIssueBody.txt │ │ └── validIssueBodyDifferentLinkLocation.txt │ ├── package.json │ ├── remove-response-label.cjs │ └── tests │ │ ├── close-invalid-link.test.cjs │ │ └── close-or-remove-response-label.test.cjs ├── sync-repo-settings.yaml └── workflows │ ├── ci.yaml │ ├── issues-no-repro.yaml │ └── response.yaml ├── .gitignore ├── .jsdoc.js ├── .kokoro ├── .gitattributes ├── common.cfg ├── continuous │ └── node18 │ │ ├── common.cfg │ │ ├── lint.cfg │ │ ├── samples-test.cfg │ │ ├── system-test.cfg │ │ └── test.cfg ├── docs.sh ├── lint.sh ├── populate-secrets.sh ├── presubmit │ ├── node18 │ │ ├── common.cfg │ │ ├── samples-test.cfg │ │ ├── system-test.cfg │ │ └── test.cfg │ └── windows │ │ ├── common.cfg │ │ └── test.cfg ├── publish.sh ├── release │ ├── common.cfg │ ├── docs-devsite.cfg │ ├── docs-devsite.sh │ ├── docs.cfg │ ├── docs.sh │ └── publish.cfg ├── samples-test.sh ├── system-test.sh ├── test.bat ├── test.sh ├── trampoline.sh └── trampoline_v2.sh ├── .mocharc.js ├── .nycrc ├── .prettierignore ├── .prettierrc.js ├── .readme-partials.yml ├── .repo-metadata.json ├── .trampolinerc ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── linkinator.config.json ├── mock-server ├── README.md ├── datastore-server.ts └── package.json ├── owlbot.py ├── package.json ├── protos ├── app_engine_key.proto ├── google │ ├── cloud │ │ └── common_resources.proto │ └── datastore │ │ ├── admin │ │ └── v1 │ │ │ ├── datastore_admin.proto │ │ │ ├── index.proto │ │ │ └── migration.proto │ │ └── v1 │ │ ├── aggregation_result.proto │ │ ├── datastore.proto │ │ ├── entity.proto │ │ ├── query.proto │ │ └── query_profile.proto ├── protos.d.ts ├── protos.js └── protos.json ├── renovate.json ├── samples ├── .eslintrc.yml ├── README.md ├── concepts.js ├── error.js ├── export.js ├── generated │ └── v1 │ │ ├── datastore.allocate_ids.js │ │ ├── datastore.begin_transaction.js │ │ ├── datastore.commit.js │ │ ├── datastore.lookup.js │ │ ├── datastore.reserve_ids.js │ │ ├── datastore.rollback.js │ │ ├── datastore.run_aggregation_query.js │ │ ├── datastore.run_query.js │ │ ├── datastore_admin.create_index.js │ │ ├── datastore_admin.delete_index.js │ │ ├── datastore_admin.export_entities.js │ │ ├── datastore_admin.get_index.js │ │ ├── datastore_admin.import_entities.js │ │ ├── datastore_admin.list_indexes.js │ │ ├── snippet_metadata.google.datastore.admin.v1.json │ │ ├── snippet_metadata.google.datastore.v1.json │ │ ├── snippet_metadata_google.datastore.admin.v1.json │ │ └── snippet_metadata_google.datastore.v1.json ├── import.js ├── index.yaml ├── indexes.get.js ├── indexes.list.js ├── package.json ├── queryFilterOr.js ├── queryProfileExplain.js ├── queryProfileExplainAggregation.js ├── queryProfileExplainAnalyze.js ├── queryProfileExplainAnalyzeAggregation.js ├── quickstart.js ├── tasks.add.js ├── tasks.delete.js ├── tasks.js ├── tasks.list.js ├── tasks.markdone.js └── test │ ├── concepts.test.js │ ├── error.test.js │ ├── helpers │ ├── populate-data.js │ └── sorting.js │ ├── import-export.test.js │ ├── index.yaml │ ├── indexes.test.js │ ├── queryFilterOr.test.js │ ├── queryProfiling.test.js │ ├── quickstart.test.js │ └── tasks.test.js ├── src ├── aggregate.ts ├── entity.ts ├── filter.ts ├── index-class.ts ├── index.ts ├── interfaces │ └── save.ts ├── query.ts ├── request.ts ├── transaction.ts ├── utils │ └── entity │ │ ├── buildEntityProto.ts │ │ └── extendExcludeFromIndexes.ts └── v1 │ ├── datastore_admin_client.ts │ ├── datastore_admin_client_config.json │ ├── datastore_admin_proto_list.json │ ├── datastore_client.ts │ ├── datastore_client_config.json │ ├── datastore_proto_list.json │ ├── gapic_metadata.json │ └── index.ts ├── system-test ├── data │ └── index.yaml ├── datastore.ts ├── fixtures │ └── sample │ │ └── src │ │ ├── index.js │ │ └── index.ts └── install.ts ├── test ├── entity.ts ├── entity │ ├── buildEntityProto.ts │ ├── excludeIndexesAndBuildProto.ts │ ├── extendExcludeFromIndexes.ts │ └── findLargeProperties_.ts ├── fixtures │ ├── complexCaseLargeStrings.ts │ └── entityObjectAndProto.ts ├── gapic-mocks │ ├── client-initialization-testing.ts │ ├── commit.ts │ ├── error-mocks.ts │ ├── get-initialized-datastore-client.ts │ ├── handwritten-errors.ts │ └── runQuery.ts ├── gapic_datastore_admin_v1.ts ├── gapic_datastore_v1.ts ├── index-class.ts ├── index.ts ├── query.ts ├── request.ts ├── transaction.ts └── try-server.ts ├── tsconfig.json └── webpack.config.js /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/coverage 3 | test/fixtures 4 | build/ 5 | docs/ 6 | protos/ 7 | samples/generated/ 8 | system-test/**/fixtures 9 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/gts" 3 | } 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.ts text eol=lf 2 | *.js text eol=lf 3 | protos/* linguist-generated 4 | **/api-extractor.json linguist-language=JSON-with-Comments 5 | -------------------------------------------------------------------------------- /.github/.OwlBot.lock.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 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 | docker: 15 | image: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest 16 | digest: sha256:c7e4968cfc97a204a4b2381f3ecb55cabc40c4cccf88b1ef8bef0d976be87fee 17 | -------------------------------------------------------------------------------- /.github/.OwlBot.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 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 | docker: 15 | image: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest 16 | 17 | 18 | deep-remove-regex: 19 | - /owl-bot-staging 20 | 21 | deep-copy-regex: 22 | - source: /google/datastore/(v.*)/.*-nodejs/(.*) 23 | dest: /owl-bot-staging/$1/$2 24 | - source: /google/datastore/(admin/v.*)/.*-nodejs/(.*) 25 | dest: /owl-bot-staging/$1/$2 26 | 27 | begin-after-commit-hash: fb91803ccef5d7c695139b22788b309e2197856b 28 | 29 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners file. 2 | # This file controls who is tagged for review for any given pull request. 3 | # 4 | # For syntax help see: 5 | # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax 6 | 7 | 8 | # Unless specified, the jsteam is the default owner for nodejs repositories. 9 | * @googleapis/cloud-native-db-dpes @googleapis/api-datastore-sdk @googleapis/jsteam -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: Google Cloud Support 3 | url: https://cloud.google.com/support/ 4 | about: If you have a support contract with Google, please use the Google Cloud Support portal. 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation_request.yml: -------------------------------------------------------------------------------- 1 | name: Documentation Requests 2 | description: Requests for more information 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: > 7 | Please use this issue type to log documentation requests against the library itself. 8 | These requests should involve documentation on Github (`.md` files), and should relate to the library 9 | itself. If you have questions or documentation requests for an API, please 10 | reach out to the API tracker itself. 11 | 12 | Please submit an issue to the API team, either by submitting an 13 | issue in its issue tracker https://cloud.google.com/support/docs/issue-trackers), or by 14 | submitting an issue in its linked tracker in the .repo-metadata.json 15 | file in the API under packages/* ([example](https://issuetracker.google.com/savedsearches/559768)). 16 | You can also submit a request to documentation on cloud.google.com itself with the "Send Feedback" 17 | on the bottom of the page. 18 | 19 | 20 | Please note that documentation requests and questions for specific APIs 21 | will be closed. 22 | - type: checkboxes 23 | attributes: 24 | label: Please make sure you have searched for information in the following 25 | guides. 26 | options: 27 | - label: "Search the issues already opened: 28 | https://github.com/GoogleCloudPlatform/google-cloud-node/issues" 29 | required: true 30 | - label: "Check our Troubleshooting guide: 31 | https://googlecloudplatform.github.io/google-cloud-node/#/docs/guid\ 32 | es/troubleshooting" 33 | required: true 34 | - label: "Check our FAQ: 35 | https://googlecloudplatform.github.io/google-cloud-node/#/docs/guid\ 36 | es/faq" 37 | required: true 38 | - label: "Check our libraries HOW-TO: 39 | https://github.com/googleapis/gax-nodejs/blob/main/client-libraries\ 40 | .md" 41 | required: true 42 | - label: "Check out our authentication guide: 43 | https://github.com/googleapis/google-auth-library-nodejs" 44 | required: true 45 | - label: "Check out handwritten samples for many of our APIs: 46 | https://github.com/GoogleCloudPlatform/nodejs-docs-samples" 47 | required: true 48 | - type: textarea 49 | attributes: 50 | label: > 51 | Documentation Request 52 | validations: 53 | required: true 54 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest an idea for this library 3 | labels: 4 | - feature request 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: > 9 | **PLEASE READ**: If you have a support contract with Google, please 10 | create an issue in the [support 11 | console](https://cloud.google.com/support/) instead of filing on GitHub. 12 | This will ensure a timely response. Otherwise, please make sure to 13 | follow the steps below. 14 | - type: textarea 15 | attributes: 16 | label: > 17 | A screenshot that you have tested with "Try this API". 18 | description: > 19 | As our client libraries are mostly autogenerated, we kindly request 20 | that you test whether your feature request is with the client library, or with the 21 | API itself. To do so, please search for your API 22 | here: https://developers.google.com/apis-explorer and attempt to 23 | reproduce the issue in the given method. Please include a screenshot of 24 | the response in "Try this API". This response should NOT match the current 25 | behavior you are experiencing. If the behavior is the same, it means 26 | that you are likely requesting a feature for the API itself. In that 27 | case, please submit an issue to the API team, either by submitting an 28 | issue in its issue tracker https://cloud.google.com/support/docs/issue-trackers, or by 29 | submitting an issue in its linked tracker in the .repo-metadata.json 30 | file in the API under packages/* ([example](https://issuetracker.google.com/savedsearches/559768)) 31 | 32 | Example of library specific issues would be: retry strategies, authentication questions, or issues with typings. 33 | Examples of API issues would include: expanding method parameter types, adding functionality to an API. 34 | validations: 35 | required: true 36 | - type: textarea 37 | attributes: 38 | label: > 39 | What would you like to see in the library? 40 | description: > 41 | Screenshots can be provided in the issue body below. 42 | placeholder: | 43 | 1. Set up authentication like so 44 | 2. Run the program like so 45 | 3. X would be nice to happen 46 | 47 | - type: textarea 48 | attributes: 49 | label: Describe alternatives you've considered 50 | 51 | - type: textarea 52 | attributes: 53 | label: Additional context/notes -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/processs_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Process Request 3 | about: Submit a process request to the library. Process requests are any requests related to library infrastructure, for example CI/CD, publishing, releasing, broken links. 4 | --- 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/questions.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: If you have a question, please use Discussions 4 | 5 | --- 6 | 7 | If you have a general question that goes beyond the library itself, we encourage you to use [Discussions](https://github.com//discussions) 8 | to engage with fellow community members! 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | > Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: 2 | 3 | ## Description 4 | 5 | > Please provide a detailed description for the change. 6 | > As much as possible, please try to keep changes separate by purpose. For example, try not to make a one-line bug fix in a feature request, or add an irrelevant README change to a bug fix. 7 | 8 | ## Impact 9 | 10 | > What's the impact of this change? 11 | 12 | ## Testing 13 | 14 | > Have you added unit and integration tests if necessary? 15 | > Were any tests changed? Are any breaking changes necessary? 16 | 17 | ## Additional Information 18 | 19 | > Any additional details that we should be aware of? 20 | 21 | ## Checklist 22 | 23 | - [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/nodejs-datastore/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea 24 | - [ ] Ensure the tests and linter pass 25 | - [ ] Code coverage does not decrease 26 | - [ ] Appropriate docs were updated 27 | - [ ] Appropriate comments were added, particularly in complex areas or places that require background 28 | - [ ] No new warnings or issues will be generated from this change 29 | 30 | Fixes #issue_number_goes_here 🦕 31 | -------------------------------------------------------------------------------- /.github/auto-approve.yml: -------------------------------------------------------------------------------- 1 | processes: 2 | - "NodeDependency" -------------------------------------------------------------------------------- /.github/auto-label.yaml: -------------------------------------------------------------------------------- 1 | requestsize: 2 | enabled: true 3 | -------------------------------------------------------------------------------- /.github/flakybot.yaml: -------------------------------------------------------------------------------- 1 | issuePriority: p2 2 | -------------------------------------------------------------------------------- /.github/generated-files-bot.yml: -------------------------------------------------------------------------------- 1 | generatedFiles: 2 | - path: '.kokoro/**' 3 | message: '`.kokoro` files are templated and should be updated in [`synthtool`](https://github.com/googleapis/synthtool)' 4 | - path: '.github/CODEOWNERS' 5 | message: 'CODEOWNERS should instead be modified via the `codeowner_team` property in .repo-metadata.json' 6 | - path: '.github/workflows/ci.yaml' 7 | message: '`.github/workflows/ci.yaml` (GitHub Actions) should be updated in [`synthtool`](https://github.com/googleapis/synthtool)' 8 | - path: '.github/generated-files-bot.+(yml|yaml)' 9 | message: '`.github/generated-files-bot.(yml|yaml)` should be updated in [`synthtool`](https://github.com/googleapis/synthtool)' 10 | - path: 'README.md' 11 | message: '`README.md` is managed by [`synthtool`](https://github.com/googleapis/synthtool). However, a partials file can be used to update the README, e.g.: https://github.com/googleapis/nodejs-storage/blob/main/.readme-partials.yaml' 12 | - path: 'samples/README.md' 13 | message: '`samples/README.md` is managed by [`synthtool`](https://github.com/googleapis/synthtool). However, a partials file can be used to update the README, e.g.: https://github.com/googleapis/nodejs-storage/blob/main/.readme-partials.yaml' 14 | ignoreAuthors: 15 | - 'gcf-owl-bot[bot]' 16 | - 'yoshi-automation' 17 | -------------------------------------------------------------------------------- /.github/release-please.yml: -------------------------------------------------------------------------------- 1 | handleGHRelease: true 2 | releaseType: node 3 | -------------------------------------------------------------------------------- /.github/release-trigger.yml: -------------------------------------------------------------------------------- 1 | enabled: true 2 | multiScmName: nodejs-datastore -------------------------------------------------------------------------------- /.github/scripts/close-invalid-link.cjs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | const fs = require('fs'); 16 | const yaml = require('js-yaml'); 17 | const path = require('path'); 18 | const TEMPLATE_FILE_PATH = path.resolve(__dirname, '../ISSUE_TEMPLATE/bug_report.yml') 19 | 20 | async function closeIssue(github, owner, repo, number) { 21 | await github.rest.issues.createComment({ 22 | owner: owner, 23 | repo: repo, 24 | issue_number: number, 25 | body: "Issue was opened with an invalid reproduction link. Please make sure the repository is a valid, publicly-accessible github repository, and make sure the url is complete (example: https://github.com/googleapis/google-cloud-node)" 26 | }); 27 | await github.rest.issues.update({ 28 | owner: owner, 29 | repo: repo, 30 | issue_number: number, 31 | state: "closed" 32 | }); 33 | } 34 | module.exports = async ({ github, context }) => { 35 | const owner = context.repo.owner; 36 | const repo = context.repo.repo; 37 | const number = context.issue.number; 38 | 39 | const issue = await github.rest.issues.get({ 40 | owner: owner, 41 | repo: repo, 42 | issue_number: number, 43 | }); 44 | 45 | const yamlData = fs.readFileSync(TEMPLATE_FILE_PATH, 'utf8'); 46 | const obj = yaml.load(yamlData); 47 | const linkMatchingText = (obj.body.find(x => {return x.type === 'input' && x.validations.required === true && x.attributes.label.includes('link')})).attributes.label; 48 | const isBugTemplate = issue.data.body.includes(linkMatchingText); 49 | 50 | if (isBugTemplate) { 51 | console.log(`Issue ${number} is a bug template`) 52 | try { 53 | const text = issue.data.body; 54 | const match = text.indexOf(linkMatchingText); 55 | if (match !== -1) { 56 | const nextLineIndex = text.indexOf('http', match); 57 | if (nextLineIndex == -1) { 58 | await closeIssue(github, owner, repo, number); 59 | return; 60 | } 61 | const link = text.substring(nextLineIndex, text.indexOf('\n', nextLineIndex)); 62 | console.log(`Issue ${number} contains this link: ${link}`); 63 | const isValidLink = (await fetch(link)).ok; 64 | console.log(`Issue ${number} has a ${isValidLink ? "valid" : "invalid"} link`) 65 | if (!isValidLink) { 66 | await closeIssue(github, owner, repo, number); 67 | } 68 | } 69 | } catch (err) { 70 | await closeIssue(github, owner, repo, number); 71 | } 72 | } 73 | }; -------------------------------------------------------------------------------- /.github/scripts/close-unresponsive.cjs: -------------------------------------------------------------------------------- 1 | /// Copyright 2024 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 | function labeledEvent(data) { 16 | return data.event === "labeled" && data.label.name === "needs more info"; 17 | } 18 | 19 | const numberOfDaysLimit = 15; 20 | const close_message = `This has been closed since a request for information has \ 21 | not been answered for ${numberOfDaysLimit} days. It can be reopened when the \ 22 | requested information is provided.`; 23 | 24 | module.exports = async ({ github, context }) => { 25 | const owner = context.repo.owner; 26 | const repo = context.repo.repo; 27 | 28 | const issues = await github.rest.issues.listForRepo({ 29 | owner: owner, 30 | repo: repo, 31 | labels: "needs more info", 32 | }); 33 | const numbers = issues.data.map((e) => e.number); 34 | 35 | for (const number of numbers) { 36 | const events = await github.paginate( 37 | github.rest.issues.listEventsForTimeline, 38 | { 39 | owner: owner, 40 | repo: repo, 41 | issue_number: number, 42 | }, 43 | (response) => response.data.filter(labeledEvent) 44 | ); 45 | 46 | const latest_response_label = events[events.length - 1]; 47 | 48 | const created_at = new Date(latest_response_label.created_at); 49 | const now = new Date(); 50 | const diff = now - created_at; 51 | const diffDays = diff / (1000 * 60 * 60 * 24); 52 | 53 | if (diffDays > numberOfDaysLimit) { 54 | await github.rest.issues.update({ 55 | owner: owner, 56 | repo: repo, 57 | issue_number: number, 58 | state: "closed", 59 | }); 60 | 61 | await github.rest.issues.createComment({ 62 | owner: owner, 63 | repo: repo, 64 | issue_number: number, 65 | body: close_message, 66 | }); 67 | } 68 | } 69 | }; -------------------------------------------------------------------------------- /.github/scripts/fixtures/invalidIssueBody.txt: -------------------------------------------------------------------------------- 1 | ### Please make sure you have searched for information in the following guides. 2 | 3 | - [X] Search the issues already opened: https://github.com/GoogleCloudPlatform/google-cloud-node/issues 4 | - [X] Search StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js 5 | - [X] Check our Troubleshooting guide: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/troubleshooting 6 | - [X] Check our FAQ: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/faq 7 | - [X] Check our libraries HOW-TO: https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md 8 | - [X] Check out our authentication guide: https://github.com/googleapis/google-auth-library-nodejs 9 | - [X] Check out handwritten samples for many of our APIs: https://github.com/GoogleCloudPlatform/nodejs-docs-samples 10 | 11 | ### A screenshot that you have tested with "Try this API". 12 | 13 | 14 | N/A 15 | 16 | ### Link to the code that reproduces this issue. A link to a **public** Github Repository or gist with a minimal reproduction. 17 | 18 | not-a-link 19 | 20 | ### A step-by-step description of how to reproduce the issue, based on the linked reproduction. 21 | 22 | 23 | Change MY_PROJECT to your project name, add credentials if needed and run. 24 | 25 | ### A clear and concise description of what the bug is, and what you expected to happen. 26 | 27 | The application crashes with the following exception (which there is no way to catch). It should just emit error, and allow graceful handling. 28 | TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Object 29 | at _write (node:internal/streams/writable:474:13) 30 | at Writable.write (node:internal/streams/writable:502:10) 31 | at Duplexify._write (/project/node_modules/duplexify/index.js:212:22) 32 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 33 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 34 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 35 | at Pumpify. (/project/node_modules/@google-cloud/speech/build/src/helpers.js:79:27) 36 | at Object.onceWrapper (node:events:633:26) 37 | at Pumpify.emit (node:events:518:28) 38 | at obj. [as _write] (/project/node_modules/stubs/index.js:28:22) 39 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 40 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 41 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 42 | at PassThrough.ondata (node:internal/streams/readable:1007:22) 43 | at PassThrough.emit (node:events:518:28) 44 | at addChunk (node:internal/streams/readable:559:12) { 45 | code: 'ERR_INVALID_ARG_TYPE' 46 | 47 | 48 | ### A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. ** 49 | 50 | No library should crash an application this way. -------------------------------------------------------------------------------- /.github/scripts/fixtures/validIssueBody.txt: -------------------------------------------------------------------------------- 1 | ### Please make sure you have searched for information in the following guides. 2 | 3 | - [X] Search the issues already opened: https://github.com/GoogleCloudPlatform/google-cloud-node/issues 4 | - [X] Search StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js 5 | - [X] Check our Troubleshooting guide: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/troubleshooting 6 | - [X] Check our FAQ: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/faq 7 | - [X] Check our libraries HOW-TO: https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md 8 | - [X] Check out our authentication guide: https://github.com/googleapis/google-auth-library-nodejs 9 | - [X] Check out handwritten samples for many of our APIs: https://github.com/GoogleCloudPlatform/nodejs-docs-samples 10 | 11 | ### A screenshot that you have tested with "Try this API". 12 | 13 | 14 | N/A 15 | 16 | ### Link to the code that reproduces this issue. A link to a **public** Github Repository or gist with a minimal reproduction. 17 | 18 | https://gist.github.com/orgads/13cbf44c91923da27d8772b5f10489c9 19 | 20 | ### A step-by-step description of how to reproduce the issue, based on the linked reproduction. 21 | 22 | 23 | Change MY_PROJECT to your project name, add credentials if needed and run. 24 | 25 | ### A clear and concise description of what the bug is, and what you expected to happen. 26 | 27 | The application crashes with the following exception (which there is no way to catch). It should just emit error, and allow graceful handling. 28 | TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Object 29 | at _write (node:internal/streams/writable:474:13) 30 | at Writable.write (node:internal/streams/writable:502:10) 31 | at Duplexify._write (/project/node_modules/duplexify/index.js:212:22) 32 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 33 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 34 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 35 | at Pumpify. (/project/node_modules/@google-cloud/speech/build/src/helpers.js:79:27) 36 | at Object.onceWrapper (node:events:633:26) 37 | at Pumpify.emit (node:events:518:28) 38 | at obj. [as _write] (/project/node_modules/stubs/index.js:28:22) 39 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 40 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 41 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 42 | at PassThrough.ondata (node:internal/streams/readable:1007:22) 43 | at PassThrough.emit (node:events:518:28) 44 | at addChunk (node:internal/streams/readable:559:12) { 45 | code: 'ERR_INVALID_ARG_TYPE' 46 | 47 | 48 | ### A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. ** 49 | 50 | No library should crash an application this way. -------------------------------------------------------------------------------- /.github/scripts/fixtures/validIssueBodyDifferentLinkLocation.txt: -------------------------------------------------------------------------------- 1 | ### Please make sure you have searched for information in the following guides. 2 | 3 | - [X] Search the issues already opened: https://github.com/GoogleCloudPlatform/google-cloud-node/issues 4 | - [X] Search StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js 5 | - [X] Check our Troubleshooting guide: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/troubleshooting 6 | - [X] Check our FAQ: https://googlecloudplatform.github.io/google-cloud-node/#/docs/guides/faq 7 | - [X] Check our libraries HOW-TO: https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md 8 | - [X] Check out our authentication guide: https://github.com/googleapis/google-auth-library-nodejs 9 | - [X] Check out handwritten samples for many of our APIs: https://github.com/GoogleCloudPlatform/nodejs-docs-samples 10 | 11 | ### A screenshot that you have tested with "Try this API". 12 | 13 | 14 | N/A 15 | 16 | ### A step-by-step description of how to reproduce the issue, based on the linked reproduction. 17 | 18 | 19 | Change MY_PROJECT to your project name, add credentials if needed and run. 20 | 21 | ### A clear and concise description of what the bug is, and what you expected to happen. 22 | 23 | The application crashes with the following exception (which there is no way to catch). It should just emit error, and allow graceful handling. 24 | TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Object 25 | at _write (node:internal/streams/writable:474:13) 26 | at Writable.write (node:internal/streams/writable:502:10) 27 | at Duplexify._write (/project/node_modules/duplexify/index.js:212:22) 28 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 29 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 30 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 31 | at Pumpify. (/project/node_modules/@google-cloud/speech/build/src/helpers.js:79:27) 32 | at Object.onceWrapper (node:events:633:26) 33 | at Pumpify.emit (node:events:518:28) 34 | at obj. [as _write] (/project/node_modules/stubs/index.js:28:22) 35 | at doWrite (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:390:139) 36 | at writeOrBuffer (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:381:5) 37 | at Writable.write (/project/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:302:11) 38 | at PassThrough.ondata (node:internal/streams/readable:1007:22) 39 | at PassThrough.emit (node:events:518:28) 40 | at addChunk (node:internal/streams/readable:559:12) { 41 | code: 'ERR_INVALID_ARG_TYPE' 42 | 43 | ### Link to the code that reproduces this issue. A link to a **public** Github Repository with a minimal reproduction. 44 | 45 | 46 | https://gist.github.com/orgads/13cbf44c91923da27d8772b5f10489c9 47 | 48 | ### A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. ** 49 | 50 | No library should crash an application this way. -------------------------------------------------------------------------------- /.github/scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tests", 3 | "private": true, 4 | "description": "tests for script", 5 | "scripts": { 6 | "test": "mocha tests/close-invalid-link.test.cjs && mocha tests/close-or-remove-response-label.test.cjs" 7 | }, 8 | "author": "Google Inc.", 9 | "license": "Apache-2.0", 10 | "engines": { 11 | "node": ">=18" 12 | }, 13 | "dependencies": { 14 | "js-yaml": "^4.1.0" 15 | }, 16 | "devDependencies": { 17 | "@octokit/rest": "^19.0.0", 18 | "mocha": "^10.0.0", 19 | "sinon": "^18.0.0" 20 | } 21 | } -------------------------------------------------------------------------------- /.github/scripts/remove-response-label.cjs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | module.exports = async ({ github, context }) => { 16 | const commenter = context.actor; 17 | const issue = await github.rest.issues.get({ 18 | owner: context.repo.owner, 19 | repo: context.repo.repo, 20 | issue_number: context.issue.number, 21 | }); 22 | const author = issue.data.user.login; 23 | const labels = issue.data.labels.map((e) => e.name); 24 | 25 | if (author === commenter && labels.includes("needs more info")) { 26 | await github.rest.issues.removeLabel({ 27 | owner: context.repo.owner, 28 | repo: context.repo.repo, 29 | issue_number: context.issue.number, 30 | name: "needs more info", 31 | }); 32 | } 33 | }; -------------------------------------------------------------------------------- /.github/scripts/tests/close-invalid-link.test.cjs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // https://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 | const { describe, it } = require('mocha'); 18 | const closeInvalidLink = require('../close-invalid-link.cjs'); 19 | const fs = require('fs'); 20 | const sinon = require('sinon'); 21 | 22 | describe('close issues with invalid links', () => { 23 | let octokitStub; 24 | let issuesStub; 25 | 26 | beforeEach(() => { 27 | issuesStub = { 28 | get: sinon.stub(), 29 | createComment: sinon.stub(), 30 | update: sinon.stub(), 31 | }; 32 | octokitStub = { 33 | rest: { 34 | issues: issuesStub, 35 | }, 36 | }; 37 | }); 38 | 39 | afterEach(() => { 40 | sinon.restore(); 41 | }); 42 | 43 | it('does not do anything if it is not a bug', async () => { 44 | const context = { repo: { owner: 'testOrg', repo: 'testRepo' }, issue: { number: 1 } }; 45 | issuesStub.get.resolves({ data: { body: "I'm having a problem with this." } }); 46 | 47 | await closeInvalidLink({ github: octokitStub, context }); 48 | 49 | sinon.assert.calledOnce(issuesStub.get); 50 | sinon.assert.notCalled(issuesStub.createComment); 51 | sinon.assert.notCalled(issuesStub.update); 52 | }); 53 | 54 | it('does not do anything if it is a bug with an appropriate link', async () => { 55 | const context = { repo: { owner: 'testOrg', repo: 'testRepo' }, issue: { number: 1 } }; 56 | issuesStub.get.resolves({ data: { body: fs.readFileSync('./fixtures/validIssueBody.txt', 'utf-8') } }); 57 | 58 | await closeInvalidLink({ github: octokitStub, context }); 59 | 60 | sinon.assert.calledOnce(issuesStub.get); 61 | sinon.assert.notCalled(issuesStub.createComment); 62 | sinon.assert.notCalled(issuesStub.update); 63 | }); 64 | 65 | it('does not do anything if it is a bug with an appropriate link and the template changes', async () => { 66 | const context = { repo: { owner: 'testOrg', repo: 'testRepo' }, issue: { number: 1 } }; 67 | issuesStub.get.resolves({ data: { body: fs.readFileSync('./fixtures/validIssueBodyDifferentLinkLocation.txt', 'utf-8') } }); 68 | 69 | await closeInvalidLink({ github: octokitStub, context }); 70 | 71 | sinon.assert.calledOnce(issuesStub.get); 72 | sinon.assert.notCalled(issuesStub.createComment); 73 | sinon.assert.notCalled(issuesStub.update); 74 | }); 75 | 76 | it('closes the issue if the link is invalid', async () => { 77 | const context = { repo: { owner: 'testOrg', repo: 'testRepo' }, issue: { number: 1 } }; 78 | issuesStub.get.resolves({ data: { body: fs.readFileSync('./fixtures/invalidIssueBody.txt', 'utf-8') } }); 79 | 80 | await closeInvalidLink({ github: octokitStub, context }); 81 | 82 | sinon.assert.calledOnce(issuesStub.get); 83 | sinon.assert.calledOnce(issuesStub.createComment); 84 | sinon.assert.calledOnce(issuesStub.update); 85 | }); 86 | }); -------------------------------------------------------------------------------- /.github/sync-repo-settings.yaml: -------------------------------------------------------------------------------- 1 | branchProtectionRules: 2 | - pattern: main 3 | isAdminEnforced: true 4 | requiredApprovingReviewCount: 1 5 | requiresCodeOwnerReviews: true 6 | requiresStrictStatusChecks: true 7 | requiredStatusCheckContexts: 8 | - "ci/kokoro: Samples test" 9 | - "ci/kokoro: System test" 10 | - lint 11 | - test (18) 12 | - test (20) 13 | - test (22) 14 | - cla/google 15 | - windows 16 | - OwlBot Post Processor 17 | permissionRules: 18 | - team: yoshi-admins 19 | permission: admin 20 | - team: jsteam-admins 21 | permission: admin 22 | - team: jsteam 23 | permission: push 24 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | pull_request: 6 | name: ci 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | node: [18, 20, 22] 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-node@v4 16 | with: 17 | node-version: ${{ matrix.node }} 18 | - run: node --version 19 | # The first installation step ensures that all of our production 20 | # dependencies work on the given Node.js version, this helps us find 21 | # dependencies that don't match our engines field: 22 | - run: npm install --production --engine-strict --ignore-scripts --no-package-lock 23 | # Clean up the production install, before installing dev/production: 24 | - run: rm -rf node_modules 25 | - run: npm install --engine-strict 26 | - run: npm test 27 | env: 28 | MOCHA_THROW_DEPRECATION: false 29 | test-script: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v4 33 | - uses: actions/setup-node@v4 34 | with: 35 | node-version: 18 36 | - run: node --version 37 | - run: npm install --engine-strict 38 | working-directory: .github/scripts 39 | - run: npm test 40 | working-directory: .github/scripts 41 | env: 42 | MOCHA_THROW_DEPRECATION: false 43 | windows: 44 | runs-on: windows-latest 45 | steps: 46 | - uses: actions/checkout@v4 47 | - uses: actions/setup-node@v4 48 | with: 49 | node-version: 18 50 | - run: npm install --engine-strict 51 | - run: npm test 52 | env: 53 | MOCHA_THROW_DEPRECATION: false 54 | lint: 55 | runs-on: ubuntu-latest 56 | steps: 57 | - uses: actions/checkout@v4 58 | - uses: actions/setup-node@v4 59 | with: 60 | node-version: 18 61 | - run: npm install 62 | - run: npm run lint 63 | docs: 64 | runs-on: ubuntu-latest 65 | steps: 66 | - uses: actions/checkout@v4 67 | - uses: actions/setup-node@v4 68 | with: 69 | node-version: 18 70 | - run: npm install 71 | - run: npm run docs 72 | - uses: JustinBeckwith/linkinator-action@v1 73 | with: 74 | paths: docs/ 75 | -------------------------------------------------------------------------------- /.github/workflows/issues-no-repro.yaml: -------------------------------------------------------------------------------- 1 | name: invalid_link 2 | on: 3 | issues: 4 | types: [opened, reopened] 5 | 6 | jobs: 7 | close: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | pull-requests: write 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: 18 17 | - run: npm install 18 | working-directory: ./.github/scripts 19 | - uses: actions/github-script@v7 20 | with: 21 | script: | 22 | const script = require('./.github/scripts/close-invalid-link.cjs') 23 | await script({github, context}) 24 | -------------------------------------------------------------------------------- /.github/workflows/response.yaml: -------------------------------------------------------------------------------- 1 | name: no_response 2 | on: 3 | schedule: 4 | - cron: '30 1 * * *' # Run every day at 01:30 5 | workflow_dispatch: 6 | issue_comment: 7 | 8 | jobs: 9 | close: 10 | if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' 11 | runs-on: ubuntu-latest 12 | permissions: 13 | issues: write 14 | pull-requests: write 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: actions/github-script@v7 18 | with: 19 | script: | 20 | const script = require('./.github/scripts/close-unresponsive.cjs') 21 | await script({github, context}) 22 | 23 | remove_label: 24 | if: github.event_name == 'issue_comment' 25 | runs-on: ubuntu-latest 26 | permissions: 27 | issues: write 28 | pull-requests: write 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: actions/github-script@v7 32 | with: 33 | script: | 34 | const script = require('./.github/scripts/remove-response-label.cjs') 35 | await script({github, context}) 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.log 2 | **/node_modules 3 | /.coverage 4 | /coverage 5 | /.nyc_output 6 | /docs/ 7 | /out/ 8 | /build/ 9 | system-test/secrets.js 10 | system-test/*key.json 11 | *.lock 12 | .DS_Store 13 | package-lock.json 14 | __pycache__ 15 | -------------------------------------------------------------------------------- /.jsdoc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 'use strict'; 20 | 21 | module.exports = { 22 | opts: { 23 | readme: './README.md', 24 | package: './package.json', 25 | template: './node_modules/jsdoc-fresh', 26 | recurse: true, 27 | verbose: true, 28 | destination: './docs/' 29 | }, 30 | plugins: [ 31 | 'plugins/markdown', 32 | 'jsdoc-region-tag' 33 | ], 34 | source: { 35 | excludePattern: '(^|\\/|\\\\)[._]', 36 | include: [ 37 | 'build/src', 38 | 'protos' 39 | ], 40 | includePattern: '\\.js$' 41 | }, 42 | templates: { 43 | copyright: 'Copyright 2025 Google LLC', 44 | includeDate: false, 45 | sourceFiles: false, 46 | systemName: '@google-cloud/datastore', 47 | theme: 'lumen', 48 | default: { 49 | outputSourceFiles: false 50 | } 51 | }, 52 | markdown: { 53 | idInHeadings: true 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /.kokoro/.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-generated=true 2 | -------------------------------------------------------------------------------- /.kokoro/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Use the trampoline script to run in docker. 14 | build_file: "nodejs-datastore/.kokoro/trampoline_v2.sh" 15 | 16 | # Configure the docker image for kokoro-trampoline. 17 | env_vars: { 18 | key: "TRAMPOLINE_IMAGE" 19 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 20 | } 21 | env_vars: { 22 | key: "TRAMPOLINE_BUILD_FILE" 23 | value: "github/nodejs-datastore/.kokoro/test.sh" 24 | } 25 | -------------------------------------------------------------------------------- /.kokoro/continuous/node18/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Use the trampoline script to run in docker. 14 | build_file: "nodejs-datastore/.kokoro/trampoline_v2.sh" 15 | 16 | # Configure the docker image for kokoro-trampoline. 17 | env_vars: { 18 | key: "TRAMPOLINE_IMAGE" 19 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 20 | } 21 | env_vars: { 22 | key: "TRAMPOLINE_BUILD_FILE" 23 | value: "github/nodejs-datastore/.kokoro/test.sh" 24 | } 25 | -------------------------------------------------------------------------------- /.kokoro/continuous/node18/lint.cfg: -------------------------------------------------------------------------------- 1 | env_vars: { 2 | key: "TRAMPOLINE_BUILD_FILE" 3 | value: "github/nodejs-datastore/.kokoro/lint.sh" 4 | } 5 | -------------------------------------------------------------------------------- /.kokoro/continuous/node18/samples-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/nodejs-datastore/.kokoro/samples-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/continuous/node18/system-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/nodejs-datastore/.kokoro/system-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/continuous/node18/test.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/nodejs-datastore/e974dbb73a1a6197d42abc006e36bdce601c40e4/.kokoro/continuous/node18/test.cfg -------------------------------------------------------------------------------- /.kokoro/docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | cd $(dirname $0)/.. 22 | 23 | npm install 24 | 25 | npm run docs-test 26 | -------------------------------------------------------------------------------- /.kokoro/lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | cd $(dirname $0)/.. 22 | 23 | npm install 24 | 25 | # Install and link samples 26 | if [ -f samples/package.json ]; then 27 | cd samples/ 28 | npm link ../ 29 | npm install 30 | cd .. 31 | fi 32 | 33 | npm run lint 34 | -------------------------------------------------------------------------------- /.kokoro/populate-secrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # This file is called in the early stage of `trampoline_v2.sh` to 17 | # populate secrets needed for the CI builds. 18 | 19 | set -eo pipefail 20 | 21 | function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;} 22 | function msg { println "$*" >&2 ;} 23 | function println { printf '%s\n' "$(now) $*" ;} 24 | 25 | # Populates requested secrets set in SECRET_MANAGER_KEYS 26 | 27 | # In Kokoro CI builds, we use the service account attached to the 28 | # Kokoro VM. This means we need to setup auth on other CI systems. 29 | # For local run, we just use the gcloud command for retrieving the 30 | # secrets. 31 | 32 | if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then 33 | GCLOUD_COMMANDS=( 34 | "docker" 35 | "run" 36 | "--entrypoint=gcloud" 37 | "--volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR}" 38 | "gcr.io/google.com/cloudsdktool/cloud-sdk" 39 | ) 40 | if [[ "${TRAMPOLINE_CI:-}" == "kokoro" ]]; then 41 | SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" 42 | else 43 | echo "Authentication for this CI system is not implemented yet." 44 | exit 2 45 | # TODO: Determine appropriate SECRET_LOCATION and the GCLOUD_COMMANDS. 46 | fi 47 | else 48 | # For local run, use /dev/shm or temporary directory for 49 | # KOKORO_GFILE_DIR. 50 | if [[ -d "/dev/shm" ]]; then 51 | export KOKORO_GFILE_DIR=/dev/shm 52 | else 53 | export KOKORO_GFILE_DIR=$(mktemp -d -t ci-XXXXXXXX) 54 | fi 55 | SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" 56 | GCLOUD_COMMANDS=("gcloud") 57 | fi 58 | 59 | msg "Creating folder on disk for secrets: ${SECRET_LOCATION}" 60 | mkdir -p ${SECRET_LOCATION} 61 | 62 | for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g") 63 | do 64 | msg "Retrieving secret ${key}" 65 | "${GCLOUD_COMMANDS[@]}" \ 66 | secrets versions access latest \ 67 | --project cloud-devrel-kokoro-resources \ 68 | --secret $key > \ 69 | "$SECRET_LOCATION/$key" 70 | if [[ $? == 0 ]]; then 71 | msg "Secret written to ${SECRET_LOCATION}/${key}" 72 | else 73 | msg "Error retrieving secret ${key}" 74 | exit 2 75 | fi 76 | done 77 | -------------------------------------------------------------------------------- /.kokoro/presubmit/node18/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Use the trampoline script to run in docker. 14 | build_file: "nodejs-datastore/.kokoro/trampoline_v2.sh" 15 | 16 | # Configure the docker image for kokoro-trampoline. 17 | env_vars: { 18 | key: "TRAMPOLINE_IMAGE" 19 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 20 | } 21 | env_vars: { 22 | key: "TRAMPOLINE_BUILD_FILE" 23 | value: "github/nodejs-datastore/.kokoro/test.sh" 24 | } 25 | -------------------------------------------------------------------------------- /.kokoro/presubmit/node18/samples-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/nodejs-datastore/.kokoro/samples-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/node18/system-test.cfg: -------------------------------------------------------------------------------- 1 | # Download resources for system tests (service account key, etc.) 2 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" 3 | 4 | env_vars: { 5 | key: "TRAMPOLINE_BUILD_FILE" 6 | value: "github/nodejs-datastore/.kokoro/system-test.sh" 7 | } 8 | 9 | env_vars: { 10 | key: "SECRET_MANAGER_KEYS" 11 | value: "long-door-651-kokoro-system-test-service-account" 12 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/node18/test.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/nodejs-datastore/e974dbb73a1a6197d42abc006e36bdce601c40e4/.kokoro/presubmit/node18/test.cfg -------------------------------------------------------------------------------- /.kokoro/presubmit/windows/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | -------------------------------------------------------------------------------- /.kokoro/presubmit/windows/test.cfg: -------------------------------------------------------------------------------- 1 | # Use the test file directly 2 | build_file: "nodejs-datastore/.kokoro/test.bat" 3 | -------------------------------------------------------------------------------- /.kokoro/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | # Start the releasetool reporter 22 | python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script 23 | 24 | cd $(dirname $0)/.. 25 | 26 | NPM_TOKEN=$(cat $KOKORO_KEYSTORE_DIR/73713_google-cloud-npm-token-1) 27 | echo "//wombat-dressing-room.appspot.com/:_authToken=${NPM_TOKEN}" > ~/.npmrc 28 | 29 | npm install 30 | npm pack . 31 | # npm provides no way to specify, observe, or predict the name of the tarball 32 | # file it generates. We have to look in the current directory for the freshest 33 | # .tgz file. 34 | TARBALL=$(ls -1 -t *.tgz | head -1) 35 | 36 | npm publish --access=public --registry=https://wombat-dressing-room.appspot.com "$TARBALL" 37 | 38 | # Kokoro collects *.tgz and package-lock.json files and stores them in Placer 39 | # so we can generate SBOMs and attestations. 40 | # However, we *don't* want Kokoro to collect package-lock.json and *.tgz files 41 | # that happened to be installed with dependencies. 42 | find node_modules -name package-lock.json -o -name "*.tgz" | xargs rm -f -------------------------------------------------------------------------------- /.kokoro/release/common.cfg: -------------------------------------------------------------------------------- 1 | before_action { 2 | fetch_keystore { 3 | keystore_resource { 4 | keystore_config_id: 73713 5 | keyname: "yoshi-automation-github-key" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.kokoro/release/docs-devsite.cfg: -------------------------------------------------------------------------------- 1 | # service account used to publish up-to-date docs. 2 | before_action { 3 | fetch_keystore { 4 | keystore_resource { 5 | keystore_config_id: 73713 6 | keyname: "docuploader_service_account" 7 | } 8 | } 9 | } 10 | 11 | # doc publications use a Python image. 12 | env_vars: { 13 | key: "TRAMPOLINE_IMAGE" 14 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 15 | } 16 | 17 | # Download trampoline resources. 18 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 19 | 20 | # Use the trampoline script to run in docker. 21 | build_file: "nodejs-datastore/.kokoro/trampoline_v2.sh" 22 | 23 | env_vars: { 24 | key: "TRAMPOLINE_BUILD_FILE" 25 | value: "github/nodejs-datastore/.kokoro/release/docs-devsite.sh" 26 | } 27 | -------------------------------------------------------------------------------- /.kokoro/release/docs-devsite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2021 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | if [[ -z "$CREDENTIALS" ]]; then 20 | # if CREDENTIALS are explicitly set, assume we're testing locally 21 | # and don't set NPM_CONFIG_PREFIX. 22 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 23 | export PATH="$PATH:${NPM_CONFIG_PREFIX}/bin" 24 | cd $(dirname $0)/../.. 25 | fi 26 | 27 | npm install 28 | npm install --no-save @google-cloud/cloud-rad@^0.4.0 29 | # publish docs to devsite 30 | npx @google-cloud/cloud-rad . cloud-rad 31 | -------------------------------------------------------------------------------- /.kokoro/release/docs.cfg: -------------------------------------------------------------------------------- 1 | # service account used to publish up-to-date docs. 2 | before_action { 3 | fetch_keystore { 4 | keystore_resource { 5 | keystore_config_id: 73713 6 | keyname: "docuploader_service_account" 7 | } 8 | } 9 | } 10 | 11 | # doc publications use a Python image. 12 | env_vars: { 13 | key: "TRAMPOLINE_IMAGE" 14 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 15 | } 16 | 17 | # Download trampoline resources. 18 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 19 | 20 | # Use the trampoline script to run in docker. 21 | build_file: "nodejs-datastore/.kokoro/trampoline_v2.sh" 22 | 23 | env_vars: { 24 | key: "TRAMPOLINE_BUILD_FILE" 25 | value: "github/nodejs-datastore/.kokoro/release/docs.sh" 26 | } 27 | -------------------------------------------------------------------------------- /.kokoro/release/docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2019 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | # build jsdocs (Python is installed on the Node 18 docker image). 20 | if [[ -z "$CREDENTIALS" ]]; then 21 | # if CREDENTIALS are explicitly set, assume we're testing locally 22 | # and don't set NPM_CONFIG_PREFIX. 23 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 24 | export PATH="$PATH:${NPM_CONFIG_PREFIX}/bin" 25 | cd $(dirname $0)/../.. 26 | fi 27 | npm install 28 | npm run docs 29 | 30 | # create docs.metadata, based on package.json and .repo-metadata.json. 31 | npm i json@9.0.6 -g 32 | python3 -m docuploader create-metadata \ 33 | --name=$(cat .repo-metadata.json | json name) \ 34 | --version=$(cat package.json | json version) \ 35 | --language=$(cat .repo-metadata.json | json language) \ 36 | --distribution-name=$(cat .repo-metadata.json | json distribution_name) \ 37 | --product-page=$(cat .repo-metadata.json | json product_documentation) \ 38 | --github-repository=$(cat .repo-metadata.json | json repo) \ 39 | --issue-tracker=$(cat .repo-metadata.json | json issue_tracker) 40 | cp docs.metadata ./docs/docs.metadata 41 | 42 | # deploy the docs. 43 | if [[ -z "$CREDENTIALS" ]]; then 44 | CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account 45 | fi 46 | if [[ -z "$BUCKET" ]]; then 47 | BUCKET=docs-staging 48 | fi 49 | python3 -m docuploader upload ./docs --credentials $CREDENTIALS --staging-bucket $BUCKET 50 | -------------------------------------------------------------------------------- /.kokoro/release/publish.cfg: -------------------------------------------------------------------------------- 1 | before_action { 2 | fetch_keystore { 3 | keystore_resource { 4 | keystore_config_id: 73713 5 | keyname: "docuploader_service_account" 6 | } 7 | } 8 | } 9 | 10 | before_action { 11 | fetch_keystore { 12 | keystore_resource { 13 | keystore_config_id: 73713 14 | keyname: "google-cloud-npm-token-1" 15 | } 16 | } 17 | } 18 | 19 | env_vars: { 20 | key: "SECRET_MANAGER_KEYS" 21 | value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem" 22 | } 23 | 24 | # Download trampoline resources. 25 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 26 | 27 | # Use the trampoline script to run in docker. 28 | build_file: "nodejs-datastore/.kokoro/trampoline_v2.sh" 29 | 30 | # Configure the docker image for kokoro-trampoline. 31 | env_vars: { 32 | key: "TRAMPOLINE_IMAGE" 33 | value: "gcr.io/cloud-devrel-kokoro-resources/node:18-user" 34 | } 35 | 36 | env_vars: { 37 | key: "TRAMPOLINE_BUILD_FILE" 38 | value: "github/nodejs-datastore/.kokoro/publish.sh" 39 | } 40 | 41 | # Store the packages we uploaded to npmjs.org and their corresponding 42 | # package-lock.jsons in Placer. That way, we have a record of exactly 43 | # what we published, and which version of which tools we used to publish 44 | # it, which we can use to generate SBOMs and attestations. 45 | action { 46 | define_artifacts { 47 | regex: "github/**/*.tgz" 48 | regex: "github/**/package-lock.json" 49 | strip_prefix: "github" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.kokoro/samples-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | # Ensure the npm global directory is writable, otherwise rebuild `npm` 20 | mkdir -p $NPM_CONFIG_PREFIX 21 | npm config -g ls || npm i -g npm@`npm --version` 22 | 23 | # Setup service account credentials. 24 | export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/secret_manager/long-door-651-kokoro-system-test-service-account 25 | export GCLOUD_PROJECT=long-door-651 26 | 27 | cd $(dirname $0)/.. 28 | 29 | # Run a pre-test hook, if a pre-samples-test.sh is in the project 30 | if [ -f .kokoro/pre-samples-test.sh ]; then 31 | set +x 32 | . .kokoro/pre-samples-test.sh 33 | set -x 34 | fi 35 | 36 | if [ -f samples/package.json ]; then 37 | npm install 38 | 39 | # Install and link samples 40 | cd samples/ 41 | npm link ../ 42 | npm install 43 | cd .. 44 | # If tests are running against main branch, configure flakybot 45 | # to open issues on failures: 46 | if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then 47 | export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml 48 | export MOCHA_REPORTER=xunit 49 | cleanup() { 50 | chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot 51 | $KOKORO_GFILE_DIR/linux_amd64/flakybot 52 | } 53 | trap cleanup EXIT HUP 54 | fi 55 | 56 | npm run samples-test 57 | fi 58 | 59 | # codecov combines coverage across integration and unit tests. Include 60 | # the logic below for any environment you wish to collect coverage for: 61 | COVERAGE_NODE=18 62 | if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then 63 | NYC_BIN=./node_modules/nyc/bin/nyc.js 64 | if [ -f "$NYC_BIN" ]; then 65 | $NYC_BIN report || true 66 | fi 67 | bash $KOKORO_GFILE_DIR/codecov.sh 68 | else 69 | echo "coverage is only reported for Node $COVERAGE_NODE" 70 | fi 71 | -------------------------------------------------------------------------------- /.kokoro/system-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | # Setup service account credentials. 22 | export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/secret_manager/long-door-651-kokoro-system-test-service-account 23 | export GCLOUD_PROJECT=long-door-651 24 | 25 | cd $(dirname $0)/.. 26 | 27 | # Run a pre-test hook, if a pre-system-test.sh is in the project 28 | if [ -f .kokoro/pre-system-test.sh ]; then 29 | set +x 30 | . .kokoro/pre-system-test.sh 31 | set -x 32 | fi 33 | 34 | npm install 35 | 36 | # If tests are running against main branch, configure flakybot 37 | # to open issues on failures: 38 | if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then 39 | export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml 40 | export MOCHA_REPORTER=xunit 41 | cleanup() { 42 | chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot 43 | $KOKORO_GFILE_DIR/linux_amd64/flakybot 44 | } 45 | trap cleanup EXIT HUP 46 | fi 47 | 48 | npm run system-test 49 | 50 | # codecov combines coverage across integration and unit tests. Include 51 | # the logic below for any environment you wish to collect coverage for: 52 | COVERAGE_NODE=18 53 | if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then 54 | NYC_BIN=./node_modules/nyc/bin/nyc.js 55 | if [ -f "$NYC_BIN" ]; then 56 | $NYC_BIN report || true 57 | fi 58 | bash $KOKORO_GFILE_DIR/codecov.sh 59 | else 60 | echo "coverage is only reported for Node $COVERAGE_NODE" 61 | fi 62 | -------------------------------------------------------------------------------- /.kokoro/test.bat: -------------------------------------------------------------------------------- 1 | @rem Copyright 2018 Google LLC. All rights reserved. 2 | @rem 3 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 4 | @rem you may not use this file except in compliance with the License. 5 | @rem You may obtain a copy of the License at 6 | @rem 7 | @rem http://www.apache.org/licenses/LICENSE-2.0 8 | @rem 9 | @rem Unless required by applicable law or agreed to in writing, software 10 | @rem distributed under the License is distributed on an "AS IS" BASIS, 11 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | @rem See the License for the specific language governing permissions and 13 | @rem limitations under the License. 14 | 15 | @echo "Starting Windows build" 16 | 17 | cd /d %~dp0 18 | cd .. 19 | 20 | @rem npm path is not currently set in our image, we should fix this next time 21 | @rem we upgrade Node.js in the image: 22 | SET PATH=%PATH%;/cygdrive/c/Program Files/nodejs/npm 23 | 24 | call nvm use 18 25 | call which node 26 | 27 | call npm install || goto :error 28 | call npm run test || goto :error 29 | 30 | goto :EOF 31 | 32 | :error 33 | exit /b 1 34 | -------------------------------------------------------------------------------- /.kokoro/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=${HOME}/.npm-global 20 | 21 | cd $(dirname $0)/.. 22 | 23 | npm install 24 | # If tests are running against main branch, configure flakybot 25 | # to open issues on failures: 26 | if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"nightly"* ]]; then 27 | export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml 28 | export MOCHA_REPORTER=xunit 29 | cleanup() { 30 | chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot 31 | $KOKORO_GFILE_DIR/linux_amd64/flakybot 32 | } 33 | trap cleanup EXIT HUP 34 | fi 35 | # Unit tests exercise the entire API surface, which may include 36 | # deprecation warnings: 37 | export MOCHA_THROW_DEPRECATION=false 38 | npm test 39 | 40 | # codecov combines coverage across integration and unit tests. Include 41 | # the logic below for any environment you wish to collect coverage for: 42 | COVERAGE_NODE=18 43 | if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then 44 | NYC_BIN=./node_modules/nyc/bin/nyc.js 45 | if [ -f "$NYC_BIN" ]; then 46 | $NYC_BIN report || true 47 | fi 48 | bash $KOKORO_GFILE_DIR/codecov.sh 49 | else 50 | echo "coverage is only reported for Node $COVERAGE_NODE" 51 | fi 52 | -------------------------------------------------------------------------------- /.kokoro/trampoline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 Google Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # This file is not used any more, but we keep this file for making it 17 | # easy to roll back. 18 | # TODO: Remove this file from the template. 19 | 20 | set -eo pipefail 21 | 22 | # Always run the cleanup script, regardless of the success of bouncing into 23 | # the container. 24 | function cleanup() { 25 | chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh 26 | ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh 27 | echo "cleanup"; 28 | } 29 | trap cleanup EXIT 30 | 31 | $(dirname $0)/populate-secrets.sh # Secret Manager secrets. 32 | python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" 33 | -------------------------------------------------------------------------------- /.mocharc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | const config = { 15 | "enable-source-maps": true, 16 | "throw-deprecation": true, 17 | "timeout": 10000, 18 | "recursive": true 19 | } 20 | if (process.env.MOCHA_THROW_DEPRECATION === 'false') { 21 | delete config['throw-deprecation']; 22 | } 23 | if (process.env.MOCHA_REPORTER) { 24 | config.reporter = process.env.MOCHA_REPORTER; 25 | } 26 | if (process.env.MOCHA_REPORTER_OUTPUT) { 27 | config['reporter-option'] = `output=${process.env.MOCHA_REPORTER_OUTPUT}`; 28 | } 29 | module.exports = config 30 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "report-dir": "./.coverage", 3 | "reporter": ["text", "lcov"], 4 | "exclude": [ 5 | "**/*-test", 6 | "**/.coverage", 7 | "**/apis", 8 | "**/benchmark", 9 | "**/conformance", 10 | "**/docs", 11 | "**/samples", 12 | "**/scripts", 13 | "**/protos", 14 | "**/test", 15 | "**/*.d.ts", 16 | ".jsdoc.js", 17 | "**/.jsdoc.js", 18 | "karma.conf.js", 19 | "webpack-tests.config.js", 20 | "webpack.config.js" 21 | ], 22 | "exclude-after-remap": false, 23 | "all": true 24 | } 25 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/coverage 3 | test/fixtures 4 | build/ 5 | docs/ 6 | protos/ 7 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | // https://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 | module.exports = { 16 | ...require('gts/.prettierrc.json') 17 | } 18 | -------------------------------------------------------------------------------- /.readme-partials.yml: -------------------------------------------------------------------------------- 1 | body: |- 2 | ### Troubleshooting 3 | #### Emulator returning `DEADLINE_EXCEEDED`, `java.lang.OutOfMemoryError` 4 | *Reference Issue: [#95](https://github.com/googleapis/nodejs-datastore/issues/95)* 5 | 6 | When using the emulator, you may experience errors such as "DEADLINE_EXCEEDED" within your application, corresponding to an error in the emulator: "java.lang.OutOfMemoryError". These errors are unique to the emulator environment and will not persist in production. 7 | 8 | A workaround is available, provided by [@ohmpatel1997](https://github.com/ohmpatel1997) [here](https://github.com/googleapis/nodejs-datastore/issues/95#issuecomment-554387312). 9 | -------------------------------------------------------------------------------- /.repo-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "datastore", 3 | "name_pretty": "Google Cloud Datastore", 4 | "product_documentation": "https://cloud.google.com/datastore/docs", 5 | "client_documentation": "https://cloud.google.com/nodejs/docs/reference/datastore/latest", 6 | "issue_tracker": "https://issuetracker.google.com/savedsearches/559768", 7 | "release_level": "stable", 8 | "language": "nodejs", 9 | "repo": "googleapis/nodejs-datastore", 10 | "distribution_name": "@google-cloud/datastore", 11 | "api_id": "datastore.googleapis.com", 12 | "codeowner_team": "@googleapis/cloud-native-db-dpes @googleapis/api-datastore-sdk", 13 | "api_shortname": "datastore", 14 | "library_type": "GAPIC_COMBO" 15 | } 16 | -------------------------------------------------------------------------------- /.trampolinerc: -------------------------------------------------------------------------------- 1 | # Copyright 2020 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 | # Template for .trampolinerc 16 | 17 | # Add required env vars here. 18 | required_envvars+=( 19 | ) 20 | 21 | # Add env vars which are passed down into the container here. 22 | pass_down_envvars+=( 23 | "AUTORELEASE_PR" 24 | "VERSION" 25 | ) 26 | 27 | # Prevent unintentional override on the default image. 28 | if [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]] && \ 29 | [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then 30 | echo "Please set TRAMPOLINE_IMAGE if you want to upload the Docker image." 31 | exit 1 32 | fi 33 | 34 | # Define the default value if it makes sense. 35 | if [[ -z "${TRAMPOLINE_IMAGE_UPLOAD:-}" ]]; then 36 | TRAMPOLINE_IMAGE_UPLOAD="" 37 | fi 38 | 39 | if [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then 40 | TRAMPOLINE_IMAGE="" 41 | fi 42 | 43 | if [[ -z "${TRAMPOLINE_DOCKERFILE:-}" ]]; then 44 | TRAMPOLINE_DOCKERFILE="" 45 | fi 46 | 47 | if [[ -z "${TRAMPOLINE_BUILD_FILE:-}" ]]; then 48 | TRAMPOLINE_BUILD_FILE="" 49 | fi 50 | 51 | # Secret Manager secrets. 52 | source ${PROJECT_ROOT}/.kokoro/populate-secrets.sh 53 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to become a contributor and submit your own code 2 | 3 | **Table of contents** 4 | 5 | * [Contributor License Agreements](#contributor-license-agreements) 6 | * [Contributing a patch](#contributing-a-patch) 7 | * [Running the tests](#running-the-tests) 8 | * [Releasing the library](#releasing-the-library) 9 | 10 | ## Contributor License Agreements 11 | 12 | We'd love to accept your sample apps and patches! Before we can take them, we 13 | have to jump a couple of legal hurdles. 14 | 15 | Please fill out either the individual or corporate Contributor License Agreement 16 | (CLA). 17 | 18 | * If you are an individual writing original source code and you're sure you 19 | own the intellectual property, then you'll need to sign an [individual CLA](https://developers.google.com/open-source/cla/individual). 20 | * If you work for a company that wants to allow you to contribute your work, 21 | then you'll need to sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate). 22 | 23 | Follow either of the two links above to access the appropriate CLA and 24 | instructions for how to sign and return it. Once we receive it, we'll be able to 25 | accept your pull requests. 26 | 27 | ## Contributing A Patch 28 | 29 | 1. Submit an issue describing your proposed change to the repo in question. 30 | 1. The repo owner will respond to your issue promptly. 31 | 1. If your proposed change is accepted, and you haven't already done so, sign a 32 | Contributor License Agreement (see details above). 33 | 1. Fork the desired repo, develop and test your code changes. 34 | 1. Ensure that your code adheres to the existing style in the code to which 35 | you are contributing. 36 | 1. Ensure that your code has an appropriate set of tests which all pass. 37 | 1. Title your pull request following [Conventional Commits](https://www.conventionalcommits.org/) styling. 38 | 1. Submit a pull request. 39 | 40 | ### Before you begin 41 | 42 | 1. [Select or create a Cloud Platform project][projects]. 43 | 1. [Enable the Google Cloud Datastore API][enable_api]. 44 | 1. [Set up authentication with a service account][auth] so you can access the 45 | API from your local workstation. 46 | 47 | 48 | ## Running the tests 49 | 50 | 1. [Prepare your environment for Node.js setup][setup]. 51 | 52 | 1. Install dependencies: 53 | 54 | npm install 55 | 56 | 1. Run the tests: 57 | 58 | # Run unit tests. 59 | npm test 60 | 61 | # Run sample integration tests. 62 | npm run samples-test 63 | 64 | # Run all system tests. 65 | npm run system-test 66 | 67 | 1. Lint (and maybe fix) any changes: 68 | 69 | npm run fix 70 | 71 | [setup]: https://cloud.google.com/nodejs/docs/setup 72 | [projects]: https://console.cloud.google.com/project 73 | [billing]: https://support.google.com/cloud/answer/6293499#enable-billing 74 | [enable_api]: https://console.cloud.google.com/flows/enableapi?apiid=datastore.googleapis.com 75 | [auth]: https://cloud.google.com/docs/authentication/getting-started -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). 4 | 5 | The Google Security Team will respond within 5 working days of your report on g.co/vulnz. 6 | 7 | We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. 8 | -------------------------------------------------------------------------------- /linkinator.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "recurse": true, 3 | "skip": [ 4 | "https://codecov.io/gh/googleapis/", 5 | "www.googleapis.com", 6 | "img.shields.io", 7 | "https://console.cloud.google.com/cloudshell", 8 | "https://support.google.com" 9 | ], 10 | "silent": true, 11 | "concurrency": 5, 12 | "retry": true, 13 | "retryErrors": true, 14 | "retryErrorsCount": 5, 15 | "retryErrorsJitter": 3000 16 | } 17 | -------------------------------------------------------------------------------- /mock-server/README.md: -------------------------------------------------------------------------------- 1 | The mock server code in this folder is used for observing requests that will 2 | be sent to the server. When the server sends back a vague error it is often 3 | because the request it receives is incorrect so it is crucial to have a tool to 4 | view the request in order to know what client library code needs to change. 5 | 6 | The steps to follow for using the mock server is: 7 | 1. Take a look at `test/try-server.ts` to see how the mock server is used. 8 | 2. In the system test you want to debug, change `it` to `it.only` to isolate that test. 9 | 3. In this test, surround the code with `startServer(async () => {` 10 | 4. Ensure `apiEndpoint: 'localhost:50051'` is passed into the datastore client that is used for this test. 11 | 5. If the system test hits an endpoint other than `runQuery` then in `datastore-server.ts`, change `.addService(service, {runQuery: grpcEndpoint})` to `.addService(service, {<>: grpcEndpoint})` 12 | 6. Set a breakpoint on the line that says `SET A BREAKPOINT HERE` in `datastore-server.ts` 13 | 7. Debug with system tests (Enter `npm run system-test -- --inspect` in terminal) 14 | 15 | 16 | -------------------------------------------------------------------------------- /mock-server/datastore-server.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | const {dirname, resolve} = require('node:path'); 16 | 17 | const PROTO_PATH = __dirname + '/../protos/google/datastore/v1/datastore.proto'; 18 | const DATASTORE_PROTOS = __dirname + '/../protos'; 19 | const GAX_PROTOS_DIR = resolve( 20 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 21 | // @ts-ignore 22 | // eslint-disable-next-line n/no-extraneous-require 23 | dirname(require.resolve('google-gax')), 24 | '../protos', 25 | ); 26 | 27 | const grpc = require('@grpc/grpc-js'); 28 | const protoLoader = require('@grpc/proto-loader'); 29 | 30 | const packageDefinition = protoLoader.loadSync(PROTO_PATH, { 31 | keepCase: true, 32 | longs: String, 33 | enums: String, 34 | defaults: true, 35 | oneofs: true, 36 | includeDirs: [DATASTORE_PROTOS, GAX_PROTOS_DIR], 37 | }); 38 | const descriptor = grpc.loadPackageDefinition(packageDefinition); 39 | 40 | /** 41 | * Implements the runQuery RPC method. 42 | */ 43 | function grpcEndpoint( 44 | call: {}, 45 | callback: (arg1: string | null, arg2: {}) => {}, 46 | ) { 47 | // SET A BREAKPOINT HERE AND EXPLORE `call` TO SEE THE REQUEST. 48 | callback(null, {message: 'Hello'}); 49 | } 50 | 51 | /** 52 | * Starts an RPC server that receives requests for datastore 53 | */ 54 | export function startServer(cb: () => void) { 55 | const server = new grpc.Server(); 56 | const service = descriptor.google.datastore.v1.Datastore.service; 57 | // On the next line, change runQuery to the grpc method you want to investigate 58 | server.addService(service, {runQuery: grpcEndpoint}); 59 | server.bindAsync( 60 | '0.0.0.0:50051', 61 | grpc.ServerCredentials.createInsecure(), 62 | () => { 63 | console.log('server started'); 64 | cb(); 65 | }, 66 | ); 67 | } 68 | -------------------------------------------------------------------------------- /mock-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grpc-examples", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "@grpc/proto-loader": "^0.5.0", 6 | "async": "^1.5.2", 7 | "google-protobuf": "^3.0.0", 8 | "@grpc/grpc-js": "^1.1.0", 9 | "lodash": "^4.6.1", 10 | "minimist": "^1.2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /owlbot.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 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 | # https://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 | import synthtool as s 16 | import synthtool.gcp as gcp 17 | import synthtool.languages.node as node 18 | import logging 19 | from pathlib import Path 20 | from synthtool import _tracked_paths 21 | from synthtool import shell 22 | import shutil 23 | 24 | logging.basicConfig(level=logging.DEBUG) 25 | 26 | staging = Path("owl-bot-staging") 27 | 28 | if staging.is_dir(): 29 | logging.info(f"Copying files from staging directory ${staging}.") 30 | 31 | # Copy the datastore library. 32 | for version in ['v1']: 33 | library = staging / version 34 | _tracked_paths.add(library) 35 | s.copy([library],excludes=[ 36 | 'package.json', 'README.md', 'src/index.ts', 'src/v1/index.ts']) 37 | 38 | # Copy the admin library. 39 | for version in ['v1']: 40 | library = staging / 'admin' / version 41 | _tracked_paths.add(library) 42 | s.copy([library],excludes=[ 43 | 'package.json', 'README.md', 'src/index.ts', 'src/v1/index.ts', 'tsconfig.json', 'tslint.json', 44 | 'system-test/fixtures/sample/src/index.ts', 'system-test/fixtures/sample/src/index.js', 45 | '.jsdoc.js', 'webpack.config.js']) 46 | 47 | # Patch the code. 48 | system_test_files = ['system-test/fixtures/sample/src/index.ts', 'system-test/fixtures/sample/src/index.js'] 49 | for file in system_test_files: 50 | s.replace(file, 'DatastoreClient', 'Datastore') 51 | s.replace(file, 'client.close', '// client.close'); # does not work with the manual layer 52 | 53 | # The staging directory should never be merged into the main branch. 54 | shutil.rmtree(staging) 55 | 56 | common_templates = gcp.CommonTemplates() 57 | templates = common_templates.node_library(source_location="build/src") 58 | s.copy(templates) 59 | 60 | node.postprocess_gapic_library_hermetic() 61 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@google-cloud/datastore", 3 | "version": "10.0.1", 4 | "description": "Cloud Datastore Client Library for Node.js", 5 | "keywords": [ 6 | "google apis client", 7 | "google api client", 8 | "google apis", 9 | "google api", 10 | "google", 11 | "google cloud platform", 12 | "google cloud", 13 | "cloud", 14 | "google datastore", 15 | "datastore" 16 | ], 17 | "repository": "googleapis/nodejs-datastore", 18 | "license": "Apache-2.0", 19 | "author": "Google LLC.", 20 | "main": "build/src/index.js", 21 | "files": [ 22 | "build/protos", 23 | "build/src" 24 | ], 25 | "scripts": { 26 | "clean": "gts clean", 27 | "compile": "tsc -p . && cp -r proto* build/ && cp -r system-test/data build/system-test", 28 | "compile-protos": "compileProtos src", 29 | "docs": "jsdoc -c .jsdoc.js", 30 | "predocs-test": "npm run docs", 31 | "docs-test": "linkinator docs", 32 | "fix": "gts fix", 33 | "prelint": "cd samples; npm link ../; npm install", 34 | "lint": "gts check", 35 | "prepare": "npm run compile-protos && npm run compile", 36 | "samples-test": "cd samples/ && npm link ../ && npm install && npm test && cd ../", 37 | "presystem-test": "npm run compile", 38 | "system-test": "mocha build/system-test --timeout 600000", 39 | "pretest": "npm run compile", 40 | "test": "c8 mocha build/test", 41 | "precompile": "gts clean" 42 | }, 43 | "dependencies": { 44 | "@google-cloud/promisify": "^5.0.0", 45 | "arrify": "^2.0.0", 46 | "async-mutex": "^0.5.0", 47 | "concat-stream": "^2.0.0", 48 | "extend": "^3.0.2", 49 | "google-gax": "^5.0.2-rc.1", 50 | "is": "^3.3.0", 51 | "protobufjs": "7.0.0", 52 | "split-array-stream": "^2.0.0", 53 | "stream-events": "^1.0.5" 54 | }, 55 | "devDependencies": { 56 | "@google-cloud/storage": "^7.16.0", 57 | "@types/extend": "^3.0.4", 58 | "@types/is": "^0.0.25", 59 | "@types/js-yaml": "^4.0.9", 60 | "@types/mocha": "^10.0.10", 61 | "@types/node": "^22.15.3", 62 | "@types/proxyquire": "^1.3.31", 63 | "@types/sinon": "^17.0.4", 64 | "async": "^3.2.6", 65 | "c8": "^10.1.3", 66 | "gapic-tools": "^1.0.2", 67 | "gts": "^6.0.2", 68 | "js-yaml": "^4.1.0", 69 | "jsdoc": "^4.0.4", 70 | "jsdoc-fresh": "^3.0.0", 71 | "jsdoc-region-tag": "^3.0.0", 72 | "linkinator": "^6.1.2", 73 | "mocha": "^11.1.0", 74 | "null-loader": "^4.0.1", 75 | "p-queue": "^8.1.0", 76 | "pack-n-play": "^3.0.1", 77 | "proxyquire": "^2.1.3", 78 | "sinon": "^20.0.0", 79 | "ts-loader": "^9.5.2", 80 | "typescript": "^5.8.3", 81 | "webpack-cli": "^6.0.1" 82 | }, 83 | "engines": { 84 | "node": ">=18" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /protos/app_engine_key.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | message Reference { 4 | required string app = 13; 5 | optional string namespace = 20; 6 | required Path path = 14; 7 | optional string database_id = 23; 8 | } 9 | 10 | message Path { 11 | repeated group Element = 1 { 12 | required string type = 2; 13 | optional int64 id = 3; 14 | optional string name = 4; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /protos/google/cloud/common_resources.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | // This file contains stub messages for common resources in GCP. 16 | // It is not intended to be directly generated, and is instead used by 17 | // other tooling to be able to match common resource patterns. 18 | syntax = "proto3"; 19 | 20 | package google.cloud; 21 | 22 | import "google/api/resource.proto"; 23 | 24 | 25 | option (google.api.resource_definition) = { 26 | type: "cloudresourcemanager.googleapis.com/Project" 27 | pattern: "projects/{project}" 28 | }; 29 | 30 | 31 | option (google.api.resource_definition) = { 32 | type: "cloudresourcemanager.googleapis.com/Organization" 33 | pattern: "organizations/{organization}" 34 | }; 35 | 36 | 37 | option (google.api.resource_definition) = { 38 | type: "cloudresourcemanager.googleapis.com/Folder" 39 | pattern: "folders/{folder}" 40 | }; 41 | 42 | 43 | option (google.api.resource_definition) = { 44 | type: "cloudbilling.googleapis.com/BillingAccount" 45 | pattern: "billingAccounts/{billing_account}" 46 | }; 47 | 48 | option (google.api.resource_definition) = { 49 | type: "locations.googleapis.com/Location" 50 | pattern: "projects/{project}/locations/{location}" 51 | }; 52 | 53 | -------------------------------------------------------------------------------- /protos/google/datastore/v1/aggregation_result.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | syntax = "proto3"; 16 | 17 | package google.datastore.v1; 18 | 19 | import "google/datastore/v1/entity.proto"; 20 | import "google/datastore/v1/query.proto"; 21 | import "google/protobuf/timestamp.proto"; 22 | 23 | option csharp_namespace = "Google.Cloud.Datastore.V1"; 24 | option go_package = "cloud.google.com/go/datastore/apiv1/datastorepb;datastorepb"; 25 | option java_multiple_files = true; 26 | option java_outer_classname = "AggregationResultProto"; 27 | option java_package = "com.google.datastore.v1"; 28 | option php_namespace = "Google\\Cloud\\Datastore\\V1"; 29 | option ruby_package = "Google::Cloud::Datastore::V1"; 30 | 31 | // The result of a single bucket from a Datastore aggregation query. 32 | // 33 | // The keys of `aggregate_properties` are the same for all results in an 34 | // aggregation query, unlike entity queries which can have different fields 35 | // present for each result. 36 | message AggregationResult { 37 | // The result of the aggregation functions, ex: `COUNT(*) AS total_entities`. 38 | // 39 | // The key is the 40 | // [alias][google.datastore.v1.AggregationQuery.Aggregation.alias] assigned to 41 | // the aggregation function on input and the size of this map equals the 42 | // number of aggregation functions in the query. 43 | map aggregate_properties = 2; 44 | } 45 | 46 | // A batch of aggregation results produced by an aggregation query. 47 | message AggregationResultBatch { 48 | // The aggregation results for this batch. 49 | repeated AggregationResult aggregation_results = 1; 50 | 51 | // The state of the query after the current batch. 52 | // Only COUNT(*) aggregations are supported in the initial launch. Therefore, 53 | // expected result type is limited to `NO_MORE_RESULTS`. 54 | QueryResultBatch.MoreResultsType more_results = 2; 55 | 56 | // Read timestamp this batch was returned from. 57 | // 58 | // In a single transaction, subsequent query result batches for the same query 59 | // can have a greater timestamp. Each batch's read timestamp 60 | // is valid for all preceding batches. 61 | google.protobuf.Timestamp read_time = 3; 62 | } 63 | -------------------------------------------------------------------------------- /protos/google/datastore/v1/query_profile.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | syntax = "proto3"; 16 | 17 | package google.datastore.v1; 18 | 19 | import "google/api/field_behavior.proto"; 20 | import "google/protobuf/duration.proto"; 21 | import "google/protobuf/struct.proto"; 22 | 23 | option csharp_namespace = "Google.Cloud.Datastore.V1"; 24 | option go_package = "cloud.google.com/go/datastore/apiv1/datastorepb;datastorepb"; 25 | option java_multiple_files = true; 26 | option java_outer_classname = "QueryProfileProto"; 27 | option java_package = "com.google.datastore.v1"; 28 | option php_namespace = "Google\\Cloud\\Datastore\\V1"; 29 | option ruby_package = "Google::Cloud::Datastore::V1"; 30 | 31 | // Specification of the Datastore Query Profile fields. 32 | 33 | // Explain options for the query. 34 | message ExplainOptions { 35 | // Optional. Whether to execute this query. 36 | // 37 | // When false (the default), the query will be planned, returning only 38 | // metrics from the planning stages. 39 | // 40 | // When true, the query will be planned and executed, returning the full 41 | // query results along with both planning and execution stage metrics. 42 | bool analyze = 1 [(google.api.field_behavior) = OPTIONAL]; 43 | } 44 | 45 | // Explain metrics for the query. 46 | message ExplainMetrics { 47 | // Planning phase information for the query. 48 | PlanSummary plan_summary = 1; 49 | 50 | // Aggregated stats from the execution of the query. Only present when 51 | // [ExplainOptions.analyze][google.datastore.v1.ExplainOptions.analyze] is set 52 | // to true. 53 | ExecutionStats execution_stats = 2; 54 | } 55 | 56 | // Planning phase information for the query. 57 | message PlanSummary { 58 | // The indexes selected for the query. For example: 59 | // [ 60 | // {"query_scope": "Collection", "properties": "(foo ASC, __name__ ASC)"}, 61 | // {"query_scope": "Collection", "properties": "(bar ASC, __name__ ASC)"} 62 | // ] 63 | repeated google.protobuf.Struct indexes_used = 1; 64 | } 65 | 66 | // Execution statistics for the query. 67 | message ExecutionStats { 68 | // Total number of results returned, including documents, projections, 69 | // aggregation results, keys. 70 | int64 results_returned = 1; 71 | 72 | // Total time to execute the query in the backend. 73 | google.protobuf.Duration execution_duration = 3; 74 | 75 | // Total billable read operations. 76 | int64 read_operations = 4; 77 | 78 | // Debugging statistics from the execution of the query. Note that the 79 | // debugging stats are subject to change as Firestore evolves. It could 80 | // include: 81 | // { 82 | // "indexes_entries_scanned": "1000", 83 | // "documents_scanned": "20", 84 | // "billing_details" : { 85 | // "documents_billable": "20", 86 | // "index_entries_billable": "1000", 87 | // "min_query_cost": "0" 88 | // } 89 | // } 90 | google.protobuf.Struct debug_stats = 5; 91 | } 92 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | "docker:disable", 5 | ":disableDependencyDashboard" 6 | ], 7 | "constraintsFiltering": "strict", 8 | "pinVersions": false, 9 | "rebaseStalePrs": true, 10 | "schedule": [ 11 | "after 9am and before 3pm" 12 | ], 13 | "gitAuthor": null, 14 | "packageRules": [ 15 | { 16 | "extends": "packages:linters", 17 | "groupName": "linters" 18 | } 19 | ], 20 | "ignoreDeps": ["typescript"] 21 | } 22 | -------------------------------------------------------------------------------- /samples/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | rules: 3 | no-console: off 4 | require-atomic-updates: off 5 | -------------------------------------------------------------------------------- /samples/error.js: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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: error sample 19 | // description: sample show how to handle and process error 20 | // usage: node error.js 21 | 22 | const {Datastore} = require('@google-cloud/datastore'); 23 | 24 | // [START error] 25 | function main() { 26 | // Creates a client 27 | const datastore = new Datastore(); 28 | 29 | const query = datastore.createQuery(['Company']).start('badrequest'); 30 | 31 | async function runQuery() { 32 | try { 33 | const [result] = await datastore.runQuery(query); 34 | // etc., etc. 35 | return result; 36 | } catch (error) { 37 | // do something with error. 38 | console.log(error.code); // 3 39 | //Forward the error to caller 40 | throw error; 41 | } 42 | } 43 | 44 | runQuery().catch(err => { 45 | console.log(err.message); // "Error parsing protocol message" 46 | }); 47 | // [END error] 48 | } 49 | 50 | main(...process.argv.slice(2)); 51 | -------------------------------------------------------------------------------- /samples/export.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | async function main(bucket = 'YOUR_BUCKET_NAME') { 16 | // [START datastore_admin_entities_export] 17 | const {Datastore} = require('@google-cloud/datastore'); 18 | const datastore = new Datastore(); 19 | 20 | async function exportEntities() { 21 | /** 22 | * TODO(developer): Uncomment these variables before running the sample. 23 | */ 24 | // const bucket = 'YOUR_BUCKET_NAME'; 25 | 26 | const [exportOperation] = await datastore.export({bucket}); 27 | await exportOperation.promise(); 28 | 29 | // The export operation has created a new file in your bucket, e.g. 30 | // gs://{YOUR_BUCKET_NAME}/{timestamp}/{timestamp}.overall_export.metadata 31 | console.log(`Export file created: ${exportOperation.result.outputUrl}`); 32 | 33 | // You may also choose to include only specific kinds and namespaces. 34 | const [specificExportOperation] = await datastore.export({ 35 | bucket, 36 | kinds: ['Employee', 'Task'], 37 | namespaces: ['Company'], 38 | }); 39 | await specificExportOperation.promise(); 40 | console.log(specificExportOperation.result.outputUrl); 41 | } 42 | 43 | exportEntities(); 44 | // [END datastore_admin_entities_export] 45 | } 46 | 47 | const args = process.argv.slice(2); 48 | main(...args).catch(console.error); 49 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore.allocate_ids.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId, keys) { 24 | // [START datastore_v1_generated_Datastore_AllocateIds_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. The ID of the project against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The ID of the database against which to make the request. 37 | * '(default)' is not allowed; please use empty string '' to refer the default 38 | * database. 39 | */ 40 | // const databaseId = 'abc123' 41 | /** 42 | * Required. A list of keys with incomplete key paths for which to allocate 43 | * IDs. No key may be reserved/read-only. 44 | */ 45 | // const keys = [1,2,3,4] 46 | 47 | // Imports the Datastore library 48 | const {DatastoreClient} = require('@google-cloud/datastore').v1; 49 | 50 | // Instantiates a client 51 | const datastoreClient = new DatastoreClient(); 52 | 53 | async function callAllocateIds() { 54 | // Construct request 55 | const request = { 56 | projectId, 57 | keys, 58 | }; 59 | 60 | // Run request 61 | const response = await datastoreClient.allocateIds(request); 62 | console.log(response); 63 | } 64 | 65 | callAllocateIds(); 66 | // [END datastore_v1_generated_Datastore_AllocateIds_async] 67 | } 68 | 69 | process.on('unhandledRejection', err => { 70 | console.error(err.message); 71 | process.exitCode = 1; 72 | }); 73 | main(...process.argv.slice(2)); 74 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore.begin_transaction.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId) { 24 | // [START datastore_v1_generated_Datastore_BeginTransaction_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. The ID of the project against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The ID of the database against which to make the request. 37 | * '(default)' is not allowed; please use empty string '' to refer the default 38 | * database. 39 | */ 40 | // const databaseId = 'abc123' 41 | /** 42 | * Options for a new transaction. 43 | */ 44 | // const transactionOptions = {} 45 | 46 | // Imports the Datastore library 47 | const {DatastoreClient} = require('@google-cloud/datastore').v1; 48 | 49 | // Instantiates a client 50 | const datastoreClient = new DatastoreClient(); 51 | 52 | async function callBeginTransaction() { 53 | // Construct request 54 | const request = { 55 | projectId, 56 | }; 57 | 58 | // Run request 59 | const response = await datastoreClient.beginTransaction(request); 60 | console.log(response); 61 | } 62 | 63 | callBeginTransaction(); 64 | // [END datastore_v1_generated_Datastore_BeginTransaction_async] 65 | } 66 | 67 | process.on('unhandledRejection', err => { 68 | console.error(err.message); 69 | process.exitCode = 1; 70 | }); 71 | main(...process.argv.slice(2)); 72 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore.commit.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId) { 24 | // [START datastore_v1_generated_Datastore_Commit_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. The ID of the project against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The ID of the database against which to make the request. 37 | * '(default)' is not allowed; please use empty string '' to refer the default 38 | * database. 39 | */ 40 | // const databaseId = 'abc123' 41 | /** 42 | * The type of commit to perform. Defaults to `TRANSACTIONAL`. 43 | */ 44 | // const mode = {} 45 | /** 46 | * The identifier of the transaction associated with the commit. A 47 | * transaction identifier is returned by a call to 48 | * Datastore.BeginTransaction google.datastore.v1.Datastore.BeginTransaction. 49 | */ 50 | // const transaction = Buffer.from('string') 51 | /** 52 | * Options for beginning a new transaction for this request. 53 | * The transaction is committed when the request completes. If specified, 54 | * TransactionOptions.mode google.datastore.v1.TransactionOptions must be 55 | * TransactionOptions.ReadWrite google.datastore.v1.TransactionOptions.ReadWrite. 56 | */ 57 | // const singleUseTransaction = {} 58 | /** 59 | * The mutations to perform. 60 | * When mode is `TRANSACTIONAL`, mutations affecting a single entity are 61 | * applied in order. The following sequences of mutations affecting a single 62 | * entity are not permitted in a single `Commit` request: 63 | * - `insert` followed by `insert` 64 | * - `update` followed by `insert` 65 | * - `upsert` followed by `insert` 66 | * - `delete` followed by `update` 67 | * When mode is `NON_TRANSACTIONAL`, no two mutations may affect a single 68 | * entity. 69 | */ 70 | // const mutations = [1,2,3,4] 71 | 72 | // Imports the Datastore library 73 | const {DatastoreClient} = require('@google-cloud/datastore').v1; 74 | 75 | // Instantiates a client 76 | const datastoreClient = new DatastoreClient(); 77 | 78 | async function callCommit() { 79 | // Construct request 80 | const request = { 81 | projectId, 82 | }; 83 | 84 | // Run request 85 | const response = await datastoreClient.commit(request); 86 | console.log(response); 87 | } 88 | 89 | callCommit(); 90 | // [END datastore_v1_generated_Datastore_Commit_async] 91 | } 92 | 93 | process.on('unhandledRejection', err => { 94 | console.error(err.message); 95 | process.exitCode = 1; 96 | }); 97 | main(...process.argv.slice(2)); 98 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore.lookup.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId, keys) { 24 | // [START datastore_v1_generated_Datastore_Lookup_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. The ID of the project against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The ID of the database against which to make the request. 37 | * '(default)' is not allowed; please use empty string '' to refer the default 38 | * database. 39 | */ 40 | // const databaseId = 'abc123' 41 | /** 42 | * The options for this lookup request. 43 | */ 44 | // const readOptions = {} 45 | /** 46 | * Required. Keys of entities to look up. 47 | */ 48 | // const keys = [1,2,3,4] 49 | /** 50 | * The properties to return. Defaults to returning all properties. 51 | * If this field is set and an entity has a property not referenced in the 52 | * mask, it will be absent from LookupResponse.found.entity.properties . 53 | * The entity's key is always returned. 54 | */ 55 | // const propertyMask = {} 56 | 57 | // Imports the Datastore library 58 | const {DatastoreClient} = require('@google-cloud/datastore').v1; 59 | 60 | // Instantiates a client 61 | const datastoreClient = new DatastoreClient(); 62 | 63 | async function callLookup() { 64 | // Construct request 65 | const request = { 66 | projectId, 67 | keys, 68 | }; 69 | 70 | // Run request 71 | const response = await datastoreClient.lookup(request); 72 | console.log(response); 73 | } 74 | 75 | callLookup(); 76 | // [END datastore_v1_generated_Datastore_Lookup_async] 77 | } 78 | 79 | process.on('unhandledRejection', err => { 80 | console.error(err.message); 81 | process.exitCode = 1; 82 | }); 83 | main(...process.argv.slice(2)); 84 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore.reserve_ids.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId, keys) { 24 | // [START datastore_v1_generated_Datastore_ReserveIds_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. The ID of the project against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The ID of the database against which to make the request. 37 | * '(default)' is not allowed; please use empty string '' to refer the default 38 | * database. 39 | */ 40 | // const databaseId = 'abc123' 41 | /** 42 | * Required. A list of keys with complete key paths whose numeric IDs should 43 | * not be auto-allocated. 44 | */ 45 | // const keys = [1,2,3,4] 46 | 47 | // Imports the Datastore library 48 | const {DatastoreClient} = require('@google-cloud/datastore').v1; 49 | 50 | // Instantiates a client 51 | const datastoreClient = new DatastoreClient(); 52 | 53 | async function callReserveIds() { 54 | // Construct request 55 | const request = { 56 | projectId, 57 | keys, 58 | }; 59 | 60 | // Run request 61 | const response = await datastoreClient.reserveIds(request); 62 | console.log(response); 63 | } 64 | 65 | callReserveIds(); 66 | // [END datastore_v1_generated_Datastore_ReserveIds_async] 67 | } 68 | 69 | process.on('unhandledRejection', err => { 70 | console.error(err.message); 71 | process.exitCode = 1; 72 | }); 73 | main(...process.argv.slice(2)); 74 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore.rollback.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId, transaction) { 24 | // [START datastore_v1_generated_Datastore_Rollback_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. The ID of the project against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The ID of the database against which to make the request. 37 | * '(default)' is not allowed; please use empty string '' to refer the default 38 | * database. 39 | */ 40 | // const databaseId = 'abc123' 41 | /** 42 | * Required. The transaction identifier, returned by a call to 43 | * Datastore.BeginTransaction google.datastore.v1.Datastore.BeginTransaction. 44 | */ 45 | // const transaction = Buffer.from('string') 46 | 47 | // Imports the Datastore library 48 | const {DatastoreClient} = require('@google-cloud/datastore').v1; 49 | 50 | // Instantiates a client 51 | const datastoreClient = new DatastoreClient(); 52 | 53 | async function callRollback() { 54 | // Construct request 55 | const request = { 56 | projectId, 57 | transaction, 58 | }; 59 | 60 | // Run request 61 | const response = await datastoreClient.rollback(request); 62 | console.log(response); 63 | } 64 | 65 | callRollback(); 66 | // [END datastore_v1_generated_Datastore_Rollback_async] 67 | } 68 | 69 | process.on('unhandledRejection', err => { 70 | console.error(err.message); 71 | process.exitCode = 1; 72 | }); 73 | main(...process.argv.slice(2)); 74 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore.run_aggregation_query.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId) { 24 | // [START datastore_v1_generated_Datastore_RunAggregationQuery_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. The ID of the project against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The ID of the database against which to make the request. 37 | * '(default)' is not allowed; please use empty string '' to refer the default 38 | * database. 39 | */ 40 | // const databaseId = 'abc123' 41 | /** 42 | * Entities are partitioned into subsets, identified by a partition ID. 43 | * Queries are scoped to a single partition. 44 | * This partition ID is normalized with the standard default context 45 | * partition ID. 46 | */ 47 | // const partitionId = {} 48 | /** 49 | * The options for this query. 50 | */ 51 | // const readOptions = {} 52 | /** 53 | * The query to run. 54 | */ 55 | // const aggregationQuery = {} 56 | /** 57 | * The GQL query to run. This query must be an aggregation query. 58 | */ 59 | // const gqlQuery = {} 60 | /** 61 | * Optional. Explain options for the query. If set, additional query 62 | * statistics will be returned. If not, only query results will be returned. 63 | */ 64 | // const explainOptions = {} 65 | 66 | // Imports the Datastore library 67 | const {DatastoreClient} = require('@google-cloud/datastore').v1; 68 | 69 | // Instantiates a client 70 | const datastoreClient = new DatastoreClient(); 71 | 72 | async function callRunAggregationQuery() { 73 | // Construct request 74 | const request = { 75 | projectId, 76 | }; 77 | 78 | // Run request 79 | const response = await datastoreClient.runAggregationQuery(request); 80 | console.log(response); 81 | } 82 | 83 | callRunAggregationQuery(); 84 | // [END datastore_v1_generated_Datastore_RunAggregationQuery_async] 85 | } 86 | 87 | process.on('unhandledRejection', err => { 88 | console.error(err.message); 89 | process.exitCode = 1; 90 | }); 91 | main(...process.argv.slice(2)); 92 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore.run_query.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId) { 24 | // [START datastore_v1_generated_Datastore_RunQuery_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. The ID of the project against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The ID of the database against which to make the request. 37 | * '(default)' is not allowed; please use empty string '' to refer the default 38 | * database. 39 | */ 40 | // const databaseId = 'abc123' 41 | /** 42 | * Entities are partitioned into subsets, identified by a partition ID. 43 | * Queries are scoped to a single partition. 44 | * This partition ID is normalized with the standard default context 45 | * partition ID. 46 | */ 47 | // const partitionId = {} 48 | /** 49 | * The options for this query. 50 | */ 51 | // const readOptions = {} 52 | /** 53 | * The query to run. 54 | */ 55 | // const query = {} 56 | /** 57 | * The GQL query to run. This query must be a non-aggregation query. 58 | */ 59 | // const gqlQuery = {} 60 | /** 61 | * The properties to return. 62 | * This field must not be set for a projection query. 63 | * See 64 | * LookupRequest.property_mask google.datastore.v1.LookupRequest.property_mask. 65 | */ 66 | // const propertyMask = {} 67 | /** 68 | * Optional. Explain options for the query. If set, additional query 69 | * statistics will be returned. If not, only query results will be returned. 70 | */ 71 | // const explainOptions = {} 72 | 73 | // Imports the Datastore library 74 | const {DatastoreClient} = require('@google-cloud/datastore').v1; 75 | 76 | // Instantiates a client 77 | const datastoreClient = new DatastoreClient(); 78 | 79 | async function callRunQuery() { 80 | // Construct request 81 | const request = { 82 | projectId, 83 | }; 84 | 85 | // Run request 86 | const response = await datastoreClient.runQuery(request); 87 | console.log(response); 88 | } 89 | 90 | callRunQuery(); 91 | // [END datastore_v1_generated_Datastore_RunQuery_async] 92 | } 93 | 94 | process.on('unhandledRejection', err => { 95 | console.error(err.message); 96 | process.exitCode = 1; 97 | }); 98 | main(...process.argv.slice(2)); 99 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore_admin.create_index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main() { 24 | // [START datastore_v1_generated_DatastoreAdmin_CreateIndex_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Project ID against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The index to create. The name and state fields are output only and will be 37 | * ignored. Single property indexes cannot be created or deleted. 38 | */ 39 | // const index = {} 40 | 41 | // Imports the Admin library 42 | const {DatastoreAdminClient} = require('@google-cloud/datastore-admin').v1; 43 | 44 | // Instantiates a client 45 | const adminClient = new DatastoreAdminClient(); 46 | 47 | async function callCreateIndex() { 48 | // Construct request 49 | const request = { 50 | }; 51 | 52 | // Run request 53 | const [operation] = await adminClient.createIndex(request); 54 | const [response] = await operation.promise(); 55 | console.log(response); 56 | } 57 | 58 | callCreateIndex(); 59 | // [END datastore_v1_generated_DatastoreAdmin_CreateIndex_async] 60 | } 61 | 62 | process.on('unhandledRejection', err => { 63 | console.error(err.message); 64 | process.exitCode = 1; 65 | }); 66 | main(...process.argv.slice(2)); 67 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore_admin.delete_index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main() { 24 | // [START datastore_v1_generated_DatastoreAdmin_DeleteIndex_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Project ID against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The resource ID of the index to delete. 37 | */ 38 | // const indexId = 'abc123' 39 | 40 | // Imports the Admin library 41 | const {DatastoreAdminClient} = require('@google-cloud/datastore-admin').v1; 42 | 43 | // Instantiates a client 44 | const adminClient = new DatastoreAdminClient(); 45 | 46 | async function callDeleteIndex() { 47 | // Construct request 48 | const request = { 49 | }; 50 | 51 | // Run request 52 | const [operation] = await adminClient.deleteIndex(request); 53 | const [response] = await operation.promise(); 54 | console.log(response); 55 | } 56 | 57 | callDeleteIndex(); 58 | // [END datastore_v1_generated_DatastoreAdmin_DeleteIndex_async] 59 | } 60 | 61 | process.on('unhandledRejection', err => { 62 | console.error(err.message); 63 | process.exitCode = 1; 64 | }); 65 | main(...process.argv.slice(2)); 66 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore_admin.export_entities.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId, outputUrlPrefix) { 24 | // [START datastore_v1_generated_DatastoreAdmin_ExportEntities_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. Project ID against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * Client-assigned labels. 37 | */ 38 | // const labels = [1,2,3,4] 39 | /** 40 | * Description of what data from the project is included in the export. 41 | */ 42 | // const entityFilter = {} 43 | /** 44 | * Required. Location for the export metadata and data files. 45 | * The full resource URL of the external storage location. Currently, only 46 | * Google Cloud Storage is supported. So output_url_prefix should be of the 47 | * form: `gs://BUCKET_NAME/NAMESPACE_PATH`, where `BUCKET_NAME` is the 48 | * name of the Cloud Storage bucket and `NAMESPACE_PATH` is an optional Cloud 49 | * Storage namespace path (this is not a Cloud Datastore namespace). For more 50 | * information about Cloud Storage namespace paths, see 51 | * Object name 52 | * considerations (https://cloud.google.com/storage/docs/naming#object-considerations). 53 | * The resulting files will be nested deeper than the specified URL prefix. 54 | * The final output URL will be provided in the 55 | * google.datastore.admin.v1.ExportEntitiesResponse.output_url google.datastore.admin.v1.ExportEntitiesResponse.output_url 56 | * field. That value should be used for subsequent ImportEntities operations. 57 | * By nesting the data files deeper, the same Cloud Storage bucket can be used 58 | * in multiple ExportEntities operations without conflict. 59 | */ 60 | // const outputUrlPrefix = 'abc123' 61 | 62 | // Imports the Admin library 63 | const {DatastoreAdminClient} = require('@google-cloud/datastore-admin').v1; 64 | 65 | // Instantiates a client 66 | const adminClient = new DatastoreAdminClient(); 67 | 68 | async function callExportEntities() { 69 | // Construct request 70 | const request = { 71 | projectId, 72 | outputUrlPrefix, 73 | }; 74 | 75 | // Run request 76 | const [operation] = await adminClient.exportEntities(request); 77 | const [response] = await operation.promise(); 78 | console.log(response); 79 | } 80 | 81 | callExportEntities(); 82 | // [END datastore_v1_generated_DatastoreAdmin_ExportEntities_async] 83 | } 84 | 85 | process.on('unhandledRejection', err => { 86 | console.error(err.message); 87 | process.exitCode = 1; 88 | }); 89 | main(...process.argv.slice(2)); 90 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore_admin.get_index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main() { 24 | // [START datastore_v1_generated_DatastoreAdmin_GetIndex_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Project ID against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * The resource ID of the index to get. 37 | */ 38 | // const indexId = 'abc123' 39 | 40 | // Imports the Admin library 41 | const {DatastoreAdminClient} = require('@google-cloud/datastore-admin').v1; 42 | 43 | // Instantiates a client 44 | const adminClient = new DatastoreAdminClient(); 45 | 46 | async function callGetIndex() { 47 | // Construct request 48 | const request = { 49 | }; 50 | 51 | // Run request 52 | const response = await adminClient.getIndex(request); 53 | console.log(response); 54 | } 55 | 56 | callGetIndex(); 57 | // [END datastore_v1_generated_DatastoreAdmin_GetIndex_async] 58 | } 59 | 60 | process.on('unhandledRejection', err => { 61 | console.error(err.message); 62 | process.exitCode = 1; 63 | }); 64 | main(...process.argv.slice(2)); 65 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore_admin.import_entities.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main(projectId, inputUrl) { 24 | // [START datastore_v1_generated_DatastoreAdmin_ImportEntities_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Required. Project ID against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | * Client-assigned labels. 37 | */ 38 | // const labels = [1,2,3,4] 39 | /** 40 | * Required. The full resource URL of the external storage location. 41 | * Currently, only Google Cloud Storage is supported. So input_url should be 42 | * of the form: 43 | * `gs://BUCKET_NAME[/NAMESPACE_PATH]/OVERALL_EXPORT_METADATA_FILE`, where 44 | * `BUCKET_NAME` is the name of the Cloud Storage bucket, `NAMESPACE_PATH` is 45 | * an optional Cloud Storage namespace path (this is not a Cloud Datastore 46 | * namespace), and `OVERALL_EXPORT_METADATA_FILE` is the metadata file written 47 | * by the ExportEntities operation. For more information about Cloud Storage 48 | * namespace paths, see 49 | * Object name 50 | * considerations (https://cloud.google.com/storage/docs/naming#object-considerations). 51 | * For more information, see 52 | * google.datastore.admin.v1.ExportEntitiesResponse.output_url google.datastore.admin.v1.ExportEntitiesResponse.output_url. 53 | */ 54 | // const inputUrl = 'abc123' 55 | /** 56 | * Optionally specify which kinds/namespaces are to be imported. If provided, 57 | * the list must be a subset of the EntityFilter used in creating the export, 58 | * otherwise a FAILED_PRECONDITION error will be returned. If no filter is 59 | * specified then all entities from the export are imported. 60 | */ 61 | // const entityFilter = {} 62 | 63 | // Imports the Admin library 64 | const {DatastoreAdminClient} = require('@google-cloud/datastore-admin').v1; 65 | 66 | // Instantiates a client 67 | const adminClient = new DatastoreAdminClient(); 68 | 69 | async function callImportEntities() { 70 | // Construct request 71 | const request = { 72 | projectId, 73 | inputUrl, 74 | }; 75 | 76 | // Run request 77 | const [operation] = await adminClient.importEntities(request); 78 | const [response] = await operation.promise(); 79 | console.log(response); 80 | } 81 | 82 | callImportEntities(); 83 | // [END datastore_v1_generated_DatastoreAdmin_ImportEntities_async] 84 | } 85 | 86 | process.on('unhandledRejection', err => { 87 | console.error(err.message); 88 | process.exitCode = 1; 89 | }); 90 | main(...process.argv.slice(2)); 91 | -------------------------------------------------------------------------------- /samples/generated/v1/datastore_admin.list_indexes.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | 21 | 'use strict'; 22 | 23 | function main() { 24 | // [START datastore_v1_generated_DatastoreAdmin_ListIndexes_async] 25 | /** 26 | * This snippet has been automatically generated and should be regarded as a code template only. 27 | * It will require modifications to work. 28 | * It may require correct/in-range values for request initialization. 29 | * TODO(developer): Uncomment these variables before running the sample. 30 | */ 31 | /** 32 | * Project ID against which to make the request. 33 | */ 34 | // const projectId = 'abc123' 35 | /** 36 | */ 37 | // const filter = 'abc123' 38 | /** 39 | * The maximum number of items to return. If zero, then all results will be 40 | * returned. 41 | */ 42 | // const pageSize = 1234 43 | /** 44 | * The next_page_token value returned from a previous List request, if any. 45 | */ 46 | // const pageToken = 'abc123' 47 | 48 | // Imports the Admin library 49 | const {DatastoreAdminClient} = require('@google-cloud/datastore-admin').v1; 50 | 51 | // Instantiates a client 52 | const adminClient = new DatastoreAdminClient(); 53 | 54 | async function callListIndexes() { 55 | // Construct request 56 | const request = { 57 | }; 58 | 59 | // Run request 60 | const iterable = adminClient.listIndexesAsync(request); 61 | for await (const response of iterable) { 62 | console.log(response); 63 | } 64 | } 65 | 66 | callListIndexes(); 67 | // [END datastore_v1_generated_DatastoreAdmin_ListIndexes_async] 68 | } 69 | 70 | process.on('unhandledRejection', err => { 71 | console.error(err.message); 72 | process.exitCode = 1; 73 | }); 74 | main(...process.argv.slice(2)); 75 | -------------------------------------------------------------------------------- /samples/import.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | async function main(file = 'YOUR_FILE_NAME') { 16 | // [START datastore_admin_entities_import] 17 | const {Datastore} = require('@google-cloud/datastore'); 18 | const datastore = new Datastore(); 19 | 20 | async function importEntities() { 21 | /** 22 | * TODO(developer): Uncomment these variables before running the sample. 23 | */ 24 | // const file = 'YOUR_FILE_NAME'; 25 | 26 | const [importOperation] = await datastore.import({file}); 27 | 28 | // Uncomment to await the results of the operation. 29 | // await importOperation.promise(); 30 | 31 | // Or cancel the operation. 32 | await importOperation.cancel(); 33 | 34 | // You may also choose to include only specific kinds and namespaces. 35 | const [specificImportOperation] = await datastore.import({ 36 | file, 37 | kinds: ['Employee', 'Task'], 38 | namespaces: ['Company'], 39 | }); 40 | 41 | // Uncomment to await the results of the operation. 42 | // await specificImportOperation.promise(); 43 | 44 | // Or cancel the operation. 45 | await specificImportOperation.cancel(); 46 | } 47 | 48 | importEntities(); 49 | // [END datastore_admin_entities_import] 50 | } 51 | 52 | const args = process.argv.slice(2); 53 | main(...args).catch(console.error); 54 | -------------------------------------------------------------------------------- /samples/index.yaml: -------------------------------------------------------------------------------- 1 | indexes: 2 | 3 | - kind: Task 4 | ancestor: no 5 | properties: 6 | - name: done 7 | - name: priority 8 | direction: desc 9 | 10 | - kind: Task 11 | properties: 12 | - name: priority 13 | direction: desc 14 | - name: created 15 | 16 | - kind: Task 17 | properties: 18 | - name: priority 19 | - name: created 20 | 21 | - kind: Task 22 | properties: 23 | - name: done 24 | - name: created 25 | 26 | - kind: Task 27 | properties: 28 | - name: category 29 | - name: priority 30 | 31 | - kind: Task 32 | properties: 33 | - name: percent_complete 34 | - name: priority 35 | -------------------------------------------------------------------------------- /samples/indexes.get.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | async function main(indexId = 'YOUR_INDEX_ID') { 16 | // [START datastore_admin_index_get] 17 | const {Datastore} = require('@google-cloud/datastore'); 18 | const datastore = new Datastore(); 19 | 20 | async function getIndex() { 21 | /** 22 | * TODO(developer): Uncomment these variables before running the sample. 23 | */ 24 | // const indexId = 'YOUR_INDEX_ID'; 25 | 26 | // Create a reference to the index before performing operations on it. 27 | const index = datastore.index(indexId); 28 | 29 | // Get the index's metadata, including its state, properties, and more. 30 | const [metadata] = await index.getMetadata(); 31 | console.log('Properties:', metadata.properties); 32 | } 33 | 34 | getIndex(); 35 | // [END datastore_admin_index_get] 36 | } 37 | 38 | const args = process.argv.slice(2); 39 | main(...args).catch(console.error); 40 | -------------------------------------------------------------------------------- /samples/indexes.list.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | async function main() { 16 | // [START datastore_admin_index_list] 17 | const {Datastore} = require('@google-cloud/datastore'); 18 | const datastore = new Datastore(); 19 | 20 | async function listIndexes() { 21 | const [indexes] = await datastore.getIndexes(); 22 | 23 | console.log(`${indexes.length} indexes returned.`); 24 | 25 | // Each returned Index object includes metadata about the index. 26 | const [firstIndex] = indexes; 27 | console.log('Properties:', firstIndex.metadata.properties); 28 | 29 | // You may also get Index references as a readable object stream. 30 | datastore 31 | .getIndexesStream() 32 | .on('data', index => { 33 | console.log('Properties:', index.metadata.properties); 34 | }) 35 | .on('end', () => { 36 | // All matching Index objects have been returned. 37 | }); 38 | } 39 | 40 | listIndexes(); 41 | // [END datastore_admin_index_list] 42 | } 43 | 44 | const args = process.argv.slice(2); 45 | main(...args).catch(console.error); 46 | -------------------------------------------------------------------------------- /samples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-docs-samples-datastore", 3 | "private": true, 4 | "license": "Apache-2.0", 5 | "author": "Google LLC.", 6 | "files": [ 7 | "*.js" 8 | ], 9 | "repository": "googleapis/nodejs-datastore", 10 | "engines": { 11 | "node": ">=18" 12 | }, 13 | "scripts": { 14 | "test": "mocha --timeout=600000" 15 | }, 16 | "dependencies": { 17 | "@google-cloud/datastore": "^10.0.1", 18 | "sinon": "^18.0.0" 19 | }, 20 | "devDependencies": { 21 | "chai": "^4.2.0", 22 | "mocha": "^8.0.0" 23 | } 24 | } -------------------------------------------------------------------------------- /samples/queryFilterOr.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | // https://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: Create a union between two filters 19 | // description: Create a union between two filters (logical OR operator) 20 | 21 | async function main() { 22 | // [START datastore_query_filter_or] 23 | /** 24 | * TODO(developer): Uncomment these variables before running the sample. 25 | */ 26 | // const projectId = "your Google Cloud project id"; 27 | 28 | // Imports the Cloud Datastore 29 | const {Datastore, PropertyFilter, or} = require('@google-cloud/datastore'); 30 | 31 | async function queryFilterOr() { 32 | // Instantiate the Datastore 33 | const datastore = new Datastore(); 34 | const query = datastore 35 | .createQuery('Task') 36 | .filter( 37 | or([ 38 | new PropertyFilter('description', '=', 'Buy milk'), 39 | new PropertyFilter('description', '=', 'Feed cats'), 40 | ]), 41 | ); 42 | 43 | const [entities] = await datastore.runQuery(query); 44 | for (const entity of entities) { 45 | console.log(`Entity found: ${entity['description']}`); 46 | } 47 | } 48 | 49 | queryFilterOr(); 50 | // [END datastore_query_filter_or] 51 | } 52 | 53 | const args = process.argv.slice(2); 54 | main(...args).catch(console.error); 55 | -------------------------------------------------------------------------------- /samples/queryProfileExplain.js: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // https://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: Run query explain (regular query) 19 | // description: Run query explain for a standard query and print query explain metrics 20 | 21 | async function main() { 22 | // [START datastore_query_explain_entity] 23 | 24 | // Imports the Cloud Datastore 25 | const {Datastore} = require('@google-cloud/datastore'); 26 | 27 | // Instantiate the Datastore 28 | const datastore = new Datastore(); 29 | const q = datastore.createQuery('Task'); 30 | const [, info] = await datastore.runQuery(q, { 31 | explainOptions: {analyze: false}, 32 | }); 33 | console.log(`info: ${Object.keys(info.explainMetrics)}`); 34 | // [END datastore_query_explain_entity] 35 | } 36 | 37 | const args = process.argv.slice(2); 38 | main(...args).catch(console.error); 39 | -------------------------------------------------------------------------------- /samples/queryProfileExplainAggregation.js: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // https://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: Run query explain (aggregate query) 19 | // description: Run query explain for an aggregate query and print query explain metrics 20 | 21 | async function main() { 22 | // [START datastore_query_explain_aggregation] 23 | 24 | // Imports the Cloud Datastore 25 | const {Datastore, AggregateField} = require('@google-cloud/datastore'); 26 | 27 | // Instantiate the Datastore 28 | const datastore = new Datastore(); 29 | const q = datastore.createQuery('Task'); 30 | const aggregate = datastore 31 | .createAggregationQuery(q) 32 | .addAggregation(AggregateField.sum('created')); 33 | const [, info] = await datastore.runAggregationQuery(aggregate, { 34 | explainOptions: {analyze: false}, 35 | }); 36 | console.log(`info: ${Object.keys(info.explainMetrics)}`); 37 | // [END datastore_query_explain_aggregation] 38 | } 39 | 40 | const args = process.argv.slice(2); 41 | main(...args).catch(console.error); 42 | -------------------------------------------------------------------------------- /samples/queryProfileExplainAnalyze.js: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // https://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: Run query explain analyze (regular query) 19 | // description: Run query explain analyze for a standard query and print query explain metrics 20 | 21 | async function main() { 22 | // [START datastore_query_explain_analyze_entity] 23 | 24 | // Imports the Cloud Datastore 25 | const {Datastore} = require('@google-cloud/datastore'); 26 | 27 | // Instantiate the Datastore 28 | const datastore = new Datastore(); 29 | const q = datastore.createQuery('Task'); 30 | const [entities, info] = await datastore.runQuery(q, { 31 | explainOptions: {analyze: true}, 32 | }); 33 | for (const entity of entities) { 34 | console.log(`Entity found: ${entity['description']}`); 35 | } 36 | console.log(`info: ${Object.keys(info.explainMetrics)}`); 37 | // [END datastore_query_explain_analyze_entity] 38 | } 39 | 40 | const args = process.argv.slice(2); 41 | main(...args).catch(console.error); 42 | -------------------------------------------------------------------------------- /samples/queryProfileExplainAnalyzeAggregation.js: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // https://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: Run query explain analyze (aggregate query) 19 | // description: Run query explain analyze for an aggregate query and print query explain metrics 20 | 21 | async function main() { 22 | // [START datastore_query_explain_analyze_aggregation] 23 | 24 | // Imports the Cloud Datastore 25 | const {Datastore, AggregateField} = require('@google-cloud/datastore'); 26 | 27 | // Instantiate the Datastore 28 | const datastore = new Datastore(); 29 | const q = datastore.createQuery('Task'); 30 | const aggregate = datastore 31 | .createAggregationQuery(q) 32 | .addAggregation(AggregateField.sum('created')); 33 | 34 | const [entities, info] = await datastore.runAggregationQuery(aggregate, { 35 | explainOptions: {analyze: true}, 36 | }); 37 | for (const entity of entities) { 38 | console.log(`Entity found: ${JSON.stringify(entity)}`); 39 | } 40 | console.log(`info: ${Object.keys(info.explainMetrics)}`); 41 | // [END datastore_query_explain_analyze_aggregation] 42 | } 43 | 44 | const args = process.argv.slice(2); 45 | main(...args).catch(console.error); 46 | -------------------------------------------------------------------------------- /samples/quickstart.js: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 | // [START datastore_quickstart] 18 | // Imports the Google Cloud client library 19 | const {Datastore} = require('@google-cloud/datastore'); 20 | 21 | // Creates a client 22 | const datastore = new Datastore(); 23 | 24 | async function quickstart() { 25 | // The kind for the new entity 26 | const kind = 'Task'; 27 | 28 | // The name/ID for the new entity 29 | const name = 'sampletask1'; 30 | 31 | // The Cloud Datastore key for the new entity 32 | const taskKey = datastore.key([kind, name]); 33 | 34 | // Prepares the new entity 35 | const task = { 36 | key: taskKey, 37 | data: { 38 | description: 'Buy milk', 39 | }, 40 | }; 41 | 42 | // Saves the entity 43 | await datastore.save(task); 44 | console.log(`Saved ${task.key.name}: ${task.data.description}`); 45 | } 46 | quickstart(); 47 | // [END datastore_quickstart] 48 | -------------------------------------------------------------------------------- /samples/tasks.add.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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: Add Task 19 | // description: Adds a task with a description . 20 | // usage: node tasks.add.js 21 | 22 | /*eslint no-warning-comments: [0, { "terms": ["todo"], "location": "anywhere" }]*/ 23 | async function main(description) { 24 | // [START datastore_add_entity] 25 | const {Datastore} = require('@google-cloud/datastore'); 26 | const datastore = new Datastore(); 27 | 28 | async function addTask() { 29 | // TODO(developer): uncomment the following line, and add a description 30 | // const description = 'description'; 31 | const taskKey = datastore.key('Task'); 32 | const entity = { 33 | key: taskKey, 34 | data: [ 35 | { 36 | name: 'created', 37 | value: new Date().toJSON(), 38 | }, 39 | { 40 | name: 'description', 41 | value: description, 42 | excludeFromIndexes: true, 43 | }, 44 | { 45 | name: 'done', 46 | value: false, 47 | }, 48 | ], 49 | }; 50 | await datastore.save(entity); 51 | console.log(`Task ${taskKey.id} created successfully.`); 52 | } 53 | addTask(); 54 | // [END datastore_add_entity] 55 | } 56 | main(...process.argv.slice(2)).catch(console.error); 57 | -------------------------------------------------------------------------------- /samples/tasks.delete.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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: Delete Task 19 | // description: Deletes task . 20 | // usage: node tasks.delete.js 21 | 22 | /*eslint no-warning-comments: [0, { "terms": ["todo"], "location": "anywhere" }]*/ 23 | async function main(taskId) { 24 | taskId = Number(taskId); 25 | // [START datastore_delete_entity] 26 | const {Datastore} = require('@google-cloud/datastore'); 27 | 28 | const datastore = new Datastore(); 29 | 30 | async function deleteTask() { 31 | // TODO(developer): uncomment the following line and define a taskId 32 | // const taskId = 'task123'; 33 | const taskKey = datastore.key(['Task', taskId]); 34 | console.log(taskKey); 35 | await datastore.delete(taskKey); 36 | console.log(`Task ${taskId} deleted successfully.`); 37 | } 38 | deleteTask(); 39 | // [END datastore_delete_entity] 40 | } 41 | 42 | main(...process.argv.slice(2)).catch(console.error); 43 | -------------------------------------------------------------------------------- /samples/tasks.list.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 Tasks 19 | // description: Lists all tasks ordered by creation time. 20 | // usage: node tasks.list.js 21 | 22 | // [START datastore_retrieve_entities] 23 | const {Datastore} = require('@google-cloud/datastore'); 24 | 25 | const datastore = new Datastore(); 26 | 27 | async function listTasks() { 28 | const query = datastore.createQuery('Task').order('created'); 29 | const [tasks] = await datastore.runQuery(query); 30 | console.log('Tasks:'); 31 | for (const task of tasks) { 32 | const taskKey = task[datastore.KEY]; 33 | console.log(taskKey.id, task); 34 | } 35 | } 36 | listTasks(); 37 | // [END datastore_retrieve_entities] 38 | -------------------------------------------------------------------------------- /samples/tasks.markdone.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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: Update Task 19 | // description: Marks task as Done. 20 | // usage: node tasks.markdone.js 21 | 22 | /*eslint no-warning-comments: [0, { "terms": ["todo"], "location": "anywhere" }]*/ 23 | async function main(taskId) { 24 | taskId = Number(taskId); 25 | // [START datastore_update_entity] 26 | const {Datastore} = require('@google-cloud/datastore'); 27 | const datastore = new Datastore(); 28 | 29 | async function markDone() { 30 | // TODO(developer): uncomment the following line and define a taskId 31 | // const taskId = 'task123'; 32 | const transaction = datastore.transaction(); 33 | const taskKey = datastore.key(['Task', taskId]); 34 | console.log(taskKey); 35 | console.log(taskKey.path); 36 | try { 37 | await transaction.run(); 38 | const [task] = await transaction.get(taskKey); 39 | task.done = true; 40 | transaction.save({ 41 | key: taskKey, 42 | data: task, 43 | }); 44 | await transaction.commit(); 45 | console.log(`Task ${taskId} updated successfully.`); 46 | } catch (err) { 47 | await transaction.rollback(); 48 | throw err; 49 | } 50 | } 51 | markDone(); 52 | // [END datastore_update_entity] 53 | } 54 | 55 | main(...process.argv.slice(2)).catch(console.error); 56 | -------------------------------------------------------------------------------- /samples/test/error.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2019 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 | const assert = require('assert'); 18 | const {describe, it} = require('mocha'); 19 | const {execSync} = require('child_process'); 20 | const exec = cmd => 21 | execSync(cmd, { 22 | encoding: 'utf8', 23 | }); 24 | 25 | describe('error', () => { 26 | it('should have an error', done => { 27 | const errorCode = 3; 28 | const output = exec('node error.js'); 29 | assert.strictEqual(parseInt(output[0]), errorCode); 30 | done(); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /samples/test/helpers/populate-data.js: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | /* eslint-disable */ 16 | 17 | /* 18 | This module is used in various samples to set datastore data to a fixed state 19 | so that the output of the sample is predictable. 20 | */ 21 | 22 | const {after, before} = require('mocha'); 23 | const {Datastore} = require('@google-cloud/datastore'); 24 | let taskKey1, taskKey2; 25 | const datastore = new Datastore(); 26 | 27 | before(async () => { 28 | taskKey1 = datastore.key('Task'); 29 | const entity1 = { 30 | key: taskKey1, 31 | data: { 32 | description: 'Buy milk', 33 | }, 34 | }; 35 | 36 | taskKey2 = datastore.key('Task'); 37 | const entity2 = { 38 | key: taskKey2, 39 | data: { 40 | description: 'Feed cats', 41 | }, 42 | }; 43 | 44 | // Ensure the datastore database has no existing data. 45 | const query = datastore.createQuery('Task'); 46 | const [entities] = await datastore.runQuery(query); 47 | await datastore.delete(entities.map(entity => entity[datastore.KEY])); 48 | 49 | await datastore.upsert(entity1); 50 | await datastore.upsert(entity2); 51 | }); 52 | 53 | after(async () => { 54 | await datastore.delete(taskKey1); 55 | await datastore.delete(taskKey2); 56 | }); 57 | -------------------------------------------------------------------------------- /samples/test/helpers/sorting.js: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // This function is used for comparing console output when the 16 | // order of the console output doesn't matter. 17 | 18 | function sortConsoleOutput(output) { 19 | return output.split('\n').sort().join('\n'); 20 | } 21 | 22 | module.exports = sortConsoleOutput; 23 | -------------------------------------------------------------------------------- /samples/test/import-export.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | const {Datastore} = require('@google-cloud/datastore'); 18 | const {assert} = require('chai'); 19 | const cp = require('child_process'); 20 | const {before, describe, it} = require('mocha'); 21 | 22 | const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); 23 | 24 | describe('import/export entities', async () => { 25 | const datastore = new Datastore(); 26 | 27 | const BUCKET_ID = 'nodejs-datastore-system-tests'; 28 | let EXPORTED_FILE; 29 | 30 | before(async () => { 31 | const [exportOperation] = await datastore.export({ 32 | bucket: BUCKET_ID, 33 | }); 34 | await exportOperation.promise(); 35 | EXPORTED_FILE = exportOperation.result.outputUrl; 36 | }); 37 | 38 | it('should export entities', async () => { 39 | const stdout = execSync(`node ./export.js ${BUCKET_ID}`); 40 | assert.include(stdout, 'Export file created:'); 41 | }); 42 | 43 | it.skip('should import entities', () => { 44 | execSync(`node ./import.js ${EXPORTED_FILE}`); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /samples/test/index.yaml: -------------------------------------------------------------------------------- 1 | indexes: 2 | - kind: Task 3 | properties: 4 | - name: done 5 | - name: priority 6 | direction: desc 7 | - kind: Task 8 | properties: 9 | - name: priority 10 | - name: percent_complete 11 | - kind: Task 12 | properties: 13 | - name: category 14 | - name: priority 15 | - kind: Task 16 | properties: 17 | - name: priority 18 | - name: created 19 | - kind: Task 20 | properties: 21 | - name: done 22 | - name: created 23 | - kind: Task 24 | properties: 25 | - name: category 26 | - name: priority 27 | direction: desc 28 | - kind: Task 29 | properties: 30 | - name: category 31 | - name: created 32 | - kind: Task 33 | properties: 34 | - name: priority 35 | direction: desc 36 | - name: created 37 | -------------------------------------------------------------------------------- /samples/test/indexes.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | const {Datastore} = require('@google-cloud/datastore'); 18 | const {assert} = require('chai'); 19 | const cp = require('child_process'); 20 | const {describe, it} = require('mocha'); 21 | 22 | const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); 23 | 24 | describe('indexes', async () => { 25 | const datastore = new Datastore(); 26 | 27 | // @TODO: Until the protos support creating indexes, these tests depend on 28 | // the remote state of declared indexes. Could be flaky! 29 | 30 | it('should list indexes', async () => { 31 | const [indexes] = await datastore.getIndexes(); 32 | const stdout = execSync('node ./indexes.list.js'); 33 | assert.include(stdout, `${indexes.length} indexes returned.`); 34 | }); 35 | 36 | it('should get a specific index', async () => { 37 | const [indexes] = await datastore.getIndexes(); 38 | const stdout = execSync(`node ./indexes.get.js ${indexes[0].id}`); 39 | assert.include(stdout, 'Properties:'); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /samples/test/queryFilterOr.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 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 | /* eslint-disable */ 16 | 17 | 'use strict'; 18 | 19 | const {assert} = require('chai'); 20 | const {describe, it} = require('mocha'); 21 | const sinon = require('sinon'); 22 | // TODO: delete unused imports 23 | 24 | const cp = require('child_process'); 25 | const sort = require('./helpers/sorting'); 26 | 27 | const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); 28 | 29 | describe('Creating a union query', () => { 30 | const stubConsole = function () { 31 | sinon.stub(console, 'error'); 32 | sinon.stub(console, 'log'); 33 | }; 34 | 35 | const restoreConsole = function () { 36 | console.log.restore(); 37 | console.error.restore(); 38 | }; 39 | 40 | beforeEach(stubConsole); 41 | afterEach(restoreConsole); 42 | 43 | require('./helpers/populate-data'); 44 | 45 | it('should get a combination of items from the Datastore', async () => { 46 | assert.strictEqual(sort(execSync(`node ./queryFilterOr.js`)), '\nEntity found: Buy milk\nEntity found: Feed cats'); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /samples/test/queryProfiling.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | /* eslint-disable */ 16 | 17 | 'use strict'; 18 | 19 | const {assert} = require('chai'); 20 | const {describe, it} = require('mocha'); 21 | 22 | const cp = require('child_process'); 23 | const sort = require('./helpers/sorting'); 24 | 25 | const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); 26 | 27 | describe('Query Profiling', () => { 28 | require('./helpers/populate-data'); 29 | 30 | it('should run query profiling for a query with analyze set to false', async () => { 31 | assert.strictEqual(sort(execSync(`node ./queryProfileExplain.js`)), '\ninfo: planSummary'); 32 | }); 33 | 34 | it('should run query profiling for an aggregation query with analyze set to false', async () => { 35 | assert.strictEqual(sort(execSync(`node ./queryProfileExplainAggregation.js`)), '\ninfo: planSummary'); 36 | }); 37 | 38 | it('should run query profiling for a query with analyze set to true', async () => { 39 | assert.strictEqual(sort(execSync(`node ./queryProfileExplainAnalyze.js`)), '\nEntity found: Buy milk\nEntity found: Feed cats\ninfo: planSummary,executionStats'); 40 | }); 41 | 42 | it('should run query profiling for an aggregation query with analyze set to true', async () => { 43 | assert.strictEqual(sort(execSync(`node ./queryProfileExplainAnalyzeAggregation.js`)), '\nEntity found: {"property_1":0}\ninfo: planSummary,executionStats'); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /samples/test/quickstart.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 | const {assert} = require('chai'); 18 | const {describe, it} = require('mocha'); 19 | const {execSync} = require('child_process'); 20 | 21 | const exec = cmd => execSync(cmd, {encoding: 'utf8'}); 22 | 23 | describe('quickstart', () => { 24 | it('should run the quickstart', () => { 25 | const output = exec('node quickstart.js'); 26 | assert.include(output, 'Saved sampletask1: Buy milk'); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /samples/test/tasks.test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 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 | const {Datastore} = require('@google-cloud/datastore'); 18 | const {assert} = require('chai'); 19 | const {describe, it, after} = require('mocha'); 20 | const {execSync} = require('child_process'); 21 | 22 | const exec = cmd => execSync(cmd, {encoding: 'utf8'}); 23 | const datastore = new Datastore(); 24 | const description = 'description'; 25 | let key; 26 | 27 | describe('task samples', () => { 28 | after(() => datastore.delete(key).catch()); 29 | 30 | it('should add a task', async () => { 31 | const expected = /^Task (\d+) created successfully.$/; 32 | const output = exec(`node tasks.add.js "${description}"`).trim(); 33 | const parts = output.match(expected); 34 | assert.match(parts[0], expected); 35 | const keyId = Number(parts[1]); 36 | const [task] = await datastore.get(datastore.key(['Task', keyId])); 37 | key = task[datastore.KEY]; 38 | assert.strictEqual(task.description, description); 39 | }); 40 | 41 | it('should mark a task as done', async () => { 42 | const expected = `Task ${key.id} updated successfully.`; 43 | const output = exec(`node tasks.markdone.js ${key.id}`); 44 | assert.include(output, expected); 45 | const [task] = await datastore.get(key); 46 | assert.strictEqual(task.done, true); 47 | }); 48 | 49 | it('should list tasks', () => { 50 | const output = exec('node tasks.list.js'); 51 | assert.include(output, key.id); 52 | }); 53 | 54 | it('should delete a task', async () => { 55 | const expected = `Task ${key.id} deleted successfully.`; 56 | const output = exec(`node tasks.delete.js ${key.id}`); 57 | assert.include(output, expected); 58 | const [task] = await datastore.get(key); 59 | assert.strictEqual(task, undefined); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /src/interfaces/save.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | import {Entity, entity} from '../entity'; 16 | 17 | /* 18 | Entity data passed into save in non array form will be of type SaveNonArrayData 19 | and does not require name and value properties. 20 | */ 21 | type SaveNonArrayData = { 22 | [k: string]: Entity; 23 | }; 24 | 25 | /* 26 | Entity data passed into save in an array form will be of type SaveArrayData 27 | so will have name and value defined because the source code of save requires a 28 | name and a value to be defined or else an error will be thrown. 29 | */ 30 | interface SaveArrayData { 31 | name: { 32 | toString(): string; 33 | }; 34 | value: Entity; 35 | excludeFromIndexes?: boolean; 36 | } 37 | 38 | /* 39 | When saving an entity, data in the data property of the entity is of type 40 | SaveDataValue. The data can either be in array form in which case it will 41 | match the SaveArrayData[] data type or it can be in non-array form where 42 | it will match the SaveNonArrayData data type. 43 | */ 44 | export type SaveDataValue = SaveArrayData[] | SaveNonArrayData; 45 | 46 | /* 47 | An Entity passed into save will include a Key object contained either inside 48 | a `key` property or inside a property indexed by the Key Symbol. If it is 49 | the former then it will be of type SaveEntityWithoutKeySymbol. 50 | */ 51 | interface SaveEntityWithoutKeySymbol { 52 | key: entity.Key; 53 | data: SaveDataValue; 54 | excludeFromIndexes?: string[]; 55 | } 56 | 57 | /* 58 | An Entity passed into save will include a Key object contained either inside 59 | a `key` property or inside a property indexed by the Key Symbol. If it is 60 | the latter then it will be of type SaveEntityWithKeySymbol. 61 | */ 62 | interface SaveEntityWithKeySymbol { 63 | [entity.KEY_SYMBOL]: entity.Key; 64 | data: SaveDataValue; 65 | } 66 | 67 | /* 68 | Entities passed into the first argument of the save function are expected to be 69 | of type SaveEntity[] after being turned into an array. We could change the 70 | signature of save later to enforce this, but doing so would be a breaking change 71 | so we just cast this value to SaveEntity[] for now to enable strong type 72 | enforcement throughout this function. 73 | */ 74 | export type SaveEntity = SaveEntityWithoutKeySymbol | SaveEntityWithKeySymbol; 75 | -------------------------------------------------------------------------------- /src/utils/entity/buildEntityProto.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | import {entity, Entity, EntityProto, ValueProto} from '../../entity'; 16 | import {EntityProtoReduceAccumulator, EntityProtoReduceData} from '../../index'; 17 | import addExcludeFromIndexes = entity.addExcludeFromIndexes; 18 | 19 | /** 20 | * This function builds the entity proto from the entity object. We cannot 21 | * rely on entity.entityToEntityProto for this because this function is only 22 | * designed to be used for non-array entities. 23 | * 24 | */ 25 | export function buildEntityProto(entityObject: Entity) { 26 | let entityProto: EntityProto = {}; 27 | if (Array.isArray(entityObject.data)) { 28 | // This code builds the right entityProto from the entityObject 29 | entityProto.properties = entityObject.data.reduce( 30 | (acc: EntityProtoReduceAccumulator, data: EntityProtoReduceData) => { 31 | const value = entity.encodeValue(data.value, data.name.toString()); 32 | 33 | if (typeof data.excludeFromIndexes === 'boolean') { 34 | const excluded = data.excludeFromIndexes; 35 | let values = value.arrayValue && value.arrayValue.values; 36 | 37 | if (values) { 38 | values = values.map((x: ValueProto) => { 39 | x.excludeFromIndexes = excluded; 40 | return x; 41 | }); 42 | } else { 43 | value.excludeFromIndexes = data.excludeFromIndexes; 44 | } 45 | } 46 | 47 | acc[data.name] = value; 48 | 49 | return acc; 50 | }, 51 | {}, 52 | ); 53 | // This code adds excludeFromIndexes in the right places 54 | addExcludeFromIndexes(entityObject.excludeFromIndexes, entityProto); 55 | } else { 56 | // This code builds the right entityProto from the entityObject 57 | entityProto = entity.entityToEntityProto(entityObject); 58 | } 59 | return entityProto; 60 | } 61 | -------------------------------------------------------------------------------- /src/utils/entity/extendExcludeFromIndexes.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | import {entity, Entity} from '../../entity'; 16 | 17 | /** 18 | * This function extends the excludeFromIndexes list when it finds 19 | * large properties in the entity object. The extended excludeFromIndexes 20 | * list is then used when building the entity proto. 21 | * 22 | * @param {Entity} entityObject The entity object to parse for properties to 23 | * add to the excludeFromIndexes list. 24 | */ 25 | export function extendExcludeFromIndexes(entityObject: Entity) { 26 | if (entityObject.excludeLargeProperties) { 27 | if (Array.isArray(entityObject.data)) { 28 | // This code populates the excludeFromIndexes list with the right values. 29 | entityObject.data.forEach( 30 | (data: { 31 | name: { 32 | toString(): string; 33 | }; 34 | value: Entity; 35 | excludeFromIndexes?: boolean; 36 | }) => { 37 | entityObject.excludeFromIndexes = entity.findLargeProperties_( 38 | data.value, 39 | data.name.toString(), 40 | entityObject.excludeFromIndexes, 41 | ); 42 | }, 43 | ); 44 | } else { 45 | entityObject.excludeFromIndexes = entity.findLargeProperties_( 46 | entityObject.data, 47 | '', 48 | entityObject.excludeFromIndexes, 49 | ); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/v1/datastore_admin_client_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "interfaces": { 3 | "google.datastore.admin.v1.DatastoreAdmin": { 4 | "retry_codes": { 5 | "non_idempotent": [], 6 | "idempotent": [ 7 | "DEADLINE_EXCEEDED", 8 | "UNAVAILABLE" 9 | ] 10 | }, 11 | "retry_params": { 12 | "default": { 13 | "initial_retry_delay_millis": 100, 14 | "retry_delay_multiplier": 1.3, 15 | "max_retry_delay_millis": 60000, 16 | "initial_rpc_timeout_millis": 60000, 17 | "rpc_timeout_multiplier": 1, 18 | "max_rpc_timeout_millis": 60000, 19 | "total_timeout_millis": 600000 20 | } 21 | }, 22 | "methods": { 23 | "ExportEntities": { 24 | "timeout_millis": 60000, 25 | "retry_codes_name": "non_idempotent", 26 | "retry_params_name": "default" 27 | }, 28 | "ImportEntities": { 29 | "timeout_millis": 60000, 30 | "retry_codes_name": "non_idempotent", 31 | "retry_params_name": "default" 32 | }, 33 | "CreateIndex": { 34 | "timeout_millis": 60000, 35 | "retry_codes_name": "non_idempotent", 36 | "retry_params_name": "default" 37 | }, 38 | "DeleteIndex": { 39 | "timeout_millis": 60000, 40 | "retry_codes_name": "non_idempotent", 41 | "retry_params_name": "default" 42 | }, 43 | "GetIndex": { 44 | "timeout_millis": 60000, 45 | "retry_codes_name": "idempotent", 46 | "retry_params_name": "default" 47 | }, 48 | "ListIndexes": { 49 | "timeout_millis": 60000, 50 | "retry_codes_name": "idempotent", 51 | "retry_params_name": "default" 52 | } 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/v1/datastore_admin_proto_list.json: -------------------------------------------------------------------------------- 1 | [ 2 | "../../protos/google/datastore/admin/v1/datastore_admin.proto", 3 | "../../protos/google/datastore/admin/v1/index.proto", 4 | "../../protos/google/datastore/admin/v1/migration.proto" 5 | ] 6 | -------------------------------------------------------------------------------- /src/v1/datastore_client_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "interfaces": { 3 | "google.datastore.v1.Datastore": { 4 | "retry_codes": { 5 | "non_idempotent": [], 6 | "idempotent": [ 7 | "DEADLINE_EXCEEDED", 8 | "UNAVAILABLE" 9 | ] 10 | }, 11 | "retry_params": { 12 | "default": { 13 | "initial_retry_delay_millis": 100, 14 | "retry_delay_multiplier": 1.3, 15 | "max_retry_delay_millis": 60000, 16 | "initial_rpc_timeout_millis": 60000, 17 | "rpc_timeout_multiplier": 1, 18 | "max_rpc_timeout_millis": 60000, 19 | "total_timeout_millis": 600000 20 | } 21 | }, 22 | "methods": { 23 | "Lookup": { 24 | "timeout_millis": 60000, 25 | "retry_codes_name": "idempotent", 26 | "retry_params_name": "default" 27 | }, 28 | "RunQuery": { 29 | "timeout_millis": 60000, 30 | "retry_codes_name": "idempotent", 31 | "retry_params_name": "default" 32 | }, 33 | "RunAggregationQuery": { 34 | "timeout_millis": 60000, 35 | "retry_codes_name": "idempotent", 36 | "retry_params_name": "default" 37 | }, 38 | "BeginTransaction": { 39 | "timeout_millis": 60000, 40 | "retry_codes_name": "non_idempotent", 41 | "retry_params_name": "default" 42 | }, 43 | "Commit": { 44 | "timeout_millis": 60000, 45 | "retry_codes_name": "non_idempotent", 46 | "retry_params_name": "default" 47 | }, 48 | "Rollback": { 49 | "timeout_millis": 60000, 50 | "retry_codes_name": "non_idempotent", 51 | "retry_params_name": "default" 52 | }, 53 | "AllocateIds": { 54 | "timeout_millis": 60000, 55 | "retry_codes_name": "non_idempotent", 56 | "retry_params_name": "default" 57 | }, 58 | "ReserveIds": { 59 | "timeout_millis": 60000, 60 | "retry_codes_name": "idempotent", 61 | "retry_params_name": "default" 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/v1/datastore_proto_list.json: -------------------------------------------------------------------------------- 1 | [ 2 | "../../protos/google/datastore/v1/aggregation_result.proto", 3 | "../../protos/google/datastore/v1/datastore.proto", 4 | "../../protos/google/datastore/v1/entity.proto", 5 | "../../protos/google/datastore/v1/query.proto", 6 | "../../protos/google/datastore/v1/query_profile.proto" 7 | ] 8 | -------------------------------------------------------------------------------- /src/v1/gapic_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": "1.0", 3 | "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", 4 | "language": "typescript", 5 | "protoPackage": "google.datastore.admin.v1", 6 | "libraryPackage": "@google-cloud/datastore-admin", 7 | "services": { 8 | "DatastoreAdmin": { 9 | "clients": { 10 | "grpc": { 11 | "libraryClient": "DatastoreAdminClient", 12 | "rpcs": { 13 | "GetIndex": { 14 | "methods": [ 15 | "getIndex" 16 | ] 17 | }, 18 | "ExportEntities": { 19 | "methods": [ 20 | "exportEntities" 21 | ] 22 | }, 23 | "ImportEntities": { 24 | "methods": [ 25 | "importEntities" 26 | ] 27 | }, 28 | "CreateIndex": { 29 | "methods": [ 30 | "createIndex" 31 | ] 32 | }, 33 | "DeleteIndex": { 34 | "methods": [ 35 | "deleteIndex" 36 | ] 37 | }, 38 | "ListIndexes": { 39 | "methods": [ 40 | "listIndexes", 41 | "listIndexesStream", 42 | "listIndexesAsync" 43 | ] 44 | } 45 | } 46 | }, 47 | "grpc-fallback": { 48 | "libraryClient": "DatastoreAdminClient", 49 | "rpcs": { 50 | "GetIndex": { 51 | "methods": [ 52 | "getIndex" 53 | ] 54 | }, 55 | "ExportEntities": { 56 | "methods": [ 57 | "exportEntities" 58 | ] 59 | }, 60 | "ImportEntities": { 61 | "methods": [ 62 | "importEntities" 63 | ] 64 | }, 65 | "CreateIndex": { 66 | "methods": [ 67 | "createIndex" 68 | ] 69 | }, 70 | "DeleteIndex": { 71 | "methods": [ 72 | "deleteIndex" 73 | ] 74 | }, 75 | "ListIndexes": { 76 | "methods": [ 77 | "listIndexes", 78 | "listIndexesStream", 79 | "listIndexesAsync" 80 | ] 81 | } 82 | } 83 | } 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/v1/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2020 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | export {DatastoreClient} from './datastore_client'; 20 | export {DatastoreAdminClient} from './datastore_admin_client'; 21 | -------------------------------------------------------------------------------- /system-test/data/index.yaml: -------------------------------------------------------------------------------- 1 | indexes: 2 | 3 | - kind: Character 4 | ancestor: yes 5 | properties: 6 | - name: appearances 7 | 8 | - kind: Character 9 | ancestor: yes 10 | properties: 11 | - name: alive 12 | 13 | - kind: Character 14 | ancestor: yes 15 | properties: 16 | - name: family 17 | - name: appearances 18 | 19 | - kind: Character 20 | ancestor: no 21 | properties: 22 | - name: family 23 | - name: appearances 24 | 25 | - kind: Character 26 | ancestor: yes 27 | properties: 28 | - name: name 29 | - name: family 30 | -------------------------------------------------------------------------------- /system-test/fixtures/sample/src/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | 20 | /* eslint-disable node/no-missing-require, no-unused-vars */ 21 | const datastore = require('@google-cloud/datastore'); 22 | 23 | function main() { 24 | const datastoreClient = new datastore.Datastore(); 25 | } 26 | 27 | main(); 28 | -------------------------------------------------------------------------------- /system-test/fixtures/sample/src/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | import {Datastore} from '@google-cloud/datastore'; 20 | 21 | // check that the client class type name can be used 22 | function doStuffWithDatastore(client: Datastore) { 23 | // client.close(); 24 | } 25 | 26 | function main() { 27 | // check that the client instance can be created 28 | const datastoreClient = new Datastore(); 29 | doStuffWithDatastore(datastoreClient); 30 | } 31 | 32 | main(); 33 | -------------------------------------------------------------------------------- /system-test/install.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2025 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 | // https://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 | // ** This file is automatically generated by gapic-generator-typescript. ** 16 | // ** https://github.com/googleapis/gapic-generator-typescript ** 17 | // ** All changes to this file may be overwritten. ** 18 | 19 | import {packNTest} from 'pack-n-play'; 20 | import {readFileSync} from 'fs'; 21 | import {describe, it} from 'mocha'; 22 | 23 | describe('📦 pack-n-play test', () => { 24 | it('TypeScript code', async function () { 25 | this.timeout(300000); 26 | const options = { 27 | packageDir: process.cwd(), 28 | sample: { 29 | description: 'TypeScript user can use the type definitions', 30 | ts: readFileSync( 31 | './system-test/fixtures/sample/src/index.ts', 32 | ).toString(), 33 | }, 34 | }; 35 | await packNTest(options); 36 | }); 37 | 38 | it('JavaScript code', async function () { 39 | this.timeout(300000); 40 | const options = { 41 | packageDir: process.cwd(), 42 | sample: { 43 | description: 'JavaScript user can use the library', 44 | ts: readFileSync( 45 | './system-test/fixtures/sample/src/index.js', 46 | ).toString(), 47 | }, 48 | }; 49 | await packNTest(options); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/entity/buildEntityProto.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | import {describe} from 'mocha'; 16 | import {Entities, EntityObject, EntityProto} from '../../src/entity'; 17 | import * as assert from 'assert'; 18 | import {buildEntityProto} from '../../src/utils/entity/buildEntityProto'; 19 | import { 20 | entityObject, 21 | expectedEntityProto, 22 | } from '../fixtures/entityObjectAndProto'; 23 | 24 | const async = require('async'); 25 | 26 | describe('buildEntityProto', () => { 27 | async.each( 28 | [ 29 | { 30 | name: 'should format an entity', 31 | entityObject: { 32 | data: { 33 | name: 'Stephen', 34 | }, 35 | }, 36 | expectedProto: { 37 | key: null, 38 | properties: { 39 | name: { 40 | stringValue: 'Stephen', 41 | }, 42 | }, 43 | }, 44 | skipped: false, 45 | }, 46 | { 47 | name: 'should format an entity array', 48 | entityObject: { 49 | data: [ 50 | { 51 | name: 'Stephen', 52 | value: 'Stephen value', 53 | }, 54 | ], 55 | }, 56 | expectedProto: { 57 | properties: { 58 | Stephen: { 59 | stringValue: 'Stephen value', 60 | }, 61 | }, 62 | }, 63 | skipped: false, 64 | }, 65 | { 66 | name: 'should respect excludeFromIndexes', 67 | skipped: false, 68 | entityObject: entityObject, 69 | expectedProto: expectedEntityProto, 70 | }, 71 | ], 72 | (test: { 73 | name: string; 74 | skipped: boolean; 75 | entityObject: EntityObject; 76 | expectedProto: EntityProto; 77 | }) => { 78 | it(test.name, function () { 79 | if (test.skipped) { 80 | this.skip(); 81 | } 82 | assert.deepStrictEqual( 83 | buildEntityProto(test.entityObject), 84 | test.expectedProto, 85 | ); 86 | }); 87 | }, 88 | ); 89 | }); 90 | -------------------------------------------------------------------------------- /test/fixtures/complexCaseLargeStrings.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | // complexCaseEntities are passed into save for the complex case. 16 | const longString = Buffer.alloc(1501, '.').toString(); 17 | export const complexCaseEntities = { 18 | longString, 19 | notMetadata: true, 20 | longStringArray: [longString], 21 | metadata: { 22 | longString, 23 | otherProperty: 'value', 24 | obj: { 25 | longStringArray: [ 26 | { 27 | longString, 28 | nestedLongStringArray: [ 29 | { 30 | longString, 31 | nestedProperty: true, 32 | }, 33 | { 34 | longString, 35 | }, 36 | ], 37 | }, 38 | ], 39 | }, 40 | longStringArray: [ 41 | { 42 | longString, 43 | nestedLongStringArray: [ 44 | { 45 | longString, 46 | nestedProperty: true, 47 | }, 48 | { 49 | longString, 50 | }, 51 | ], 52 | }, 53 | ], 54 | }, 55 | }; 56 | -------------------------------------------------------------------------------- /test/gapic-mocks/error-mocks.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | import * as mocha from 'mocha'; 16 | import * as assert from 'assert'; 17 | import {Datastore} from '../../src'; 18 | 19 | /** 20 | * Returns a callback function that expects an error with a particular 21 | * message. This is used for testing all client library functions that accept 22 | * a callback in order to ensure the callback receives a particular error. 23 | * 24 | * @param {mocha.Done} done The mocha done function which is called when the 25 | * test finishes. 26 | * @param {string} message The expected error message in the test. 27 | * 28 | */ 29 | export function getCallbackExpectingError(done: mocha.Done, message: string) { 30 | return (error?: Error | null) => { 31 | try { 32 | if (error) { 33 | assert.strictEqual(error.message, message); 34 | done(); 35 | return; 36 | } 37 | done(new Error('The callback should have received an error')); 38 | } catch (err: unknown) { 39 | done(err); 40 | } 41 | }; 42 | } 43 | 44 | /** 45 | * This function ends the test with an error if a call reaches the gapic 46 | * layer. Using this function in a test makes the test fail if any outgoing 47 | * grpc calls are made in that test. This allows the test to ensure that no 48 | * grpc calls happen, which is typically desired behaviour when an error is 49 | * sent back to the user from the handwritten layer. 50 | * 51 | * @param {Datastore} datastore The datastore client. 52 | * @param {string} clientName The datastore client. 53 | * @param {mocha.Done} done The mocha done function which is called when the 54 | * test finishes. 55 | */ 56 | export function errorOnGapicCall( 57 | datastore: Datastore, 58 | clientName: string, 59 | done: mocha.Done, 60 | ) { 61 | const dataClient = datastore.clients_.get(clientName); 62 | if (dataClient) { 63 | dataClient.runQuery = () => { 64 | done(new Error('The gapic layer should not have received a call')); 65 | }; 66 | dataClient.runAggregationQuery = () => { 67 | done(new Error('The gapic layer should not have received a call')); 68 | }; 69 | dataClient.lookup = () => { 70 | done(new Error('The gapic layer should not have received a call')); 71 | }; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test/gapic-mocks/get-initialized-datastore-client.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | import {Datastore} from '../../src'; 16 | 17 | /** 18 | * This function gets a datastore client that has already been initialized 19 | * meaning that its gapic data client has been created and is ready to be mocked 20 | * out with whatever behavior is needed in a test. Mocking out the gapic client 21 | * is common for testing handwritten layer behaviour because it is a way to 22 | * evaluate data that reaches the handwritten layer thereby testing the 23 | * handwritten layer in isolation. 24 | */ 25 | export function getInitializedDatastoreClient(): Datastore { 26 | const clientName = 'DatastoreClient'; 27 | const PROJECT_ID = 'project-id'; 28 | const NAMESPACE = 'namespace'; 29 | const options = { 30 | projectId: PROJECT_ID, 31 | namespace: NAMESPACE, 32 | }; 33 | const datastore = new Datastore(options); 34 | // By default, datastore.clients_ is an empty map. 35 | // To mock out commit we need the map to contain the Gapic data client. 36 | // Normally a call to the data client through the datastore object would initialize it. 37 | // We don't want to make this call because it would make a grpc request. 38 | // So we just add the data client to the map. 39 | const gapic = Object.freeze({ 40 | v1: require('../../src/v1'), 41 | }); 42 | datastore.clients_.set(clientName, new gapic.v1[clientName](options)); 43 | return datastore; 44 | } 45 | -------------------------------------------------------------------------------- /test/gapic-mocks/runQuery.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | import * as assert from 'assert'; 16 | import {describe} from 'mocha'; 17 | import {DatastoreClient} from '../../src'; 18 | import * as protos from '../../protos/protos'; 19 | import {getInitializedDatastoreClient} from './get-initialized-datastore-client'; 20 | 21 | describe('Run Query', () => { 22 | const clientName = 'DatastoreClient'; 23 | const datastore = getInitializedDatastoreClient(); 24 | 25 | // This function is used for doing assertion checks. 26 | // The idea is to check that the right request gets passed to the commit function in the Gapic layer. 27 | function setRunQueryComparison( 28 | compareFn: (request: protos.google.datastore.v1.IRunQueryRequest) => void, 29 | ) { 30 | const dataClient = datastore.clients_.get(clientName); 31 | if (dataClient) { 32 | dataClient.runQuery = ( 33 | request: any, 34 | options: any, 35 | callback: ( 36 | err?: unknown, 37 | res?: protos.google.datastore.v1.IRunQueryResponse, 38 | ) => void, 39 | ) => { 40 | try { 41 | compareFn(request); 42 | } catch (e) { 43 | callback(e); 44 | } 45 | callback(null, { 46 | batch: { 47 | moreResults: 48 | protos.google.datastore.v1.QueryResultBatch.MoreResultsType 49 | .NO_MORE_RESULTS, 50 | }, 51 | }); 52 | }; 53 | } 54 | } 55 | 56 | it('should pass new transaction into runQuery for transactions', async () => { 57 | setRunQueryComparison( 58 | (request: protos.google.datastore.v1.IRunQueryRequest) => { 59 | assert.deepStrictEqual(request, { 60 | readOptions: { 61 | consistencyType: 'newTransaction', 62 | newTransaction: {}, 63 | }, 64 | partitionId: { 65 | namespaceId: 'namespace', 66 | }, 67 | query: { 68 | distinctOn: [], 69 | kind: [{name: 'Task'}], 70 | order: [], 71 | projection: [], 72 | }, 73 | projectId: 'project-id', 74 | }); 75 | }, 76 | ); 77 | const transaction = datastore.transaction(); 78 | const query = datastore.createQuery('Task'); 79 | await transaction.runQuery(query); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /test/try-server.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2024 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 | import {describe, it} from 'mocha'; 16 | import {Datastore} from '../src'; 17 | 18 | import {startServer} from '../mock-server/datastore-server'; 19 | 20 | describe('Try server', () => { 21 | it.skip('should try to connect to the running server', done => { 22 | startServer(async () => { 23 | const datastore = new Datastore({ 24 | namespace: `${Date.now()}`, 25 | apiEndpoint: 'localhost:50051', 26 | }); 27 | const postKey = datastore.key(['Post', 'post1']); 28 | const query = datastore.createQuery('Post').hasAncestor(postKey); 29 | const allResults = await datastore.runQuery(query); 30 | done(); 31 | }); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/gts/tsconfig-google.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "outDir": "build", 6 | "resolveJsonModule": true, 7 | "lib": [ 8 | "es2018", 9 | "dom" 10 | ] 11 | }, 12 | "include": [ 13 | "src/*.ts", 14 | "src/**/*.ts", 15 | "test/*.ts", 16 | "test/**/*.ts", 17 | "system-test/*.ts", 18 | "mock-server/datastore-server.ts", 19 | "src/v1/datastore_client_config.json", 20 | "protos/protos.json", 21 | "src/v1/datastore_admin_client_config.json" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | // Copyright 2021 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 | // https://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 | const path = require('path'); 16 | 17 | module.exports = { 18 | entry: './src/index.ts', 19 | output: { 20 | library: 'datastore', 21 | filename: './datastore.js', 22 | }, 23 | node: { 24 | child_process: 'empty', 25 | fs: 'empty', 26 | crypto: 'empty', 27 | }, 28 | resolve: { 29 | alias: { 30 | '../../../package.json': path.resolve(__dirname, 'package.json'), 31 | }, 32 | extensions: ['.js', '.json', '.ts'], 33 | }, 34 | module: { 35 | rules: [ 36 | { 37 | test: /\.tsx?$/, 38 | use: 'ts-loader', 39 | exclude: /node_modules/, 40 | }, 41 | { 42 | test: /node_modules[\\/]@grpc[\\/]grpc-js/, 43 | use: 'null-loader', 44 | }, 45 | { 46 | test: /node_modules[\\/]grpc/, 47 | use: 'null-loader', 48 | }, 49 | { 50 | test: /node_modules[\\/]retry-request/, 51 | use: 'null-loader', 52 | }, 53 | { 54 | test: /node_modules[\\/]https?-proxy-agent/, 55 | use: 'null-loader', 56 | }, 57 | { 58 | test: /node_modules[\\/]gtoken/, 59 | use: 'null-loader', 60 | }, 61 | ], 62 | }, 63 | mode: 'production', 64 | }; 65 | --------------------------------------------------------------------------------