From 80b7644f1607225c69c7971c18aad3c729201251 Mon Sep 17 00:00:00 2001 From: twobiers <22715034+twobiers@users.noreply.github.com> Date: Fri, 6 Sep 2024 23:27:26 +0200 Subject: [PATCH] Implement multiple things --- .github/workflows/ci.yaml | 1 + .github/workflows/release.yaml | 44 ++++ .gitignore | 2 + buf.gen.yaml | 2 +- package-lock.json | 193 +++++++++++++++++- package.json | 31 ++- src/function.ts | 27 ++- {gen => src/gen}/v1/run_function_connect.ts | 0 .../gen}/v1beta1/run_function_connect.ts | 0 src/main.ts | 26 +++ tsconfig.json | 8 +- 11 files changed, 311 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/release.yaml rename {gen => src/gen}/v1/run_function_connect.ts (100%) rename {gen => src/gen}/v1beta1/run_function_connect.ts (100%) create mode 100644 src/main.ts diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index acba330..c4460a8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,5 +18,6 @@ jobs: uses: actions/setup-node@v4 with: node-version: 22 + cache: npm - run: npm ci - run: npm test \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..40a35bc --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,44 @@ +name: CD + +on: + push: + tags: + - "*" + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - run: npm ci + - run: npm test + + publish-package: + runs-on: ubuntu-latest + + needs: test + + permissions: + contents: read + id-token: write + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + registry-url: "https://registry.npmjs.org" + cache: npm + + - run: npm ci + - run: npm run build + - run: npm publish --access public --provenance + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index fbabc80..c214872 100644 --- a/.gitignore +++ b/.gitignore @@ -146,3 +146,5 @@ dist # ignore IDE folders .vscode/ .idea/ + +.dist/ diff --git a/buf.gen.yaml b/buf.gen.yaml index b55aa46..c289ac5 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -6,5 +6,5 @@ plugins: opt: target=ts out: src/gen - local: protoc-gen-connect-es - out: gen + out: src/gen opt: target=ts \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 23a7687..6605a60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,8 @@ "@connectrpc/connect-fastify": "^1.4.0", "@connectrpc/connect-node": "^1.4.0", "@kubernetes/client-node": "^0.21.0", - "fastify": "^4.28.1" + "fastify": "^4.28.1", + "yargs": "^17.7.2" }, "devDependencies": { "@bufbuild/buf": "^1.39.0", @@ -16,6 +17,7 @@ "@bufbuild/protoc-gen-es": "^1.10.0", "@connectrpc/connect": "^1.4.0", "@connectrpc/protoc-gen-connect-es": "^1.4.0", + "@types/yargs": "^17.0.33", "typescript": "^5.5.4" } }, @@ -397,6 +399,21 @@ "@types/node": "*" } }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, "node_modules/@typescript/vfs": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.0.tgz", @@ -623,6 +640,86 @@ "node": ">=18" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -731,6 +828,14 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -929,6 +1034,14 @@ "node": ">= 0.6" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -1497,6 +1610,14 @@ "node": ">= 0.12" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -2031,11 +2152,81 @@ } } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "optional": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } } } } diff --git a/package.json b/package.json index f40b519..fc59fc5 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,39 @@ { + "name": "function-sdk-typescript", + "version": "0.0.1", + "license": "Apache-2.0", + "description": "Crossplane Function SDK to build composition functions in TypeScript", + "homepage": "https://github.com/twobiers/function-sdk-typescript", + "author": "twobiers", + "type": "module", "scripts": { + "build": "tsc", "generate": "buf generate", "test": "node --test" }, + "dependencies": { + "@connectrpc/connect-fastify": "^1.4.0", + "@connectrpc/connect-node": "^1.4.0", + "@kubernetes/client-node": "^0.21.0", + "fastify": "^4.28.1", + "yargs": "^17.7.2" + }, "devDependencies": { "@bufbuild/buf": "^1.39.0", "@bufbuild/protobuf": "^1.10.0", "@bufbuild/protoc-gen-es": "^1.10.0", "@connectrpc/connect": "^1.4.0", "@connectrpc/protoc-gen-connect-es": "^1.4.0", + "@types/yargs": "^17.0.33", "typescript": "^5.5.4" }, - "dependencies": { - "@connectrpc/connect-fastify": "^1.4.0", - "@connectrpc/connect-node": "^1.4.0", - "@kubernetes/client-node": "^0.21.0", - "fastify": "^4.28.1" - } + "repository": { + "type": "git", + "url": "https://github.com/twobiers/function-sdk-typescript.git" + }, + "keywords": [ + "crossplane", + "function", + "sdk" + ] } diff --git a/src/function.ts b/src/function.ts index 771cb7c..d835281 100644 --- a/src/function.ts +++ b/src/function.ts @@ -1,7 +1,7 @@ import * as v1 from "./gen/v1/run_function_pb" import * as v1beta1 from "./gen/v1beta1/run_function_pb" -import { FunctionRunnerService as v1FunctionRunnerService } from "../gen/v1/run_function_connect"; -import { FunctionRunnerService as v1beta1FunctionRunnerService } from "../gen/v1beta1/run_function_connect"; +import { FunctionRunnerService as v1FunctionRunnerService } from "./gen/v1/run_function_connect"; +import { FunctionRunnerService as v1beta1FunctionRunnerService } from "./gen/v1beta1/run_function_connect"; import { fastify } from "fastify"; import { fastifyConnectPlugin } from "@connectrpc/connect-fastify"; import { PartialMessage } from "@bufbuild/protobuf"; @@ -14,6 +14,11 @@ type MTLSCertificates = { ca: string; } +export type FunctionServeOpts = { + insecure: boolean; + mtlsCertificates: MTLSCertificates; +} + export function loadMTLSCertificates(dir?: string): MTLSCertificates | Record { if (!dir) { return {}; @@ -26,14 +31,14 @@ export function loadMTLSCertificates(dir?: string): MTLSCertificates | Record PartialMessage, - certs: MTLSCertificates + opts: FunctionServeOpts ) { const server = fastify({ http2: true, https: { - ...certs + ...opts.mtlsCertificates } }); await server.register(fastifyConnectPlugin, { @@ -50,17 +55,17 @@ export async function newFunction( }) .service(v1beta1FunctionRunnerService, { async runFunction(request, _context) { - const b = request.toBinary(); - const gareq = v1.RunFunctionRequest.fromBinary(b); + const betaBinary = request.toBinary(); + const stableRequest = v1.RunFunctionRequest.fromBinary(betaBinary); - const garsp = new v1.RunFunctionResponse(fn(gareq)); + const stableResponse = new v1.RunFunctionResponse(fn(stableRequest)); - const bResp = garsp.toBinary(); - return v1beta1.RunFunctionResponse.fromBinary(bResp); + const stableResponseBinary = stableResponse.toBinary(); + return v1beta1.RunFunctionResponse.fromBinary(stableResponseBinary); } }); }, }); - await server.listen({ host: "localhost", port: 8443 }); + await server.listen({ host: "localhost", port: 9443 }); console.log("server is listening at", server.addresses()); } diff --git a/gen/v1/run_function_connect.ts b/src/gen/v1/run_function_connect.ts similarity index 100% rename from gen/v1/run_function_connect.ts rename to src/gen/v1/run_function_connect.ts diff --git a/gen/v1beta1/run_function_connect.ts b/src/gen/v1beta1/run_function_connect.ts similarity index 100% rename from gen/v1beta1/run_function_connect.ts rename to src/gen/v1beta1/run_function_connect.ts diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..77a1bc3 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,26 @@ +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; + +yargs(hideBin(process.argv)) + .command('serve [port]', 'start the server', (yargs) => { + return yargs + .env() + .option('debug', { + describe: 'Enable debug logging', + type: "boolean", + default: false, + }) + .option('insecure', { + describe: 'Disable gRPC transport security', + type: "boolean", + default: false, + }) + .option('tls-certs-dir', { + describe: 'A directory containing mTLS server certs (tls.key and tls.crt), and a CA used to verify clients (ca.crt).', + type: "string", + default: "", + }) + }, (argv) => { + + }) + .parse() \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 8bb6097..7b37618 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ @@ -25,9 +25,9 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ + "module": "ESNext", /* Specify what module code is generated. */ // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ @@ -55,7 +55,7 @@ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ + "outDir": "./dist", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ // "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */