-
Notifications
You must be signed in to change notification settings - Fork 192
feat: support grpc plugins with ts and bun #2293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
SkArchon
wants to merge
95
commits into
main
Choose a base branch
from
milinda/eng-7174-support-grpc-plugins-with-bun-typescript
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+10,656
−1,732
Open
Changes from 86 commits
Commits
Show all changes
95 commits
Select commit
Hold shift + click to select a range
29bb604
feat: cli updates
SkArchon e1c3dbd
fix: updates
SkArchon cc08a5b
feat: cli updates
SkArchon 5e68f51
feat: cli updates
SkArchon c2f32f7
fix: cli
SkArchon be23381
fix: updates
SkArchon 9053591
fix: updates
SkArchon 7abe72f
fix: updates
SkArchon 009ea52
fix: add health check service and move go router plugin
SkArchon f962e9d
fix: updates
SkArchon 809ae2e
fix: router plugin
SkArchon 1c480c5
fix: updates
SkArchon d41a606
fix: updates
SkArchon f6f7b61
fix: updates
SkArchon 6ea8136
fix: updates
SkArchon 2f4a1cc
fix: updates
SkArchon 81d8e08
fix: updates
SkArchon 1eb5db5
fix: updates
SkArchon 52adc57
fix: updates
SkArchon 11347a8
fix: updates
SkArchon f423a92
fix: updates
SkArchon 6ab77e9
fix: cleanup
SkArchon 19e1f19
fix: revert
SkArchon a06c05c
fix: cleanup
SkArchon a6a1255
fix: cleanup
SkArchon 5cda4dc
fix: cleanup
SkArchon e0025be
fix: updates
SkArchon df8c076
fix: templates
SkArchon 6eace15
fix: templates
SkArchon 10be6cb
fix: updates
SkArchon 6c1de9f
fix: lint changes
SkArchon 4897a0f
fix: linting
SkArchon 2a0292e
fix: updates
SkArchon 69c434f
fix: updates
SkArchon a94f90f
fix: changes
SkArchon 773d616
fix: temp
SkArchon df92322
fix: updates
SkArchon f8b2145
fix: updates
SkArchon c94513f
fix: updates
SkArchon 40a3d48
fix: updates
SkArchon dc15d41
fix: refactoring
SkArchon c7229ae
fix: refactoring
SkArchon 5340a19
fix: updates
SkArchon 48831fd
fix: ci changes
SkArchon 5feb446
fix: refactoring
SkArchon 30f48e6
fix: ci updates
SkArchon 7f4d714
fix: ci updates
SkArchon 0f9c289
fix: updates
SkArchon 2dddf0c
fix: refactoring`
SkArchon 4bb7b10
fix: revert
SkArchon 4bb5dd2
Merge branch 'main' into milinda/eng-7174-support-grpc-plugins-with-b…
SkArchon 56f4e28
fix: review comments
SkArchon f5a7089
fix: updates
SkArchon ee9307a
fix: recompile templates
SkArchon a00ed32
fix: cleanup
SkArchon 4e25bd4
fix: cleanup
SkArchon f20ff83
fix: updates
SkArchon db1d2f0
fix: refactoring
SkArchon 489b50a
fix: linting
SkArchon 760d277
Merge branch 'main' into milinda/eng-7174-support-grpc-plugins-with-b…
SkArchon 747854a
fix: refactoring
SkArchon 10125cc
fix: templates
SkArchon fc4bf7f
fix: platform updates
SkArchon c1580f2
fix: linting
SkArchon c9340e2
Merge branch 'main' into milinda/eng-7174-support-grpc-plugins-with-b…
SkArchon c2d0b81
fix: tests
SkArchon 4dce726
fix: templates
SkArchon a91f3dd
fix: tests
SkArchon 8a5bda0
fix: revert
SkArchon d4c8b78
fix: formatting
SkArchon 1672582
fix: update imports`
SkArchon 7883122
fix: demonstration
SkArchon 6fbd524
fix: update configuration
SkArchon e553b06
fix: diff testing
SkArchon 1991bf0
fix: diff updates
SkArchon 349e5b1
fix: project updates
SkArchon 10594aa
Merge branch 'main' into milinda/eng-7174-support-grpc-plugins-with-b…
SkArchon 4a9234b
fix: patch the grpc health check node modules
SkArchon 1291745
fix: template compilation
SkArchon 22f7c5b
Merge branch 'main' into milinda/eng-7174-support-grpc-plugins-with-b…
SkArchon d27a5f3
fix: local builds
SkArchon 3e523e8
fix: spinner updating
SkArchon a80cf59
fix: ts tests
SkArchon 770c4ba
fix: tests
SkArchon 49812b6
Merge remote-tracking branch 'origin/main' into milinda/eng-7174-supp…
SkArchon 04b622b
fix: linting
SkArchon 42273e1
fix: update makefile
SkArchon 10ba33e
fix: plugin build
SkArchon 3a08009
fix: workflows
SkArchon 1238bb2
fix: ci updates
SkArchon 9d291a2
fix: courses updates
SkArchon 07437fc
fix: go module
SkArchon a95f179
fix: enable debugging
SkArchon acb1628
fix: linting
SkArchon 2b4e469
fix: package updating
SkArchon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| import { describe, test, expect } from "bun:test"; | ||
| import * as grpc from "@grpc/grpc-js"; | ||
| import type { Subprocess } from "bun"; | ||
|
|
||
| // Generated gRPC types | ||
| import { CoursesServiceClient } from '../generated/service_grpc_pb.js'; | ||
| import { QueryHelloRequest, QueryHelloResponse } from "../generated/service_pb.js"; | ||
|
|
||
| function queryHello(client: CoursesServiceClient, name: string): Promise<QueryHelloResponse> { | ||
| return new Promise((resolve, reject) => { | ||
| const req = new QueryHelloRequest(); | ||
| req.setName(name); | ||
| client.queryHello(req, (err, resp) => { | ||
| if (err) { | ||
| reject(err); | ||
| return; | ||
| } | ||
| if (!resp) { | ||
| reject(new Error("empty response")); | ||
| return; | ||
| } | ||
| resolve(resp); | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| describe("CoursesServiceService.queryHello", () => { | ||
| test("returns greeting with sequential world IDs", async () => { | ||
| const [subprocess, address] = await startPluginProcess(); | ||
| const client = createClient(address); | ||
| try { | ||
| const cases = [ | ||
| { name: "Alice", wantId: "world-1", wantName: "Hello from CoursesServiceService plugin! Alice" }, | ||
| { name: "", wantId: "world-2", wantName: "Hello from CoursesServiceService plugin! " }, | ||
| { name: "John & Jane", wantId: "world-3", wantName: "Hello from CoursesServiceService plugin! John & Jane" }, | ||
| ]; | ||
|
|
||
| for (const c of cases) { | ||
| const resp = await queryHello(client, c.name); | ||
| const world = resp.getHello(); | ||
| expect(world).toBeTruthy(); | ||
| expect(world!.getId()).toBe(c.wantId); | ||
| expect(world!.getName()).toBe(c.wantName); | ||
| } | ||
| } finally { | ||
| client.close(); | ||
| subprocess.kill(); | ||
| } | ||
| }); | ||
|
|
||
| test("IDs increment across multiple requests in a fresh process", async () => { | ||
| const [subprocess, address] = await startPluginProcess(); | ||
| const client = createClient(address); | ||
| try { | ||
| const first = await queryHello(client, "First"); | ||
| expect(first.getHello()!.getId()).toBe("world-1"); | ||
|
|
||
| const second = await queryHello(client, "Second"); | ||
| expect(second.getHello()!.getId()).toBe("world-2"); | ||
|
|
||
| const third = await queryHello(client, "Third"); | ||
| expect(third.getHello()!.getId()).toBe("world-3"); | ||
| } finally { | ||
| client.close(); | ||
| subprocess.kill(); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
|
|
||
| async function startPluginProcess(): Promise<[Subprocess, string]> { | ||
| const proc = Bun.spawn(["bun", "run", "src/plugin.ts"], { | ||
| stdout: "pipe", | ||
| stderr: "inherit", | ||
| }); | ||
|
|
||
| // Read the first line from stdout and parse the address | ||
| if (!proc.stdout) { | ||
| throw new Error("plugin stdout not available"); | ||
| } | ||
| const reader = proc.stdout.getReader(); | ||
| const decoder = new TextDecoder(); | ||
| const { value } = await reader.read(); | ||
| reader.releaseLock(); | ||
|
|
||
| const text = decoder.decode(value ?? new Uint8Array()); | ||
| const firstLine = text.split("\n")[0]?.trim() ?? ""; | ||
| const parts = firstLine.split("|"); | ||
| const address = parts[3]; | ||
|
|
||
| return [proc, address]; | ||
| } | ||
|
|
||
| function createClient(address: string): CoursesServiceClient { | ||
| const target = `unix://$\\{address\\}`; | ||
| return new CoursesServiceClient(target, grpc.credentials.createInsecure()); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| import { readFileSync, writeFileSync, readdirSync } from 'node:fs'; | ||
| import { join, basename } from 'node:path'; | ||
|
|
||
| interface TemplateMap { | ||
| [key: string]: string; | ||
| } | ||
|
|
||
| // Convert file names to camelCase property names | ||
| function fileNameToPropertyName(fileName: string): string { | ||
| // Remove .template extension | ||
| let name = fileName.replace('.template', ''); | ||
|
|
||
| // Handle special cases for dotfiles | ||
| if (name.startsWith('.')) { | ||
| name = name.slice(1); // Remove the dot | ||
| } | ||
|
|
||
| // Convert to camelCase | ||
| // Split by dots, dashes, underscores, and spaces | ||
| const parts = name.split(/[ ._-]/); | ||
|
|
||
| return parts | ||
| .map((part, index) => { | ||
| // Normalize all-caps words (like README -> Readme) | ||
| if (part === part.toUpperCase() && part.length > 1) { | ||
| part = part.charAt(0) + part.slice(1).toLowerCase(); | ||
| } | ||
|
|
||
| if (index === 0) { | ||
| // First part: lowercase first char, preserve rest | ||
| return part.charAt(0).toLowerCase() + part.slice(1); | ||
| } | ||
| // Subsequent parts: uppercase first char, preserve rest | ||
| return part.charAt(0).toUpperCase() + part.slice(1); | ||
| }) | ||
| .join(''); | ||
| } | ||
|
|
||
| function compileTemplates(dir: string, outputFile: string, comment?: string) { | ||
| const files = readdirSync(dir).filter((f) => f.endsWith('.template')); | ||
|
|
||
| if (files.length === 0) { | ||
| console.log(`No templates found in ${dir}`); | ||
| return; | ||
| } | ||
|
|
||
| const templates: TemplateMap = {}; | ||
|
|
||
| for (const file of files) { | ||
| const filePath = join(dir, file); | ||
| const content = readFileSync(filePath, 'utf8'); | ||
|
|
||
| // Convert file name to property name | ||
| const key = fileNameToPropertyName(file); | ||
| templates[key] = content; | ||
| } | ||
|
|
||
| // Generate TypeScript file | ||
| const lines: string[] = []; | ||
|
|
||
| if (comment) { | ||
| lines.push(`// ${comment}`); | ||
| } | ||
| lines.push('// This file is auto-generated. Do not edit manually.'); | ||
| lines.push('/* eslint-disable no-template-curly-in-string */'); | ||
| lines.push(''); | ||
|
|
||
| // Create const declarations | ||
| for (const [key, content] of Object.entries(templates)) { | ||
| lines.push(`const ${key} = ${JSON.stringify(content)};`); | ||
| lines.push(''); | ||
| } | ||
|
|
||
| // Export default object | ||
| lines.push('export default {'); | ||
| for (const key of Object.keys(templates)) { | ||
| lines.push(` ${key},`); | ||
| } | ||
| lines.push('};'); | ||
| lines.push(''); | ||
|
|
||
| writeFileSync(outputFile, lines.join('\n'), 'utf8'); | ||
| console.log(`Generated ${outputFile} with ${files.length} templates`); | ||
| } | ||
|
|
||
| // Compile all template subdirectories, generating <templates>/<folder>.ts in the templates root | ||
| const templatesDir = 'src/commands/router/commands/plugin/templates'; | ||
|
|
||
| const entries = readdirSync(templatesDir, { withFileTypes: true }); | ||
| const subdirs = entries.filter((e: any) => e.isDirectory()); | ||
|
|
||
| if (subdirs.length === 0) { | ||
| console.log(`No template subdirectories found in ${templatesDir}`); | ||
| } else { | ||
| for (const dirent of subdirs) { | ||
| const dirName = dirent.name; | ||
| const dirPath = join(templatesDir, dirName); | ||
| const outFile = join(templatesDir, `${dirName}.ts`); | ||
| const comment = `Templates for ${dirName} (templating is done by pupa)`; | ||
| compileTemplates(dirPath, outFile, comment); | ||
| } | ||
| console.log('All templates compiled successfully'); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.