wgc 0.80.1 → 0.81.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +1 -1
- package/dist/src/commands/router/plugin/commands/init.js +71 -21
- package/dist/src/commands/router/plugin/commands/init.js.map +1 -1
- package/dist/src/commands/router/plugin/commands/test.js +3 -1
- package/dist/src/commands/router/plugin/commands/test.js.map +1 -1
- package/dist/src/commands/router/plugin/templates/plugin.d.ts +12 -0
- package/dist/src/commands/router/plugin/templates/{go-plugin.js → plugin.js} +151 -90
- package/dist/src/commands/router/plugin/templates/plugin.js.map +1 -0
- package/dist/src/commands/router/plugin/templates/project.d.ts +9 -0
- package/dist/src/commands/router/plugin/templates/project.js +199 -0
- package/dist/src/commands/router/plugin/templates/project.js.map +1 -0
- package/dist/src/commands/router/plugin/toolchain.js +1 -1
- package/dist/src/commands/router/plugin/toolchain.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/dist/src/commands/router/plugin/templates/go-plugin.d.ts +0 -5
- package/dist/src/commands/router/plugin/templates/go-plugin.js.map +0 -1
package/dist/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable import/no-named-as-default-member */
|
|
1
2
|
import { access, mkdir, rename, rm, writeFile } from 'node:fs/promises';
|
|
2
3
|
import { tmpdir } from 'node:os';
|
|
3
4
|
import { randomUUID } from 'node:crypto';
|
|
@@ -8,17 +9,26 @@ import pupa from 'pupa';
|
|
|
8
9
|
import Spinner from 'ora';
|
|
9
10
|
import { compileGraphQLToMapping, compileGraphQLToProto } from '@wundergraph/protographic';
|
|
10
11
|
import { camelCase, upperFirst } from 'lodash-es';
|
|
11
|
-
import
|
|
12
|
+
import PluginTemplates from '../templates/plugin.js';
|
|
13
|
+
import ProjectTemplates from '../templates/project.js';
|
|
12
14
|
import { renderResultTree } from '../helper.js';
|
|
13
15
|
export default (opts) => {
|
|
14
16
|
const command = new Command('init');
|
|
15
17
|
command.description('Scaffold a new gRPC router plugin');
|
|
16
18
|
command.argument('name', 'Name of the plugin');
|
|
17
|
-
command.option('-
|
|
19
|
+
command.option('-p, --project <project>', 'Project name', 'cosmo');
|
|
20
|
+
command.option('-d, --directory <directory>', 'Directory to create the project in', '.');
|
|
21
|
+
command.option('--only-plugin', 'Only create the plugin without a router project', false);
|
|
18
22
|
command.option('-l, --language <language>', 'Programming language to use for the plugin', 'go');
|
|
19
23
|
command.action(async (name, options) => {
|
|
20
24
|
const startTime = performance.now();
|
|
21
|
-
const
|
|
25
|
+
const cwd = process.cwd();
|
|
26
|
+
if (options.onlyPlugin) {
|
|
27
|
+
options.project = '';
|
|
28
|
+
}
|
|
29
|
+
const projectDir = resolve(cwd, options.directory, options.project);
|
|
30
|
+
const pluginDir = resolve(cwd, projectDir, 'plugins', name);
|
|
31
|
+
const originalPluginName = name;
|
|
22
32
|
name = upperFirst(camelCase(name));
|
|
23
33
|
const serviceName = name + 'Service';
|
|
24
34
|
// Check if a directory exists
|
|
@@ -45,25 +55,65 @@ export default (opts) => {
|
|
|
45
55
|
spinner.fail(pc.yellow(`Language '${options.language}' is not supported yet. Using 'go' instead.`));
|
|
46
56
|
options.language = 'go';
|
|
47
57
|
}
|
|
48
|
-
await writeFile(resolve(tempDir, 'README.md'), pupa(readme, { name }));
|
|
49
|
-
await writeFile(resolve(srcDir, 'schema.graphql'), pupa(schema, { name }));
|
|
50
|
-
spinner.text = 'Generating mapping and proto files...';
|
|
51
|
-
const mapping = compileGraphQLToMapping(schema, serviceName);
|
|
52
|
-
await writeFile(resolve(generatedDir, 'mapping.json'), JSON.stringify(mapping, null, 2));
|
|
53
58
|
const goModulePath = 'github.com/wundergraph/cosmo/plugin';
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
spinner.text = 'Generating mapping and proto files...';
|
|
60
|
+
if (!options.onlyPlugin && options.project) {
|
|
61
|
+
await writeFile(resolve(tempDir, 'README.md'), pupa(ProjectTemplates.readme, { name, originalPluginName }));
|
|
62
|
+
await writeFile(resolve(srcDir, 'schema.graphql'), pupa(PluginTemplates.schema, { name }));
|
|
63
|
+
const mapping = compileGraphQLToMapping(PluginTemplates.schema, serviceName);
|
|
64
|
+
await writeFile(resolve(generatedDir, 'mapping.json'), JSON.stringify(mapping, null, 2));
|
|
65
|
+
const proto = compileGraphQLToProto(PluginTemplates.schema, {
|
|
66
|
+
serviceName,
|
|
67
|
+
packageName: 'service',
|
|
68
|
+
goPackage: goModulePath,
|
|
69
|
+
});
|
|
70
|
+
await writeFile(resolve(generatedDir, 'service.proto'), proto.proto);
|
|
71
|
+
await writeFile(resolve(generatedDir, 'service.proto.lock.json'), JSON.stringify(proto.lockData, null, 2));
|
|
72
|
+
await writeFile(resolve(srcDir, 'main.go'), pupa(PluginTemplates.mainGo, { serviceName }));
|
|
73
|
+
await writeFile(resolve(srcDir, 'main_test.go'), pupa(PluginTemplates.mainGoTest, { serviceName }));
|
|
74
|
+
await writeFile(resolve(tempDir, 'go.mod'), pupa(PluginTemplates.goMod, { modulePath: goModulePath }));
|
|
75
|
+
await writeFile(resolve(tempDir, 'Makefile'), pupa(PluginTemplates.makefile, { originalPluginName }));
|
|
76
|
+
await writeFile(resolve(tempDir, '.gitignore'), PluginTemplates.gitignore);
|
|
77
|
+
await writeFile(resolve(tempDir, '.cursorignore'), PluginTemplates.cursorIgnore);
|
|
78
|
+
// Create cursor rules in .cursor/rules
|
|
79
|
+
await mkdir(resolve(tempDir, '.cursor', 'rules'), { recursive: true });
|
|
80
|
+
await writeFile(resolve(tempDir, '.cursor', 'rules', 'plugin-development.mdc'), pupa(PluginTemplates.cursorRules, { name, originalPluginName }));
|
|
81
|
+
// Create a project directory structure
|
|
82
|
+
await mkdir(projectDir, { recursive: true });
|
|
83
|
+
await mkdir(resolve(projectDir, 'plugins'), { recursive: true });
|
|
84
|
+
// Write router config to the project root
|
|
85
|
+
await writeFile(resolve(projectDir, 'config.yaml'), ProjectTemplates.routerConfig);
|
|
86
|
+
await writeFile(resolve(projectDir, 'graph.yaml'), pupa(ProjectTemplates.graphConfig, { originalPluginName }));
|
|
87
|
+
await writeFile(resolve(projectDir, 'Makefile'), pupa(ProjectTemplates.makefile, { originalPluginName }));
|
|
88
|
+
await writeFile(resolve(projectDir, '.gitignore'), ProjectTemplates.gitignore);
|
|
89
|
+
await writeFile(resolve(projectDir, 'README.md'), pupa(ProjectTemplates.projectReadme, { name, originalPluginName }));
|
|
90
|
+
// Move plugin from temp directory to project plugins directory
|
|
91
|
+
await rename(tempDir, pluginDir);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
await writeFile(resolve(tempDir, 'README.md'), pupa(PluginTemplates.readme, { name, originalPluginName }));
|
|
95
|
+
await writeFile(resolve(tempDir, 'Makefile'), pupa(PluginTemplates.makefile, { originalPluginName }));
|
|
96
|
+
await writeFile(resolve(srcDir, 'schema.graphql'), pupa(PluginTemplates.schema, { name }));
|
|
97
|
+
const mapping = compileGraphQLToMapping(PluginTemplates.schema, serviceName);
|
|
98
|
+
await writeFile(resolve(generatedDir, 'mapping.json'), JSON.stringify(mapping, null, 2));
|
|
99
|
+
// Create cursor rules in .cursor/rules
|
|
100
|
+
await mkdir(resolve(tempDir, '.cursor', 'rules'), { recursive: true });
|
|
101
|
+
await writeFile(resolve(tempDir, '.cursor', 'rules', 'plugin-development.mdc'), pupa(PluginTemplates.cursorRules, { name, originalPluginName }));
|
|
102
|
+
const proto = compileGraphQLToProto(PluginTemplates.schema, {
|
|
103
|
+
serviceName,
|
|
104
|
+
packageName: 'service',
|
|
105
|
+
goPackage: goModulePath,
|
|
106
|
+
});
|
|
107
|
+
await writeFile(resolve(generatedDir, 'service.proto'), proto.proto);
|
|
108
|
+
await writeFile(resolve(generatedDir, 'service.proto.lock.json'), JSON.stringify(proto.lockData, null, 2));
|
|
109
|
+
await writeFile(resolve(srcDir, 'main.go'), pupa(PluginTemplates.mainGo, { serviceName }));
|
|
110
|
+
await writeFile(resolve(srcDir, 'main_test.go'), pupa(PluginTemplates.mainGoTest, { serviceName }));
|
|
111
|
+
await writeFile(resolve(tempDir, 'go.mod'), pupa(PluginTemplates.goMod, { modulePath: goModulePath }));
|
|
112
|
+
await writeFile(resolve(tempDir, '.gitignore'), PluginTemplates.gitignore);
|
|
113
|
+
await writeFile(resolve(tempDir, '.cursorignore'), PluginTemplates.cursorIgnore);
|
|
114
|
+
await mkdir(resolve(projectDir, 'plugins'), { recursive: true });
|
|
115
|
+
await rename(tempDir, pluginDir);
|
|
116
|
+
}
|
|
67
117
|
const endTime = performance.now();
|
|
68
118
|
const elapsedTimeMs = endTime - startTime;
|
|
69
119
|
const formattedTime = elapsedTimeMs > 1000 ? `${(elapsedTimeMs / 1000).toFixed(2)}s` : `${Math.round(elapsedTimeMs)}ms`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../../../src/commands/router/plugin/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../../../src/commands/router/plugin/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import os from 'node:os';
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { resolve } from 'pathe';
|
|
5
5
|
import Spinner from 'ora';
|
|
6
|
-
import { checkAndInstallTools, runGoTests } from '../toolchain.js';
|
|
6
|
+
import { checkAndInstallTools, installGoDependencies, runGoTests } from '../toolchain.js';
|
|
7
7
|
import { renderResultTree } from '../helper.js';
|
|
8
8
|
export default (opts) => {
|
|
9
9
|
const command = new Command('test');
|
|
@@ -22,6 +22,8 @@ export default (opts) => {
|
|
|
22
22
|
if (!options.skipToolsInstallation) {
|
|
23
23
|
await checkAndInstallTools(options.forceToolsInstallation);
|
|
24
24
|
}
|
|
25
|
+
spinner.text = 'Installing Go dependencies...';
|
|
26
|
+
await installGoDependencies(pluginDir, spinner);
|
|
25
27
|
const srcDir = resolve(pluginDir, 'src');
|
|
26
28
|
spinner.text = 'Running tests...';
|
|
27
29
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../../../../src/commands/router/plugin/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,OAAO,MAAM,KAAK,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../../../../../src/commands/router/plugin/commands/test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
/* eslint-disable no-tabs */
|
|
1
2
|
// We store the templates in code to avoid dealing with file system issues when
|
|
2
3
|
// building for bun and transpiling TypeScript.
|
|
3
|
-
|
|
4
|
+
const goMod = `
|
|
4
5
|
module {modulePath}
|
|
5
6
|
|
|
6
7
|
go 1.24.1
|
|
@@ -12,7 +13,21 @@ require (
|
|
|
12
13
|
google.golang.org/protobuf v1.36.5
|
|
13
14
|
)
|
|
14
15
|
`;
|
|
15
|
-
|
|
16
|
+
const makefile = `
|
|
17
|
+
.PHONY: build test generate
|
|
18
|
+
|
|
19
|
+
make: build
|
|
20
|
+
|
|
21
|
+
test:
|
|
22
|
+
npx wgc@latest router plugin test .
|
|
23
|
+
|
|
24
|
+
generate:
|
|
25
|
+
npx wgc@latest router plugin build . --generate-only
|
|
26
|
+
|
|
27
|
+
build:
|
|
28
|
+
npx wgc@latest router plugin build . --debug
|
|
29
|
+
`;
|
|
30
|
+
const mainGo = `package main
|
|
16
31
|
|
|
17
32
|
import (
|
|
18
33
|
"context"
|
|
@@ -55,7 +70,10 @@ func (s *{serviceName}) QueryHello(ctx context.Context, req *service.QueryHelloR
|
|
|
55
70
|
return response, nil
|
|
56
71
|
}
|
|
57
72
|
`;
|
|
58
|
-
|
|
73
|
+
const gitignore = `# Ignore the binary files
|
|
74
|
+
bin/
|
|
75
|
+
`;
|
|
76
|
+
const mainGoTest = `package main
|
|
59
77
|
|
|
60
78
|
import (
|
|
61
79
|
"context"
|
|
@@ -205,9 +223,9 @@ func TestSequentialIDs(t *testing.T) {
|
|
|
205
223
|
assert.Equal(t, "3", thirdResp.Hello.Id)
|
|
206
224
|
}
|
|
207
225
|
`;
|
|
208
|
-
|
|
226
|
+
const readme = `# {name} Plugin - Cosmo gRPC Subgraph Example
|
|
209
227
|
|
|
210
|
-
This repository contains a simple Cosmo gRPC subgraph plugin that showcases how to design APIs with GraphQL but implement them using gRPC methods instead of traditional resolvers.
|
|
228
|
+
This repository contains a simple Cosmo gRPC subgraph plugin that showcases how to design APIs with GraphQL Federation but implement them using gRPC methods instead of traditional resolvers.
|
|
211
229
|
|
|
212
230
|
## What is this demo about?
|
|
213
231
|
|
|
@@ -223,120 +241,163 @@ The plugin demonstrates:
|
|
|
223
241
|
- Proper structure for a Cosmo gRPC subgraph plugin
|
|
224
242
|
- How to test your gRPC service implementation with gRPC client and server without external dependencies
|
|
225
243
|
|
|
226
|
-
##
|
|
244
|
+
## Getting Started
|
|
245
|
+
|
|
246
|
+
Plugin structure:
|
|
247
|
+
|
|
248
|
+
\`\`\`
|
|
249
|
+
plugins/{originalPluginName}/
|
|
250
|
+
├── Makefile # Automation scripts
|
|
251
|
+
├── go.mod # Go module file with dependencies
|
|
252
|
+
├── go.sum # Go checksums file
|
|
253
|
+
├── src/
|
|
254
|
+
│ ├── main.go # Main plugin implementation
|
|
255
|
+
│ ├── main_test.go # Tests for the plugin
|
|
256
|
+
│ └── schema.graphql # GraphQL schema defining the API
|
|
257
|
+
├── generated/ # Generated code (created during build)
|
|
258
|
+
└── bin/ # Compiled binaries (created during build)
|
|
259
|
+
└── plugin # The compiled plugin binary
|
|
260
|
+
\`\`\`
|
|
227
261
|
|
|
228
|
-
|
|
229
|
-
- \`main.go\` - The gRPC service implementation with methods that replace GraphQL resolvers
|
|
230
|
-
- \`main_test.go\` - The gRPC service implementation with methods that replace GraphQL resolvers
|
|
231
|
-
- \`schema.graphql\` - The GraphQL schema defining the API contract
|
|
232
|
-
- \`generated/\` - Contains generated code from the plugin schema
|
|
233
|
-
- \`bin/\` - Contains compiled binaries of the plugin
|
|
262
|
+
## 🔧 Customizing Your Plugin
|
|
234
263
|
|
|
235
|
-
|
|
264
|
+
- Change the GraphQL schema in \`src/schema.graphql\` and regenerate the code with \`make generate\`.
|
|
265
|
+
- Implement the changes in \`src/main.go\` and test your implementation with \`make test\`.
|
|
266
|
+
- Build the plugin with \`make build\`.
|
|
236
267
|
|
|
237
|
-
|
|
268
|
+
## 📚 Learn More
|
|
238
269
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
270
|
+
For more information about Cosmo and building router plugins:
|
|
271
|
+
- [Cosmo Documentation](https://cosmo-docs.wundergraph.com/)
|
|
272
|
+
- [Cosmo Router Plugins Guide](https://cosmo-docs.wundergraph.com/router/plugins)
|
|
242
273
|
|
|
243
|
-
|
|
274
|
+
---
|
|
244
275
|
|
|
245
|
-
|
|
246
|
-
type World {
|
|
276
|
+
<p align="center">Made with ❤️ by <a href="https://wundergraph.com">WunderGraph</a></p>`;
|
|
277
|
+
const schema = `type World {
|
|
278
|
+
"""
|
|
279
|
+
The ID of the world
|
|
280
|
+
"""
|
|
247
281
|
id: ID!
|
|
282
|
+
"""
|
|
283
|
+
The name of the world
|
|
284
|
+
"""
|
|
248
285
|
name: String!
|
|
249
286
|
}
|
|
250
287
|
|
|
251
288
|
type Query {
|
|
289
|
+
"""
|
|
290
|
+
The hello query
|
|
291
|
+
"""
|
|
252
292
|
hello(name: String!): World!
|
|
253
293
|
}
|
|
254
|
-
|
|
294
|
+
`;
|
|
295
|
+
const cursorRules = `---
|
|
296
|
+
description: {name} Plugin Guide
|
|
297
|
+
globs: src/**
|
|
298
|
+
alwaysApply: false
|
|
299
|
+
---
|
|
255
300
|
|
|
256
|
-
|
|
301
|
+
# {name} Plugin Guide
|
|
257
302
|
|
|
258
|
-
|
|
303
|
+
This rule explains the structure and workflow for the Cosmo Router {name} plugin.
|
|
259
304
|
|
|
260
|
-
|
|
261
|
-
wgc router plugin build <plugin-directory>
|
|
262
|
-
\`\`\`
|
|
305
|
+
## Plugin Structure
|
|
263
306
|
|
|
264
|
-
|
|
307
|
+
The {name} plugin demonstrates how to implement a GraphQL API using gRPC methods:
|
|
265
308
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
- name: <plugin-name>
|
|
270
|
-
plugin:
|
|
271
|
-
version: 0.0.1
|
|
272
|
-
directory: <plugin-directory>/<plugin-name>
|
|
273
|
-
\`\`\`
|
|
309
|
+
- @src/schema.graphql - Defines the GraphQL schema
|
|
310
|
+
- @src/main.go - Contains the plugin implementation
|
|
311
|
+
- @src/main_test.go - Contains tests for the plugin
|
|
274
312
|
|
|
275
|
-
|
|
313
|
+
## Development Workflow
|
|
276
314
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
315
|
+
1. Make changes to @src/schema.graphql
|
|
316
|
+
2. Run \`make generate\` from the plugin directory to regenerate code
|
|
317
|
+
3. Implement the service:
|
|
318
|
+
- Implement the service in @main.go but you can create different files for each method if you think it leads to more readable code
|
|
319
|
+
- Review generated @generated/service.pb.go and @generated/service_grpc.pb.go
|
|
320
|
+
- Ensure ALL generated RPC methods and types are fully implemented
|
|
321
|
+
- Partial implementations will cause runtime errors
|
|
322
|
+
4. Update tests in @main_test.go:
|
|
323
|
+
- Add test cases for ALL new functionality
|
|
324
|
+
- Test both success and error scenarios
|
|
325
|
+
- Verify ALL edge cases
|
|
326
|
+
- Create different test files if it leads to more readable tests
|
|
327
|
+
5. Run \`make test\` to ensure complete test coverage
|
|
280
328
|
|
|
281
|
-
|
|
329
|
+
## Generated Code
|
|
282
330
|
|
|
283
|
-
|
|
284
|
-
wgc router plugin test <plugin-directory>/<plugin-name>
|
|
285
|
-
\`\`\`
|
|
286
|
-
or
|
|
287
|
-
\`\`\`bash
|
|
288
|
-
go test src -v
|
|
289
|
-
\`\`\`
|
|
290
|
-
if you have the Go toolchain already installed.
|
|
331
|
+
The code generation creates:
|
|
291
332
|
|
|
292
|
-
|
|
333
|
+
- @generated/service.proto - The protobuf service definition
|
|
334
|
+
- @generated/service.pb.go - Go structures for requests/responses
|
|
335
|
+
- @generated/service_grpc.pb.go - The gRPC service interface
|
|
293
336
|
|
|
294
|
-
|
|
295
|
-
execution_config:
|
|
296
|
-
file:
|
|
297
|
-
path: ./config.yaml
|
|
298
|
-
plugins:
|
|
299
|
-
- <plugin-directory>
|
|
300
|
-
\`\`\`
|
|
337
|
+
If the files doesn't exist, you need to generate them with \`make generate\`
|
|
301
338
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
Once running, you can perform GraphQL operations like:
|
|
305
|
-
|
|
306
|
-
\`\`\`graphql
|
|
307
|
-
# Hello query
|
|
308
|
-
query {
|
|
309
|
-
hello(name: "World") {
|
|
310
|
-
id
|
|
311
|
-
name
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
\`\`\`
|
|
339
|
+
**Important**: Never manipulate the @generated/ files yourself. The source of truth for the API contract is the GraphQL schema. Use \`make generate\` to update the proto and service interface.
|
|
315
340
|
|
|
316
|
-
##
|
|
341
|
+
## Important Implementation Pattern
|
|
317
342
|
|
|
318
|
-
|
|
319
|
-
- Change the GraphQL schema in \`src/schema.graphql\` and rebuild the plugin
|
|
343
|
+
When implementing a plugin:
|
|
320
344
|
|
|
321
|
-
|
|
345
|
+
1. Implement the generated service interface in \`main.go\`
|
|
346
|
+
2. Handle the context properly in your implementation methods
|
|
347
|
+
3. Ensure proper error handling and error messages
|
|
348
|
+
4. Follow Go conventions for naming and structuring your code
|
|
322
349
|
|
|
323
|
-
|
|
324
|
-
export const schema = `type World {
|
|
325
|
-
"""
|
|
326
|
-
The ID of the world
|
|
327
|
-
"""
|
|
328
|
-
id: ID!
|
|
329
|
-
"""
|
|
330
|
-
The name of the world
|
|
331
|
-
"""
|
|
332
|
-
name: String!
|
|
333
|
-
}
|
|
350
|
+
## Service Integration
|
|
334
351
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
352
|
+
If you need to integrate with other HTTP services, you should prefer to use the \`github.com/wundergraph/cosmo/router-plugin/httpclient\` package.
|
|
353
|
+
Always prefer a real integration over mocking. In the tests, you can mock the service by bootstrapping an http server that returns the expected response.
|
|
354
|
+
In tests, focus on a well-defined contract and the expected behavior of your service. Structure tests by endpoint, use-cases and use table-driven tests to cover all cases.
|
|
355
|
+
|
|
356
|
+
Example:
|
|
357
|
+
|
|
358
|
+
\`\`\`go
|
|
359
|
+
// Initialize HTTP client for external API calls
|
|
360
|
+
// The base URL is the URL of the external API
|
|
361
|
+
client := httpclient.New(
|
|
362
|
+
httpclient.WithBaseURL("<replace_with_base_url>"),
|
|
363
|
+
httpclient.WithTimeout(5*time.Second),
|
|
364
|
+
httpclient.WithHeaders(map[string]string{}),
|
|
365
|
+
)
|
|
366
|
+
// A HTTP GET request to the external API
|
|
367
|
+
resp, err := client.Get(ctx, "/<replace_with_path>")
|
|
368
|
+
// A HTTP POST/PUT/DELETE request to the external API with a struct that is marshalled to JSON
|
|
369
|
+
resp, err := client.Post(ctx, "/<replace_with_path>", payload)
|
|
370
|
+
// Passing payload with custom request options
|
|
371
|
+
resp, err := client.Put(ctx, "/<replace_with_path>", payload,
|
|
372
|
+
httpclient.WithHeaders(map[string]string{}),
|
|
373
|
+
)
|
|
374
|
+
// Unmarshal the JSON response into our data structure
|
|
375
|
+
data, err := httpclient.UnmarshalTo[[]ResponseType](resp)
|
|
376
|
+
// The response offers the following fields:
|
|
377
|
+
type Response struct {
|
|
378
|
+
StatusCode int
|
|
379
|
+
Headers http.Header
|
|
380
|
+
Body []byte
|
|
340
381
|
}
|
|
382
|
+
// You can check for success (StatusCode >= 200 && StatusCode < 300)
|
|
383
|
+
resp.IsSuccess()
|
|
384
|
+
\`\`\`
|
|
385
|
+
`;
|
|
386
|
+
const cursorIgnore = `# Ignore the mapping and lock files
|
|
387
|
+
generated/mapping.json
|
|
388
|
+
generated/service.proto.lock.json
|
|
389
|
+
# Ignore the plugin binary
|
|
390
|
+
bin/
|
|
341
391
|
`;
|
|
342
|
-
|
|
392
|
+
export default {
|
|
393
|
+
goMod,
|
|
394
|
+
mainGo,
|
|
395
|
+
mainGoTest,
|
|
396
|
+
readme,
|
|
397
|
+
schema,
|
|
398
|
+
gitignore,
|
|
399
|
+
makefile,
|
|
400
|
+
cursorRules,
|
|
401
|
+
cursorIgnore,
|
|
402
|
+
};
|
|
403
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../../../../src/commands/router/plugin/templates/plugin.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAE5B,+EAA+E;AAC/E,+CAA+C;AAE/C,MAAM,KAAK,GAAG;;;;;;;;;;;CAWb,CAAC;AAEF,MAAM,QAAQ,GAAG;;;;;;;;;;;;;CAahB,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Cd,CAAC;AAEF,MAAM,SAAS,GAAG;;CAEjB,CAAC;AAEF,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqJlB,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wFAkDyE,CAAC;AAEzF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;CAiBd,CAAC;AAEF,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0FnB,CAAC;AAEF,MAAM,YAAY,GAAG;;;;;CAKpB,CAAC;AAEF,eAAe;IACb,KAAK;IACL,MAAM;IACN,UAAU;IACV,MAAM;IACN,MAAM;IACN,SAAS;IACT,QAAQ;IACR,WAAW;IACX,YAAY;CACb,CAAC"}
|