diff --git a/.github/workflows/npm-publish-github-packages.yml b/.github/workflows/npm-publish-github-packages.yml new file mode 100644 index 0000000..47a37f9 --- /dev/null +++ b/.github/workflows/npm-publish-github-packages.yml @@ -0,0 +1,36 @@ +# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created +# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages + +name: Node.js Package + +on: + release: + types: [created] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - run: npm ci + - run: npm test + + publish-gpr: + needs: build + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + registry-url: https://npm.pkg.github.com/ + - run: npm ci + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 0000000..8bec15a --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,20 @@ +name: Publish to npm + +on: + push: + branches: + - main # Ersetzen Sie 'main' durch den Namen Ihrer Hauptbranch, falls anders + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: '14' # Ersetzen Sie '14' durch die gewünschte Node.js-Version + registry-url: 'https://registry.npmjs.org' + - run: npm ci + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} \ No newline at end of file diff --git a/README.md b/README.md index 45a5f5d..56c75ee 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,141 @@ -# Protocol Buffers for Node -A wrapper in Node for the compiled protoc from https://github.com/protocolbuffers/protobuf. -## Version -It's currently using Protocol Buffers `v3.20.3`. +# protoc-helper +[![npm version](https://badge.fury.io/js/protoc-helper.svg)](https://badge.fury.io/js/protoc-helper) +[![NPM Downloads](https://img.shields.io/npm/dw/protoc-helper.svg)](https://www.npmjs.com/package/protoc-helper) +[![npm version](https://img.shields.io/badge/protoc_v26.0-binary-blue)](https://www.npmjs.com/package/protoc-helper) -## Platforms -Google only provides binary files for Windows, Linux and OSX in x86_64 and x86_32. +A multilanguage protoc protobuff generator for node. uses the protoc binary and supports multiple platforms and processors. forked from [node-protoc](https://github.com/YePpHa/node-protoc) to add additional languages. +. Please see [Protobuf Plugin Installation](https://github.com/ji-podhead/protoc-helper/tree/master?tab=readme-ov-file#protobuf-plugin-installation) to install the required plugins for your target language. -## Examples -There's currently no documentation. Hopefully this example will help. +## Install +- **local:** `npm i protoc-helper` +- **cli-tool:** `npx install protoch` +## How to use +- you can find a demoscript and the proto file in the scripts folder. +--- + +**CLI (via npx global install)** +```JavaScript +npx protoch +npx protoc --go_out= --proto_path= // exchange --go_out is using another lamguage +``` +--- +**via Script**
+`without instance` (array not supported) +```JavaScript +createProtobuff( ) +createProtobuff( ) +``` +`using class instance` ```JavaScript -var protoc = require("protoc"); - -protoc.library(["path/to/file.proto", "path/to/file2.proto"], function(err, files) { - if (err) { - console.error(err); - return; - } - - // Handle the JavaScript Vinyl files. - // These files can be used in Google Closure Compiler, - // but they require the files in - // https://github.com/google/protobuf/tree/master/js - - // ... -}); +generator.generateProtobuf( ) ``` +`usings array` for multiple files -It's also possible to directly call the protoc binary file: +```JavaScript +generator.generateProtobuf([[ ],[ ]]) ``` -npx protoc --help +--- +### Arguments + **lang** The programming language for which the Protobuf file should be generated. +
**total_proto_file_path** The path to the Proto file that should be used as the source. +
**output_path** The path where the generated Protobuf file should be saved +
**proto_file** The name of the proto file including the extension. +
**proto_file_folder** A path to a folder that holds a proto file. + +### Example +```JavaScript +const {ProtobuffGenerator,createProtobuff} = require("protoc-helper") +const generator = new ProtobuffGenerator() +const dir = String(__dirname)+"/" +generator.generateProtobuf([["go",dir,"helloworld.proto",dir],["python",dir,"helloworld.proto",dir]]) + ``` + + +--- + +if you like this package, pls consider giving Jeppe’s and my repo a Star on github + +--- +## Protobuf Plugin Installation + +### JavaScript/TypeScript +- **Repository**: [https://github.com/improbable-eng/ts-protoc-gen](https://github.com/improbable-eng/ts-protoc-gen) +- **Installation**: npm install ts-protoc-gen `already added to dependencies` +### Go +- **Repository**: [https://github.com/golang/protobuf](https://github.com/golang/protobuf) +- **Installation**: bash go get -u github.com/golang/protobuf/protoc-gen-go + + +### Java +- **Repository**: [https://github.com/google/protobuf-gradle-plugin](https://github.com/google/protobuf-gradle-plugin) +- **Installation**: gradle plugins { id 'com.google.protobuf' version '0.8.17' } + + +### Python +- **Repository**: [https://github.com/protocolbuffers/protobuf](https://github.com/protocolbuffers/protobuf) +- **Installation**:`may doesnt need plugin` see https://protobuf.dev/reference/python/python-generated/ + + +### C# +- **Repository**: [https://github.com/protocolbuffers/protobuf](https://github.com/protocolbuffers/protobuf) +- **Installation**: powershell Install-Package Google.Protobuf.Tools `or it may doesnt need plugin` + + +### Ruby +- **Repository**: [https://github.com/localshred/protobuf](https://github.com/localshred/protobuf) +- **Installation**: doesnt need plugin, but might check out https://github.com/ruby-protobuf/protobuf + + +### Objective-C +- **Repository**: [[https://github.com/alexeyxo/protobuf-objc](https://github.com/protocolbuffers/protobuf](https://github.com/alexeyxo/protobuf-objc) +- **Installation**: may require cocoapod. see repo above + + +### PHP +- **Repository**: [https://github.com/protocolbuffers/protobuf](https://github.com/protocolbuffers/protobuf) +- **Installation**: doesnt need plugin + + +### Dart +- **Repository**: [https://github.com/dart-lang/protobuf](https://github.com/dart-lang/protobuf) +- **Installation**: bash dart pub global activate protoc_plugin + + +### Rust +- **Repository**: (https://github.com/neoeinstein/protoc-gen-prost](https://github.com/neoeinstein/protoc-gen-prost) +- **Installation**:*see repo + + +### Swift +- **Repository**: [https://github.com/apple/swift-protobuf](https://github.com/apple/swift-protobuf) +- **Installation**: swift // Add SwiftProtobuf as a dependency to your Xcode project + + +### Kotlin +- **Repository**: [https://github.com/grpc/grpc-kotlin/tree/master/compiler](https://github.com/grpc/grpc-kotlin/tree/master/compiler) +- **Installation**:Clone and build the plugin; it clone https://github.com/grpc/grpc-kotlin.git cd grpc-kotlin/compiler ./gradlew installDist + + +### Scala +- **Repository**: [https://github.com/scalapb/ScalaPB](https://github.com/scalapb/ScalaPB) +- **Installation**:Add ScalaPB as a dependency to your sbt project libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.11.1" + + + +## NPX and additional args + +you can use `npx protoc` or add your own arguments in the index.js: +```JavaScript + switch (language) { + case 'go': + // Example for Go --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative + command = `npx protoc --go_out=${outputPath} --proto_path=${proto_path} ${proto_file}`; + break; + case 'java': + // Example for Java + command = `npx protoc --java_out=${outputPath} --proto_path=${proto_path} ${proto_file}`; + break; + case 'python': ``` diff --git a/index.js b/index.js index 1daed70..3cea824 100644 --- a/index.js +++ b/index.js @@ -1,130 +1,150 @@ -const path = require("path"); -const cp = require("child_process"); +//other languages const fs = require("fs"); -const protoc = require("./protoc.js"); -const Vinyl = require("vinyl"); -const uuid = require("uuid"); -const mkdirp = require("mkdirp"); -const glob = require("glob"); - -exports.protoc = function(args, options, callback) { - cp.execFile(protoc, args, options, callback); -}; - -exports.closure = function(files, options, callback) { - if (!callback) { - callback = options; - options = null; - } - - options.imports = options.imports || []; - options.outputPath = options.outputPath || "./"; - - const cwd = process.cwd(); - const absoluteOutputPath = path.resolve(cwd, options.outputPath); - const relative = path.relative(absoluteOutputPath, cwd); - - const args = [ - "--js_out=one_output_file_per_input_file,binary:." - ]; - - for (var i = 0; i < options.imports.length; i++) { - args.push("-I", path.join(relative, options.imports[i])); - } - - for (var i = 0; i < files.length; i++) { - args.push(path.join(relative, files[i])); - } - - mkdirp(options.outputPath, function(err) { - if (err) { - callback(err); - return; - } - - exports.protoc(args, { - "cwd": options.outputPath - }, callback); - }); -}; - -/** - * Converts .proto files to .js files that can be used in Google Closure - * Compiler. - * The generated .js files require the files in - * https://github.com/protocolbuffers/protobuf/tree/v3.20.3/js. - * @param {?Array} files the proto files. - * @param {?function(?Error, ?Array)} callback the callback method. +const { exec } = require('child_process'); +const path = require('path'); +const cp = require("child_process"); +const { type } = require("os"); + + +/** + * @description Generate your protobuf files. Array is not supported. + * Use the function in one of the following ways: + * - Absolute path:`createProtobuff(,,)` + * - Name and Path:`createProtobuff(,,,)` + * @param {string} lang - Target language + * @param {string} output_path - The folder where your protobuf files are getting placed + * @param {string} proto_file - The name of the proto file (used when specifying the folder and file name separately) + * @param {string} proto_file_folder - The folder where your proto file is located (used when specifying the folder and file name separately) + * @param {string} absolute_proto_file_path - The folder path and the proto file in one string (used when specifying the `.proto` file path directly) */ -exports.library = function(files, callback) { - var dirpath = "tmp"; - var filename = uuid.v4(); - var jsFile = path.join(dirpath, filename); - mkdirp("tmp", function(err) { - if (err) { - callback(err); - return; +function createProtobuff(lang,output_path,proto_file_folder,proto_file){ + let directoryPath,fileName + if(proto_file==undefined) { + directoryPath = path.dirname(proto_file_folder); + fileName = path.basename(proto_file_folder); + console.log(`Directory: ${directoryPath}`); + console.log(`File Name: ${fileName}`); } - - exports.protoc(["--js_out=library=" + jsFile + ",binary:."].concat(files), function(err, stdout, stderr) { - if (err) { - callback(err); - return; - } - - if (fs.existsSync(jsFile + ".js")) { - fs.readFile(jsFile + ".js", function(err, contents) { - if (err) { - callback(err); - return; - } - - fs.unlink(jsFile + ".js", function(err) { - if (err) { - callback(err); - return; + else{ + directoryPath=proto_file + fileName=proto_file_folder + } + new ProtobuffGenerator().generateProtobuff(lang,output_path,fileName,directoryPath) +} + +function mycallback(){ + //console.log("created ") + } +class ProtobuffGenerator { + /** + * Constructor for the ProtobufGenerator class. + * Initializes necessary variables and configurations. + */ + constructor() { + // Initialization of necessary variables and configurations + // This could include setting up paths, loading configurations, etc. + } + + /** + * @description Generate your protobuf files. Array is not supported. + * Use the function in one of the following ways: + * - no Array:`generateProtobuff( )` + * - with Array:`generateProtobuff([[,,,],...])` + * @param {string|Array} lang - The programming language for which the Protobuf file should be generated. + * @param {string} outputPath - The path where the generated Protobuf file should be saved. + * @param {string} proto_file - The name of the Proto file that should be used as the source. + * @param {string} proto_file_folder - The folder where the Proto file is located that should be used as the source. + * @throws {Error} If the specified language is not supported. + */ + generateProtobuff(lang,output_path, proto_file,proto_file_folder,additionalCommands) { + let command; + let arr + switch (lang) { + case 'go': + // Example for Go --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative + command = `npx protoc --go_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'java': + // Example for Java + command = `npx protoc --java_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'python': + // Example for Python + command = `npx protoc --python_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'csharp': + // Example for C# + command = `npx protoc --objc_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'ruby': + // Example for Ruby + command = `npx protoc --ruby_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'objc': + // Example for Objective-C + command = `npx protoc --objc_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'php': + // Example for PHP + command = `npx protoc --php_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'dart': + // Example for Dart + command = `npx protoc --dart_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'rust': + // Example for Rust + command = `npx protoc --rust_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'swift': + // Example for Swift + command = `npx protoc --swift_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'kotlin': + // Example for Kotlin + command = `npx protoc --kotlin_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'scala': + // Example for Scala + command = `npx protoc --scala_out=${output_path} ${additionalCommands?additionalCommands:""} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'js': + command = `npx protoc --js_out=${output_path} --proto_path=${proto_file_folder} ${proto_file}`; + break; + case 'ts': + // Example for JavaScript/TypeScript + command= `npx protoc --ts_out=${output_path} --proto_path=${proto_file_folder} ${proto_file}` + break; + default: + + if(Array.isArray(lang)){ + arr = true; + for (let arg of lang){ + this.generateProtobuff(...arg); + } + } else if(typeof(lang) == 'object'){ + arr = true; + for (let arg in lang){ + this.generateProtobuff(...arg); + + } + } else { + throw new Error(`Unsupported language: ${lang}`); + } } - - fs.rmdir(dirpath, function() { - callback(null, [new Vinyl({ - "cwd": "/", - "base": "/", - "path": filename + ".js", - "contents": contents - })]); - }); - }); - }); - } else { - glob("**/*.js", { - "cwd": jsFile - }, function(err, matches) { - if (err) { - callback(err, null); + if(arr!=true){ + } +if(arr!=true) + { exec(command, function(err, stdout, stderr) { + if (err) { + console.error(err); return; - } - - var files = matches.map(function(match) { - return new Vinyl({ - "cwd": "/", - "base": "/", - "path": match, - "contents": fs.readFileSync(path.join(jsFile, match)) - }); - }); - - rimraf(jsFile, function(err) { - if (err) { - callback(err); - return; - } - - fs.rmdir(dirpath, function() { - callback(null, files); - }); - }); - }); - } - }); - }); -}; + } + console.log("__________\n"+"finished command: " + JSON.stringify([lang,output_path, proto_file,proto_file_folder, additionalCommands])) +// mycallback(null, stdout, stderr); + } + ) + } + } + } +module.exports ={createProtobuff,ProtobuffGenerator} diff --git a/package copy.json b/package copy.json new file mode 100644 index 0000000..1afb33b --- /dev/null +++ b/package copy.json @@ -0,0 +1,37 @@ +{ + "name": "@ji-podhead/protoc-helper", + "version": "1.0.5", + "description": "multilanguage grpc protobuff generator for node. forked from node-protoc.git. ", + "main": "index.js", + "scripts": { + "postinstall": "node scripts/postinstall.js", + "test": "node scripts/test.js", + "build": "npm run build", + "deploy": "npm publish" + }, + "bin": { + "protoc": "./bin/protoc" + }, + "author": "ji & Jeppe Rune Mortensen ", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/ji-podhead/protoc-helper" + }, + "publishConfig": { + "registry": "https://npm.pkg.github.com", + "access": "public", + "token": "{{NPM_TOKEN}}" + }, + "dependencies": { + "@ji-podhead/protoc-helper": "^1.0.3", + "glob": "^7.2.3", + "mkdirp": "^0.5.6", + "node-fetch": "^3.2.10", + "protoc-gen-ts": "^0.8.7", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11", + "uuid": "^9.0.0", + "vinyl": "^2.2.1" + } +} diff --git a/package.json b/package.json index e726168..63455d2 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,56 @@ { - "name": "protoc", - "version": "1.1.3", - "description": "A tool for converting proto buffers (.proto) files into javascript files usable in Closure Compiler with Closure Library.", + "name": "protoc-helper", + "version": "1.0.18", + "description": "multilanguage grpc protobuff generator for node. uses the protoc binary and supports multiple platforms and processors. forked from node-protoc.git. ", "main": "index.js", "scripts": { "postinstall": "node scripts/postinstall.js", - "test": "node scripts/test.js" + "test": "node scripts/test.js", + "build": "npm run build", + "deploy": "npm publish" }, "bin": { "protoc": "./bin/protoc" }, - "author": "Jeppe Rune Mortensen ", + "author": "ji & Jeppe Rune Mortensen ", "license": "MIT", "repository": { "type": "git", - "url": "git+https://github.com/YePpHa/node-protoc.git" + "url": "https://github.com/ji-podhead/protoc-helper" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" }, "dependencies": { "glob": "^7.2.3", "mkdirp": "^0.5.6", "node-fetch": "^3.2.10", + "protoc-gen-ts": "^0.8.7", "rimraf": "^3.0.2", "unzipper": "^0.10.11", "uuid": "^9.0.0", "vinyl": "^2.2.1" - } + }, + "keywords": [ + "protobuff_gen for node", + "protoc binary for node", + "grpc", + "protoc", + "protoc-gen", + "ts", + "go", +"java", +"python", +"csharp", +"ruby", +"objc", +"php", +"dart", +"rust", +"swift", +"kotlin", +"scala", +"js" + ] } diff --git a/scripts/helloworld.proto b/scripts/helloworld.proto new file mode 100644 index 0000000..c92cec6 --- /dev/null +++ b/scripts/helloworld.proto @@ -0,0 +1,41 @@ +// Copyright 2015 gRPC authors. +// +// 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. +//demoproto +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "./"; +option java_outer_classname = "HelloWorldProto"; +option objc_class_prefix = "HLW"; +option go_package = "./"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} + + rpc SayHelloStreamReply (HelloRequest) returns (stream HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/scripts/postinstall.js b/scripts/postinstall.js index a606585..02c2080 100644 --- a/scripts/postinstall.js +++ b/scripts/postinstall.js @@ -4,7 +4,7 @@ const unzip = require("unzipper"); const mkdirp = require("mkdirp"); const protoc = require("../protoc.js"); -const protoVersion = "3.20.3"; +const protoVersion = "26.0"; const releases = { "win32_x86_32": `https://github.com/protocolbuffers/protobuf/releases/download/v${protoVersion}/protoc-${protoVersion}-win32.zip`, diff --git a/scripts/test.js b/scripts/test.js index 930d513..bd86e07 100644 --- a/scripts/test.js +++ b/scripts/test.js @@ -1,7 +1,16 @@ -const protoc = require("../index.js"); -protoc.library(["protoc/include/google/protobuf/timestamp.proto"], function(err, files) { - if (err) { - console.error(err); - return; - } -}); +//newtest +const { ProtobuffGenerator, createProtobuff } = require('../index'); +const path = require('path'); +console.log(__dirname) +const dir = String(__dirname) + +console.log("_______ WITHOUT CLASS _________") +createProtobuff("js",dir,path.join(dir,"helloworld.proto")) + +console.log("_______ CLASS _________") +const generator = new ProtobuffGenerator() +generator.generateProtobuff("js",dir,"helloworld.proto",dir) + +console.log("_______ CLASS + ARRAY ARGUMENTS_________") +generator.generateProtobuff([["go",dir,"helloworld.proto",dir],["python",dir,"helloworld.proto",dir]]) +