diff --git a/packages/typeless-sample-bot/__snapshots__/index.js b/packages/typeless-sample-bot/__snapshots__/index.js index f9ad75930d9..ce202525118 100644 --- a/packages/typeless-sample-bot/__snapshots__/index.js +++ b/packages/typeless-sample-bot/__snapshots__/index.js @@ -120,7 +120,7 @@ exports['command line option "targets" works with multiple sample files 1'] = [ ] exports['command line option "recursive" causes recursion and only matches samples 1'] = [ - "// Copyright 2019-2021 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This is a generated sample, using the typeless sample bot. Please\n// look for the source TypeScript sample (.ts) for modifications.\n'use strict';\n\n/**\n * This application demonstrates how to perform basic operations on\n * subscriptions with the Google Cloud Pub/Sub API.\n *\n * For more information, see the README.md under /pubsub and the documentation\n * at https://cloud.google.com/pubsub/docs.\n */\n\n// sample-metadata:\n// title: Listen For Avro Records\n// description: Listens for records in Avro encoding from a subscription.\n// usage: node listenForAvroRecords.js [timeout-in-seconds]\n\n// [START pubsub_subscribe_avro_records]\n/**\n * TODO(developer): Uncomment these variables before running the sample.\n */\n// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';\n// const timeout = 60;\n\n// Imports the Google Cloud client library\nconst { PubSub, Schema, Encodings } = require(\"@google-cloud/pubsub\");\n\n// Node FS library, to load definitions\nconst fs = require(\"fs\");\n\n// And the Apache Avro library\nconst avro = require(\"avro-js\");\n\n// Creates a client; cache this for further use\nconst pubSubClient = new PubSub();\n\nfunction listenForAvroRecords(subscriptionNameOrId, timeout) {\n // References an existing subscription\n const subscription = pubSubClient.subscription(subscriptionNameOrId);\n\n // Make an encoder using the official avro-js library.\n const definition = fs.\n readFileSync('system-test/fixtures/provinces.avsc').\n toString();\n const type = avro.parse(definition);\n\n // Create an event handler to handle messages\n let messageCount = 0;\n const messageHandler = async (message) => {\n // \"Ack\" (acknowledge receipt of) the message\n message.ack();\n\n // Get the schema metadata from the message.\n const schemaMetadata = Schema.metadataFromMessage(message.attributes);\n\n let result;\n switch (schemaMetadata.encoding) {\n case Encodings.Binary:\n result = type.fromBuffer(message.data);\n break;\n case Encodings.Json:\n result = type.fromString(message.data.toString());\n break;\n default:\n console.log(`Unknown schema encoding: ${schemaMetadata.encoding}`);\n break;}\n\n\n console.log(`Received message ${message.id}:`);\n console.log(`\\tData: ${JSON.stringify(result, null, 4)}`);\n console.log(`\\tAttributes: ${message.attributes}`);\n messageCount += 1;\n };\n\n // Listen for new messages until timeout is hit\n subscription.on('message', messageHandler);\n\n setTimeout(() => {\n subscription.removeListener('message', messageHandler);\n console.log(`${messageCount} message(s) received.`);\n }, timeout * 1000);\n}\n// [END pubsub_subscribe_avro_records]\n\nfunction main(\nsubscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID',\ntimeout = 60)\n{\n timeout = Number(timeout);\n\n try {\n listenForAvroRecords(subscriptionNameOrId, timeout);\n } catch (err) {\n console.error(err.message);\n process.exitCode = 1;\n }\n}\n\nmain(...process.argv.slice(2));", + "// Copyright 2019-2021 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This is a generated sample, using the typeless sample bot. Please\n// look for the source TypeScript sample (.ts) for modifications.\n'use strict';\n\n/**\n * This application demonstrates how to perform basic operations on\n * subscriptions with the Google Cloud Pub/Sub API.\n *\n * For more information, see the README.md under /pubsub and the documentation\n * at https://cloud.google.com/pubsub/docs.\n */\n\n// sample-metadata:\n// title: Listen For Avro Records\n// description: Listens for records in Avro encoding from a subscription.\n// usage: node listenForAvroRecords.js [timeout-in-seconds]\n\n// [START pubsub_subscribe_avro_records]\n/**\n * TODO(developer): Uncomment these variables before running the sample.\n */\n// const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';\n// const timeout = 60;\n\n// Imports the Google Cloud client library\nconst { PubSub, Schema, Encodings } = require(\"@google-cloud/pubsub\");\n\n// Node FS library, to load definitions\nconst fs = require(\"fs\");\n\n// And the Apache Avro library\nconst avro = require(\"avro-js\");\n\n// Creates a client; cache this for further use\nconst pubSubClient = new PubSub();\n\nfunction listenForAvroRecords(subscriptionNameOrId, timeout) {\n // References an existing subscription\n const subscription = pubSubClient.subscription(subscriptionNameOrId);\n\n // Make an encoder using the official avro-js library.\n const definition = fs.\n readFileSync('system-test/fixtures/provinces.avsc').\n toString();\n const type = avro.parse(definition);\n\n // Create an event handler to handle messages\n let messageCount = 0;\n const messageHandler = async (message) => {\n // \"Ack\" (acknowledge receipt of) the message\n message.ack();\n\n // Get the schema metadata from the message.\n const schemaMetadata = Schema.metadataFromMessage(message.attributes);\n\n let result;\n switch (schemaMetadata.encoding) {\n case Encodings.Binary:\n result = type.fromBuffer(message.data);\n break;\n case Encodings.Json:\n result = type.fromString(message.data.toString());\n break;\n default:\n console.log(`Unknown schema encoding: ${schemaMetadata.encoding}`);\n break;}\n\n\n console.log(`Received message ${message.id}:`);\n console.log(`\\tData: ${JSON.stringify(result, null, 4)}`);\n console.log(`\\tAttributes: ${message.attributes}`);\n messageCount += 1;\n };\n\n // Listen for new messages until timeout is hit\n subscription.on('message', messageHandler);\n\n setTimeout(() => {\n subscription.removeListener('message', messageHandler);\n console.log(`${messageCount} message(s) received.`);\n }, timeout * 1000);\n\n use.optional.chaining();\n}\n// [END pubsub_subscribe_avro_records]\n\nfunction main(\nsubscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID',\ntimeout = 60)\n{\n timeout = Number(timeout);\n\n try {\n listenForAvroRecords(subscriptionNameOrId, timeout);\n } catch (err) {\n console.error(err.message);\n process.exitCode = 1;\n }\n}\n\nmain(...process.argv.slice(2));", "// Copyright 2019-2021 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// This is a generated sample, using the typeless sample bot. Please\n// look for the source TypeScript sample (.ts) for modifications.\n'use strict';\n\n/**\n * This sample demonstrates how to perform basic operations on topics with\n * the Google Cloud Pub/Sub API.\n *\n * For more information, see the README.md under /pubsub and the documentation\n * at https://cloud.google.com/pubsub/docs.\n */\n\n// sample-metadata:\n// title: Publish Avro Records to a Topic\n// description: Publishes a record in Avro to a topic with a schema.\n// usage: node publishAvroRecords.js \n\n// [START pubsub_publish_avro_records]\n/**\n * TODO(developer): Uncomment this variable before running the sample.\n */\n// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';\n\n// Imports the Google Cloud client library\nconst { PubSub, Encodings } = require(\"@google-cloud/pubsub\");\n\n// And the Apache Avro library\nconst avro = require(\"avro-js\");\nconst fs = require(\"fs\");\n\n// Creates a client; cache this for further use\nconst pubSubClient = new PubSub();\n\n\n\n\n\n\nasync function publishAvroRecords(topicNameOrId) {\n // Get the topic metadata to learn about its schema encoding.\n const topic = pubSubClient.topic(topicNameOrId);\n const [topicMetadata] = await topic.getMetadata();\n const topicSchemaMetadata = topicMetadata.schemaSettings;\n\n if (!topicSchemaMetadata) {\n console.log(`Topic ${topicNameOrId} doesn't seem to have a schema.`);\n return;\n }\n const schemaEncoding = topicSchemaMetadata.encoding;\n\n // Make an encoder using the official avro-js library.\n const definition = fs.\n readFileSync('system-test/fixtures/provinces.avsc').\n toString();\n const type = avro.parse(definition);\n\n // Encode the message.\n const province = {\n name: 'Ontario',\n post_abbr: 'ON'\n };\n let dataBuffer;\n switch (schemaEncoding) {\n case Encodings.Binary:\n dataBuffer = type.toBuffer(province);\n break;\n case Encodings.Json:\n dataBuffer = Buffer.from(type.toString(province));\n break;\n default:\n console.log(`Unknown schema encoding: ${schemaEncoding}`);\n break;}\n\n if (!dataBuffer) {\n console.log(`Invalid encoding ${schemaEncoding} on the topic.`);\n return;\n }\n\n const messageId = await topic.publish(dataBuffer);\n console.log(`Avro record ${messageId} published.`);\n}\n// [END pubsub_publish_avro_records]\n\nfunction main(topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID') {\n publishAvroRecords(topicNameOrId).catch((err) => {\n console.error(err.message);\n process.exitCode = 1;\n });\n}\n\nmain(...process.argv.slice(2));" ] diff --git a/packages/typeless-sample-bot/src/samples.ts b/packages/typeless-sample-bot/src/samples.ts index b8e731a15a7..228afc9d6ca 100644 --- a/packages/typeless-sample-bot/src/samples.ts +++ b/packages/typeless-sample-bot/src/samples.ts @@ -23,6 +23,7 @@ import path from 'node:path'; import {typescript as presetTypescript} from './preset-loader.js'; import importToRequire from './transforms/import-to-require.js'; import nullCoalescing from './transforms/null-coalescing.js'; +import optionalChaining from './transforms/optional-chaining.js'; import {addComments} from './transforms/add-comments.js'; // Converts an async iterable into an array of the same type. @@ -85,7 +86,7 @@ export async function* filterByContents( // the transform process. const babelConfig = { presets: [[presetTypescript, {}]], - plugins: [[importToRequire], [nullCoalescing]], + plugins: [[importToRequire], [nullCoalescing], [optionalChaining]], parserOpts: {} as babel.ParserOptions, generatorOpts: { // Ensures that Babel keeps newlines so that comments end up diff --git a/packages/typeless-sample-bot/src/transforms/optional-chaining.ts b/packages/typeless-sample-bot/src/transforms/optional-chaining.ts new file mode 100644 index 00000000000..e39bbdf2179 --- /dev/null +++ b/packages/typeless-sample-bot/src/transforms/optional-chaining.ts @@ -0,0 +1,48 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as Babel from '@babel/types'; +import {NodePathSingle, VisitorPlugin} from './babel.js'; + +// Because optional chaining is still a proposal in many versions of Node, +// go ahead and convert it to plain '.'. It should work in TypeScript. +export default function optionalChaining(): VisitorPlugin { + return { + visitor: { + OptionalCallExpression(path: NodePathSingle) { + const node = path.node as Babel.OptionalCallExpression; + path.replaceWith(Babel.callExpression(node.callee, node.arguments)); + }, + OptionalMemberExpression(path: NodePathSingle) { + const node = path.node as Babel.OptionalMemberExpression; + path.replaceWith( + Babel.memberExpression( + node.object, + node.property, + node.computed, + node.optional + ) + ); + }, + LogicalExpression(path: NodePathSingle) { + const node = path.node as Babel.LogicalExpression; + if (node.operator === '??') { + path.replaceWith( + Babel.logicalExpression('||', node.left, node.right) + ); + } + }, + }, + }; +} diff --git a/packages/typeless-sample-bot/test/fixtures/folder/listenForAvroRecords.ts b/packages/typeless-sample-bot/test/fixtures/folder/listenForAvroRecords.ts index f479e04c13b..b363885b6fd 100644 --- a/packages/typeless-sample-bot/test/fixtures/folder/listenForAvroRecords.ts +++ b/packages/typeless-sample-bot/test/fixtures/folder/listenForAvroRecords.ts @@ -89,6 +89,8 @@ function listenForAvroRecords(subscriptionNameOrId: string, timeout: number) { subscription.removeListener('message', messageHandler); console.log(`${messageCount} message(s) received.`); }, timeout * 1000); + + use?.optional?.chaining?.(); } // [END pubsub_subscribe_avro_records]