diff --git a/cosmo-router/graph.yaml b/cosmo-router/graph.yaml index f12d606..7b188a3 100644 --- a/cosmo-router/graph.yaml +++ b/cosmo-router/graph.yaml @@ -6,4 +6,7 @@ subgraphs: file: ../subgraphs/products/schema.graphql - plugin: version: 0.0.1 - path: plugins/users \ No newline at end of file + path: plugins/users + - plugin: + version: 0.0.1 + path: plugins/courses \ No newline at end of file diff --git a/cosmo-router/package.json b/cosmo-router/package.json index 810deac..c8676b0 100644 --- a/cosmo-router/package.json +++ b/cosmo-router/package.json @@ -6,9 +6,19 @@ "type": "module", "scripts": { "compose": "wgc router compose -i graph.yaml -o config.json", - "build": "wgc router plugin build plugins/users --debug && npm run compose", - "test": "wgc router plugin test plugins/users", - "generate": "wgc router plugin build plugins/users --generate-only", + + "build:users": "wgc router plugin build plugins/users --debug", + "build:courses": "wgc router plugin build plugins/courses --debug", + "build": "npm run build:users && npm run build:courses && npm run compose", + + "test:users": "wgc router plugin test plugins/users", + "test:courses": "wgc router plugin test plugins/courses", + "test": "npm run test:users && npm run test:courses", + + "generate:users": "wgc router plugin build plugins/users --generate-only", + "generate:courses": "wgc router plugin build plugins/courses --generate-only", + "generate": "npm run generate:users && npm run generate:courses", + "postinstall": "rm -rf release && wgc router download-binary -o release && chmod +x release/router", "start": "./release/router" }, diff --git a/cosmo-router/plugins/courses/.gitignore b/cosmo-router/plugins/courses/.gitignore new file mode 100644 index 0000000..3d1eaf8 --- /dev/null +++ b/cosmo-router/plugins/courses/.gitignore @@ -0,0 +1,2 @@ +# Ignore the binary files +bin/ diff --git a/cosmo-router/plugins/courses/Makefile b/cosmo-router/plugins/courses/Makefile new file mode 100644 index 0000000..d2bec31 --- /dev/null +++ b/cosmo-router/plugins/courses/Makefile @@ -0,0 +1,19 @@ + +.PHONY: build test generate install-wgc + +install-wgc: + @which wgc > /dev/null 2>&1 || npm install -g wgc@latest + +make: build + +test: install-wgc + wgc router plugin test . + +generate: install-wgc + wgc router plugin generate . + +publish: generate + wgc router plugin publish . + +build: install-wgc + wgc router plugin build . --debug diff --git a/cosmo-router/plugins/courses/README.md b/cosmo-router/plugins/courses/README.md new file mode 100644 index 0000000..555d9d8 --- /dev/null +++ b/cosmo-router/plugins/courses/README.md @@ -0,0 +1,120 @@ +# Courses Plugin + +A Cosmo Router plugin for course management and enrollment. This plugin provides a GraphQL API for managing courses, instructors, and student enrollments using gRPC service implementation. + +## Features + +- Course creation and management +- Instructor course assignments +- In-memory data storage with mock data + +## Testing + +The tests validate all functionality of the plugin including: + +- Course querying (all courses and by ID) +- User lookup by ID (instructors and students) +- Course creation +- Student enrollment in courses + +### Running Tests + +```bash +cd cosmo-router/plugins/courses +make test +``` + +## Directory Structure + +``` +courses/ +├── bin/ # Compiled plugin binaries +├── generated/ # Auto-generated gRPC code from schema +│ ├── service.pb.js +│ ├── service_grpc_pb.js +│ └── service.proto +├── src/ # Source code +│ ├── plugin.ts # Plugin implementation +│ ├── plugin.test.ts # Integration tests +│ ├── plugin-server.ts # gRPC server setup +│ └── schema.graphql # GraphQL schema definition +└── package.json # Dependencies +``` + +## GraphQL API + +### Queries + +- `courses`: List all courses +- `course(id: ID!)`: Get a course by ID + +### Mutations + +- `createCourse(input: CourseInput!)`: Create a new course +- `enrollUser(userId: ID!, courseId: ID!)`: Enroll a user in a course + + +## Example GraphQL Operations + +```graphql +# Get all courses +query { + courses { + id + title + description + instructor { + id + } + durationHours + published + } +} + +# Get a specific course +query { + course(id: "course-1") { + id + title + description + instructor { + id + } + durationHours + published + } +} + +# Create a new course +mutation { + createCourse(input: { + title: "Advanced GraphQL" + description: "Master GraphQL concepts" + instructorId: "1" + durationHours: 30 + published: true + }) { + id + title + description + instructor { + id + } + } +} + +# Enroll a user in a course +mutation { + enrollUser(userId: "user-1", courseId: "course-1") { + id + user { + id + } + course { + id + title + } + progress + } +} +``` \ No newline at end of file diff --git a/cosmo-router/plugins/courses/bun.lock b/cosmo-router/plugins/courses/bun.lock new file mode 100644 index 0000000..7d6f51a --- /dev/null +++ b/cosmo-router/plugins/courses/bun.lock @@ -0,0 +1,236 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "plugin-bun", + "dependencies": { + "@grpc/grpc-js": "^1.14.0", + "google-protobuf": "^4.0.0", + "grpc-health-check": "2.1.0", + }, + "devDependencies": { + "@protocolbuffers/protoc-gen-js": "4.0.0", + "@types/bun": "^1.3.1", + "@types/google-protobuf": "^3.15.12", + "@types/node": "^20.11.5", + "grpc-tools": "^1.12.4", + "grpc_tools_node_protoc_ts": "^5.3.3", + }, + }, + }, + "patchedDependencies": { + "@protobufjs/inquire@1.1.0": "patches/@protobufjs_inquire@1.1.0.patch", + "grpc-health-check@2.1.0": "patches/grpc-health-check@2.1.0.patch", + }, + "packages": { + "@grpc/grpc-js": ["@grpc/grpc-js@1.14.1", "", { "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-sPxgEWtPUR3EnRJCEtbGZG2iX8LQDUls2wUS3o27jg07KqJFMq6YDeWvMo1wfpmy3rqRdS0rivpLwhqQtEyCuQ=="], + + "@grpc/proto-loader": ["@grpc/proto-loader@0.8.0", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.5.3", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ=="], + + "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="], + + "@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@1.0.11", "", { "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", "make-dir": "^3.1.0", "node-fetch": "^2.6.7", "nopt": "^5.0.0", "npmlog": "^5.0.1", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.11" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ=="], + + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], + + "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], + + "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="], + + "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="], + + "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="], + + "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], + + "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="], + + "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], + + "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], + + "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], + + "@protocolbuffers/protoc-gen-js": ["@protocolbuffers/protoc-gen-js@4.0.0", "", { "dependencies": { "adm-zip": "^0.5.16" }, "bin": { "protoc-gen-js": "cli.js" } }, "sha512-mbh4dOKkAW8y5cOFjcwBFE6O2AIk/douB6Xgz2BcD7muAgX0Xh3gkVbwb6lHJlT8AvRGAUWhlsmx0YO2j967uA=="], + + "@types/bun": ["@types/bun@1.3.2", "", { "dependencies": { "bun-types": "1.3.2" } }, "sha512-t15P7k5UIgHKkxwnMNkJbWlh/617rkDGEdSsDbu+qNHTaz9SKf7aC8fiIlUdD5RPpH6GEkP0cK7WlvmrEBRtWg=="], + + "@types/google-protobuf": ["@types/google-protobuf@3.15.12", "", {}, "sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ=="], + + "@types/node": ["@types/node@20.19.25", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ=="], + + "@types/react": ["@types/react@19.2.6", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w=="], + + "abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "adm-zip": ["adm-zip@0.5.16", "", {}, "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ=="], + + "agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "aproba": ["aproba@2.1.0", "", {}, "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew=="], + + "are-we-there-yet": ["are-we-there-yet@2.0.0", "", { "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" } }, "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "bun-types": ["bun-types@1.3.2", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-i/Gln4tbzKNuxP70OWhJRZz1MRfvqExowP7U6JKoI8cntFrtxg7RJK3jvz7wQW54UuvNC8tbKHHri5fy74FVqg=="], + + "chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "color-support": ["color-support@1.1.3", "", { "bin": { "color-support": "bin.js" } }, "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "console-control-strings": ["console-control-strings@1.1.0", "", {}, "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "delegates": ["delegates@1.0.0", "", {}, "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "gauge": ["gauge@3.0.2", "", { "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", "console-control-strings": "^1.0.0", "has-unicode": "^2.0.1", "object-assign": "^4.1.1", "signal-exit": "^3.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.2" } }, "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "google-protobuf": ["google-protobuf@4.0.0", "", {}, "sha512-b8wmenhUMf2WNL+xIJ/slvD/hEE6V3nRnG86O2bzkBrMweM9gnqZE1dfXlDjibY3aXJXDNbAHepevYyQ7qWKsQ=="], + + "grpc-health-check": ["grpc-health-check@2.1.0", "", { "dependencies": { "@grpc/proto-loader": "^0.7.13" } }, "sha512-HH3WjwNtusMTEQAtRelFgsFyNcOdihvpjusNDIrGYfWG8tPNSHqELrSyriIjm70k65YSxetsKG1y4H1L5gi1wQ=="], + + "grpc-tools": ["grpc-tools@1.13.0", "", { "dependencies": { "@mapbox/node-pre-gyp": "^1.0.5" }, "bin": { "grpc_tools_node_protoc": "bin/protoc.js", "grpc_tools_node_protoc_plugin": "bin/protoc_plugin.js" } }, "sha512-7CbkJ1yWPfX0nHjbYG58BQThNhbICXBZynzCUxCb3LzX5X9B3hQbRY2STiRgIEiLILlK9fgl0z0QVGwPCdXf5g=="], + + "grpc_tools_node_protoc_ts": ["grpc_tools_node_protoc_ts@5.3.3", "", { "dependencies": { "google-protobuf": "3.15.8", "handlebars": "4.7.7" }, "bin": { "protoc-gen-ts": "bin/protoc-gen-ts" } }, "sha512-M/YrklvVXMtuuj9kb42PxeouZhs7Ul+R4e/31XwrankUcKL8cQQP50Q9q+KEHGyHQaPt6VtKKsxMgLaKbCxeww=="], + + "handlebars": ["handlebars@4.7.7", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.0", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA=="], + + "has-unicode": ["has-unicode@2.0.1", "", {}, "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="], + + "https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + + "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "nopt": ["nopt@5.0.0", "", { "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ=="], + + "npmlog": ["npmlog@5.0.1", "", { "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", "gauge": "^3.0.0", "set-blocking": "^2.0.0" } }, "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="], + + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + + "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="], + + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + + "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "wide-align": ["wide-align@1.1.5", "", { "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg=="], + + "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], + + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "yargs": ["yargs@17.7.2", "", { "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" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "grpc-health-check/@grpc/proto-loader": ["@grpc/proto-loader@0.7.15", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ=="], + + "grpc_tools_node_protoc_ts/google-protobuf": ["google-protobuf@3.15.8", "", {}, "sha512-2jtfdqTaSxk0cuBJBtTTWsot4WtR9RVr2rXg7x7OoqiuOKopPrwXpM1G4dXIkLcUNRh3RKzz76C8IOkksZSeOw=="], + + "make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + } +} diff --git a/cosmo-router/plugins/courses/generated/mapping.json b/cosmo-router/plugins/courses/generated/mapping.json new file mode 100644 index 0000000..0d7a50f --- /dev/null +++ b/cosmo-router/plugins/courses/generated/mapping.json @@ -0,0 +1,217 @@ +{ + "version": 1, + "service": "CoursesService", + "operationMappings": [ + { + "type": "OPERATION_TYPE_QUERY", + "original": "courses", + "mapped": "QueryCourses", + "request": "QueryCoursesRequest", + "response": "QueryCoursesResponse" + }, + { + "type": "OPERATION_TYPE_QUERY", + "original": "course", + "mapped": "QueryCourse", + "request": "QueryCourseRequest", + "response": "QueryCourseResponse" + }, + { + "type": "OPERATION_TYPE_MUTATION", + "original": "createCourse", + "mapped": "MutationCreateCourse", + "request": "MutationCreateCourseRequest", + "response": "MutationCreateCourseResponse" + }, + { + "type": "OPERATION_TYPE_MUTATION", + "original": "enrollUser", + "mapped": "MutationEnrollUser", + "request": "MutationEnrollUserRequest", + "response": "MutationEnrollUserResponse" + } + ], + "entityMappings": [ + { + "typeName": "User", + "kind": "entity", + "key": "id", + "rpc": "LookupUserById", + "request": "LookupUserByIdRequest", + "response": "LookupUserByIdResponse" + } + ], + "typeFieldMappings": [ + { + "type": "Query", + "fieldMappings": [ + { + "original": "courses", + "mapped": "courses", + "argumentMappings": [] + }, + { + "original": "course", + "mapped": "course", + "argumentMappings": [ + { + "original": "id", + "mapped": "id" + } + ] + } + ] + }, + { + "type": "Mutation", + "fieldMappings": [ + { + "original": "createCourse", + "mapped": "create_course", + "argumentMappings": [ + { + "original": "input", + "mapped": "input" + } + ] + }, + { + "original": "enrollUser", + "mapped": "enroll_user", + "argumentMappings": [ + { + "original": "userId", + "mapped": "user_id" + }, + { + "original": "courseId", + "mapped": "course_id" + } + ] + } + ] + }, + { + "type": "User", + "fieldMappings": [ + { + "original": "id", + "mapped": "id", + "argumentMappings": [] + }, + { + "original": "instructorCourses", + "mapped": "instructor_courses", + "argumentMappings": [] + }, + { + "original": "enrollments", + "mapped": "enrollments", + "argumentMappings": [] + } + ] + }, + { + "type": "Course", + "fieldMappings": [ + { + "original": "id", + "mapped": "id", + "argumentMappings": [] + }, + { + "original": "title", + "mapped": "title", + "argumentMappings": [] + }, + { + "original": "description", + "mapped": "description", + "argumentMappings": [] + }, + { + "original": "instructor", + "mapped": "instructor", + "argumentMappings": [] + }, + { + "original": "durationHours", + "mapped": "duration_hours", + "argumentMappings": [] + }, + { + "original": "published", + "mapped": "published", + "argumentMappings": [] + }, + { + "original": "enrollments", + "mapped": "enrollments", + "argumentMappings": [] + } + ] + }, + { + "type": "Enrollment", + "fieldMappings": [ + { + "original": "id", + "mapped": "id", + "argumentMappings": [] + }, + { + "original": "user", + "mapped": "user", + "argumentMappings": [] + }, + { + "original": "course", + "mapped": "course", + "argumentMappings": [] + }, + { + "original": "progress", + "mapped": "progress", + "argumentMappings": [] + }, + { + "original": "enrolledAt", + "mapped": "enrolled_at", + "argumentMappings": [] + } + ] + }, + { + "type": "CourseInput", + "fieldMappings": [ + { + "original": "title", + "mapped": "title", + "argumentMappings": [] + }, + { + "original": "description", + "mapped": "description", + "argumentMappings": [] + }, + { + "original": "instructorId", + "mapped": "instructor_id", + "argumentMappings": [] + }, + { + "original": "durationHours", + "mapped": "duration_hours", + "argumentMappings": [] + }, + { + "original": "published", + "mapped": "published", + "argumentMappings": [] + } + ] + } + ], + "enumMappings": [], + "resolveMappings": [] +} \ No newline at end of file diff --git a/cosmo-router/plugins/courses/generated/service.pb.go b/cosmo-router/plugins/courses/generated/service.pb.go new file mode 100644 index 0000000..965e2ba --- /dev/null +++ b/cosmo-router/plugins/courses/generated/service.pb.go @@ -0,0 +1,1300 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc v5.29.3 +// source: generated/service.proto + +package plugin + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Key message for User entity lookup +type LookupUserByIdRequestKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Key field for User entity lookup. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *LookupUserByIdRequestKey) Reset() { + *x = LookupUserByIdRequestKey{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LookupUserByIdRequestKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LookupUserByIdRequestKey) ProtoMessage() {} + +func (x *LookupUserByIdRequestKey) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LookupUserByIdRequestKey.ProtoReflect.Descriptor instead. +func (*LookupUserByIdRequestKey) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{0} +} + +func (x *LookupUserByIdRequestKey) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +// Request message for User entity lookup. +type LookupUserByIdRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of keys to look up User entities. + // Order matters - each key maps to one entity in LookupUserByIdResponse. + Keys []*LookupUserByIdRequestKey `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys,omitempty"` +} + +func (x *LookupUserByIdRequest) Reset() { + *x = LookupUserByIdRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LookupUserByIdRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LookupUserByIdRequest) ProtoMessage() {} + +func (x *LookupUserByIdRequest) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LookupUserByIdRequest.ProtoReflect.Descriptor instead. +func (*LookupUserByIdRequest) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{1} +} + +func (x *LookupUserByIdRequest) GetKeys() []*LookupUserByIdRequestKey { + if x != nil { + return x.Keys + } + return nil +} + +// Response message for User entity lookup. +type LookupUserByIdResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of User entities in the same order as the keys in LookupUserByIdRequest. + // Always return the same number of entities as keys. Use null for entities that cannot be found. + // + // Example: + // + // LookupUserByIdRequest: + // keys: + // - id: 1 + // - id: 2 + // LookupUserByIdResponse: + // result: + // - id: 1 # User with id 1 found + // - null # User with id 2 not found + Result []*User `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"` +} + +func (x *LookupUserByIdResponse) Reset() { + *x = LookupUserByIdResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LookupUserByIdResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LookupUserByIdResponse) ProtoMessage() {} + +func (x *LookupUserByIdResponse) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LookupUserByIdResponse.ProtoReflect.Descriptor instead. +func (*LookupUserByIdResponse) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{2} +} + +func (x *LookupUserByIdResponse) GetResult() []*User { + if x != nil { + return x.Result + } + return nil +} + +// Request message for courses operation: Returns a list of all courses. +type QueryCoursesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *QueryCoursesRequest) Reset() { + *x = QueryCoursesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryCoursesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryCoursesRequest) ProtoMessage() {} + +func (x *QueryCoursesRequest) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryCoursesRequest.ProtoReflect.Descriptor instead. +func (*QueryCoursesRequest) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{3} +} + +// Response message for courses operation: Returns a list of all courses. +type QueryCoursesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Returns a list of all courses + Courses []*Course `protobuf:"bytes,1,rep,name=courses,proto3" json:"courses,omitempty"` +} + +func (x *QueryCoursesResponse) Reset() { + *x = QueryCoursesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryCoursesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryCoursesResponse) ProtoMessage() {} + +func (x *QueryCoursesResponse) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryCoursesResponse.ProtoReflect.Descriptor instead. +func (*QueryCoursesResponse) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{4} +} + +func (x *QueryCoursesResponse) GetCourses() []*Course { + if x != nil { + return x.Courses + } + return nil +} + +// Request message for course operation: Returns a single course by ID. +type QueryCourseRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *QueryCourseRequest) Reset() { + *x = QueryCourseRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryCourseRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryCourseRequest) ProtoMessage() {} + +func (x *QueryCourseRequest) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryCourseRequest.ProtoReflect.Descriptor instead. +func (*QueryCourseRequest) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{5} +} + +func (x *QueryCourseRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +// Response message for course operation: Returns a single course by ID. +type QueryCourseResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Returns a single course by ID + Course *Course `protobuf:"bytes,1,opt,name=course,proto3" json:"course,omitempty"` +} + +func (x *QueryCourseResponse) Reset() { + *x = QueryCourseResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryCourseResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryCourseResponse) ProtoMessage() {} + +func (x *QueryCourseResponse) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryCourseResponse.ProtoReflect.Descriptor instead. +func (*QueryCourseResponse) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{6} +} + +func (x *QueryCourseResponse) GetCourse() *Course { + if x != nil { + return x.Course + } + return nil +} + +// Request message for createCourse operation: Creates a new course. +type MutationCreateCourseRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Input *CourseInput `protobuf:"bytes,1,opt,name=input,proto3" json:"input,omitempty"` +} + +func (x *MutationCreateCourseRequest) Reset() { + *x = MutationCreateCourseRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MutationCreateCourseRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MutationCreateCourseRequest) ProtoMessage() {} + +func (x *MutationCreateCourseRequest) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MutationCreateCourseRequest.ProtoReflect.Descriptor instead. +func (*MutationCreateCourseRequest) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{7} +} + +func (x *MutationCreateCourseRequest) GetInput() *CourseInput { + if x != nil { + return x.Input + } + return nil +} + +// Response message for createCourse operation: Creates a new course. +type MutationCreateCourseResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Creates a new course + CreateCourse *Course `protobuf:"bytes,1,opt,name=create_course,json=createCourse,proto3" json:"create_course,omitempty"` +} + +func (x *MutationCreateCourseResponse) Reset() { + *x = MutationCreateCourseResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MutationCreateCourseResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MutationCreateCourseResponse) ProtoMessage() {} + +func (x *MutationCreateCourseResponse) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MutationCreateCourseResponse.ProtoReflect.Descriptor instead. +func (*MutationCreateCourseResponse) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{8} +} + +func (x *MutationCreateCourseResponse) GetCreateCourse() *Course { + if x != nil { + return x.CreateCourse + } + return nil +} + +// Request message for enrollUser operation: Enrolls a user in a course. +type MutationEnrollUserRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + CourseId string `protobuf:"bytes,2,opt,name=course_id,json=courseId,proto3" json:"course_id,omitempty"` +} + +func (x *MutationEnrollUserRequest) Reset() { + *x = MutationEnrollUserRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MutationEnrollUserRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MutationEnrollUserRequest) ProtoMessage() {} + +func (x *MutationEnrollUserRequest) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MutationEnrollUserRequest.ProtoReflect.Descriptor instead. +func (*MutationEnrollUserRequest) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{9} +} + +func (x *MutationEnrollUserRequest) GetUserId() string { + if x != nil { + return x.UserId + } + return "" +} + +func (x *MutationEnrollUserRequest) GetCourseId() string { + if x != nil { + return x.CourseId + } + return "" +} + +// Response message for enrollUser operation: Enrolls a user in a course. +type MutationEnrollUserResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Enrolls a user in a course + EnrollUser *Enrollment `protobuf:"bytes,1,opt,name=enroll_user,json=enrollUser,proto3" json:"enroll_user,omitempty"` +} + +func (x *MutationEnrollUserResponse) Reset() { + *x = MutationEnrollUserResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MutationEnrollUserResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MutationEnrollUserResponse) ProtoMessage() {} + +func (x *MutationEnrollUserResponse) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MutationEnrollUserResponse.ProtoReflect.Descriptor instead. +func (*MutationEnrollUserResponse) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{10} +} + +func (x *MutationEnrollUserResponse) GetEnrollUser() *Enrollment { + if x != nil { + return x.EnrollUser + } + return nil +} + +// User type from users plugin (extended here) +type User struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Courses where this user is the instructor + InstructorCourses []*Course `protobuf:"bytes,2,rep,name=instructor_courses,json=instructorCourses,proto3" json:"instructor_courses,omitempty"` + // User's course enrollments + Enrollments []*Enrollment `protobuf:"bytes,3,rep,name=enrollments,proto3" json:"enrollments,omitempty"` +} + +func (x *User) Reset() { + *x = User{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *User) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*User) ProtoMessage() {} + +func (x *User) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use User.ProtoReflect.Descriptor instead. +func (*User) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{11} +} + +func (x *User) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *User) GetInstructorCourses() []*Course { + if x != nil { + return x.InstructorCourses + } + return nil +} + +func (x *User) GetEnrollments() []*Enrollment { + if x != nil { + return x.Enrollments + } + return nil +} + +// Represents a course in the system +type Course struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The unique identifier for the course + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // The course title + Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` + // Course description + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + // Course instructor (User from users plugin) + Instructor *User `protobuf:"bytes,4,opt,name=instructor,proto3" json:"instructor,omitempty"` + // Course duration in hours + DurationHours int32 `protobuf:"varint,5,opt,name=duration_hours,json=durationHours,proto3" json:"duration_hours,omitempty"` + // Whether the course is published + Published bool `protobuf:"varint,6,opt,name=published,proto3" json:"published,omitempty"` + // Students enrolled in this course + Enrollments []*Enrollment `protobuf:"bytes,7,rep,name=enrollments,proto3" json:"enrollments,omitempty"` +} + +func (x *Course) Reset() { + *x = Course{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Course) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Course) ProtoMessage() {} + +func (x *Course) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Course.ProtoReflect.Descriptor instead. +func (*Course) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{12} +} + +func (x *Course) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Course) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *Course) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Course) GetInstructor() *User { + if x != nil { + return x.Instructor + } + return nil +} + +func (x *Course) GetDurationHours() int32 { + if x != nil { + return x.DurationHours + } + return 0 +} + +func (x *Course) GetPublished() bool { + if x != nil { + return x.Published + } + return false +} + +func (x *Course) GetEnrollments() []*Enrollment { + if x != nil { + return x.Enrollments + } + return nil +} + +// Input for creating a course +type CourseInput struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + InstructorId string `protobuf:"bytes,3,opt,name=instructor_id,json=instructorId,proto3" json:"instructor_id,omitempty"` + DurationHours int32 `protobuf:"varint,4,opt,name=duration_hours,json=durationHours,proto3" json:"duration_hours,omitempty"` + Published bool `protobuf:"varint,5,opt,name=published,proto3" json:"published,omitempty"` +} + +func (x *CourseInput) Reset() { + *x = CourseInput{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CourseInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CourseInput) ProtoMessage() {} + +func (x *CourseInput) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CourseInput.ProtoReflect.Descriptor instead. +func (*CourseInput) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{13} +} + +func (x *CourseInput) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *CourseInput) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *CourseInput) GetInstructorId() string { + if x != nil { + return x.InstructorId + } + return "" +} + +func (x *CourseInput) GetDurationHours() int32 { + if x != nil { + return x.DurationHours + } + return 0 +} + +func (x *CourseInput) GetPublished() bool { + if x != nil { + return x.Published + } + return false +} + +// Represents a user's enrollment in a course +type Enrollment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The unique identifier for the enrollment + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // The enrolled user (User from users plugin) + User *User `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` + // The course + Course *Course `protobuf:"bytes,3,opt,name=course,proto3" json:"course,omitempty"` + // Completion percentage (0-100) + Progress int32 `protobuf:"varint,4,opt,name=progress,proto3" json:"progress,omitempty"` + // When the user enrolled + EnrolledAt string `protobuf:"bytes,5,opt,name=enrolled_at,json=enrolledAt,proto3" json:"enrolled_at,omitempty"` +} + +func (x *Enrollment) Reset() { + *x = Enrollment{} + if protoimpl.UnsafeEnabled { + mi := &file_generated_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Enrollment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Enrollment) ProtoMessage() {} + +func (x *Enrollment) ProtoReflect() protoreflect.Message { + mi := &file_generated_service_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Enrollment.ProtoReflect.Descriptor instead. +func (*Enrollment) Descriptor() ([]byte, []int) { + return file_generated_service_proto_rawDescGZIP(), []int{14} +} + +func (x *Enrollment) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Enrollment) GetUser() *User { + if x != nil { + return x.User + } + return nil +} + +func (x *Enrollment) GetCourse() *Course { + if x != nil { + return x.Course + } + return nil +} + +func (x *Enrollment) GetProgress() int32 { + if x != nil { + return x.Progress + } + return 0 +} + +func (x *Enrollment) GetEnrolledAt() string { + if x != nil { + return x.EnrolledAt + } + return "" +} + +var File_generated_service_proto protoreflect.FileDescriptor + +var file_generated_service_proto_rawDesc = []byte{ + 0x0a, 0x17, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x22, 0x2a, 0x0a, 0x18, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x55, 0x73, 0x65, 0x72, + 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4e, + 0x0a, 0x15, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x55, 0x73, 0x65, 0x72, 0x42, 0x79, 0x49, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x55, 0x73, 0x65, 0x72, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3f, + 0x0a, 0x16, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x55, 0x73, 0x65, 0x72, 0x42, 0x79, 0x49, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, + 0x15, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x41, 0x0a, 0x14, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, + 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, + 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, + 0x52, 0x07, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, 0x22, 0x24, 0x0a, 0x12, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, + 0x3e, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x22, + 0x49, 0x0a, 0x1b, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, + 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x54, 0x0a, 0x1c, 0x4d, 0x75, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x72, + 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0d, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x75, 0x72, + 0x73, 0x65, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, + 0x22, 0x51, 0x0a, 0x19, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, + 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x72, 0x73, + 0x65, 0x49, 0x64, 0x22, 0x52, 0x0a, 0x1a, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x34, 0x0a, 0x0b, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0a, 0x65, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x22, 0x8d, 0x01, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x3e, 0x0a, 0x12, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, + 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x52, 0x11, 0x69, + 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, + 0x12, 0x35, 0x0a, 0x0b, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xfb, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x72, + 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x0a, 0x69, 0x6e, + 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x0a, 0x69, + 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6f, 0x75, 0x72, 0x73, + 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x35, + 0x0a, 0x0b, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xaf, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, + 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72, + 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, + 0x6f, 0x75, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x64, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6f, 0x75, 0x72, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x22, 0xa5, 0x01, 0x0a, 0x0a, 0x45, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x06, 0x63, 0x6f, 0x75, + 0x72, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x72, + 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, + 0x0a, 0x0b, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x32, + 0xc8, 0x03, 0x0a, 0x0e, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x53, 0x0a, 0x0e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x55, 0x73, 0x65, 0x72, + 0x42, 0x79, 0x49, 0x64, 0x12, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, + 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x55, 0x73, 0x65, 0x72, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, + 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x55, 0x73, 0x65, 0x72, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x14, 0x4d, 0x75, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x12, + 0x24, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, + 0x75, 0x72, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5f, + 0x0a, 0x12, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, + 0x55, 0x73, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, + 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, + 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x4a, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x12, 0x1b, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, + 0x75, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x72, 0x73, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0c, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x72, 0x73, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x25, 0x5a, 0x23, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_generated_service_proto_rawDescOnce sync.Once + file_generated_service_proto_rawDescData = file_generated_service_proto_rawDesc +) + +func file_generated_service_proto_rawDescGZIP() []byte { + file_generated_service_proto_rawDescOnce.Do(func() { + file_generated_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_generated_service_proto_rawDescData) + }) + return file_generated_service_proto_rawDescData +} + +var file_generated_service_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_generated_service_proto_goTypes = []any{ + (*LookupUserByIdRequestKey)(nil), // 0: service.LookupUserByIdRequestKey + (*LookupUserByIdRequest)(nil), // 1: service.LookupUserByIdRequest + (*LookupUserByIdResponse)(nil), // 2: service.LookupUserByIdResponse + (*QueryCoursesRequest)(nil), // 3: service.QueryCoursesRequest + (*QueryCoursesResponse)(nil), // 4: service.QueryCoursesResponse + (*QueryCourseRequest)(nil), // 5: service.QueryCourseRequest + (*QueryCourseResponse)(nil), // 6: service.QueryCourseResponse + (*MutationCreateCourseRequest)(nil), // 7: service.MutationCreateCourseRequest + (*MutationCreateCourseResponse)(nil), // 8: service.MutationCreateCourseResponse + (*MutationEnrollUserRequest)(nil), // 9: service.MutationEnrollUserRequest + (*MutationEnrollUserResponse)(nil), // 10: service.MutationEnrollUserResponse + (*User)(nil), // 11: service.User + (*Course)(nil), // 12: service.Course + (*CourseInput)(nil), // 13: service.CourseInput + (*Enrollment)(nil), // 14: service.Enrollment +} +var file_generated_service_proto_depIdxs = []int32{ + 0, // 0: service.LookupUserByIdRequest.keys:type_name -> service.LookupUserByIdRequestKey + 11, // 1: service.LookupUserByIdResponse.result:type_name -> service.User + 12, // 2: service.QueryCoursesResponse.courses:type_name -> service.Course + 12, // 3: service.QueryCourseResponse.course:type_name -> service.Course + 13, // 4: service.MutationCreateCourseRequest.input:type_name -> service.CourseInput + 12, // 5: service.MutationCreateCourseResponse.create_course:type_name -> service.Course + 14, // 6: service.MutationEnrollUserResponse.enroll_user:type_name -> service.Enrollment + 12, // 7: service.User.instructor_courses:type_name -> service.Course + 14, // 8: service.User.enrollments:type_name -> service.Enrollment + 11, // 9: service.Course.instructor:type_name -> service.User + 14, // 10: service.Course.enrollments:type_name -> service.Enrollment + 11, // 11: service.Enrollment.user:type_name -> service.User + 12, // 12: service.Enrollment.course:type_name -> service.Course + 1, // 13: service.CoursesService.LookupUserById:input_type -> service.LookupUserByIdRequest + 7, // 14: service.CoursesService.MutationCreateCourse:input_type -> service.MutationCreateCourseRequest + 9, // 15: service.CoursesService.MutationEnrollUser:input_type -> service.MutationEnrollUserRequest + 5, // 16: service.CoursesService.QueryCourse:input_type -> service.QueryCourseRequest + 3, // 17: service.CoursesService.QueryCourses:input_type -> service.QueryCoursesRequest + 2, // 18: service.CoursesService.LookupUserById:output_type -> service.LookupUserByIdResponse + 8, // 19: service.CoursesService.MutationCreateCourse:output_type -> service.MutationCreateCourseResponse + 10, // 20: service.CoursesService.MutationEnrollUser:output_type -> service.MutationEnrollUserResponse + 6, // 21: service.CoursesService.QueryCourse:output_type -> service.QueryCourseResponse + 4, // 22: service.CoursesService.QueryCourses:output_type -> service.QueryCoursesResponse + 18, // [18:23] is the sub-list for method output_type + 13, // [13:18] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name +} + +func init() { file_generated_service_proto_init() } +func file_generated_service_proto_init() { + if File_generated_service_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_generated_service_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*LookupUserByIdRequestKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*LookupUserByIdRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*LookupUserByIdResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*QueryCoursesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*QueryCoursesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[5].Exporter = func(v any, i int) any { + switch v := v.(*QueryCourseRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[6].Exporter = func(v any, i int) any { + switch v := v.(*QueryCourseResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[7].Exporter = func(v any, i int) any { + switch v := v.(*MutationCreateCourseRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[8].Exporter = func(v any, i int) any { + switch v := v.(*MutationCreateCourseResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[9].Exporter = func(v any, i int) any { + switch v := v.(*MutationEnrollUserRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[10].Exporter = func(v any, i int) any { + switch v := v.(*MutationEnrollUserResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[11].Exporter = func(v any, i int) any { + switch v := v.(*User); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[12].Exporter = func(v any, i int) any { + switch v := v.(*Course); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[13].Exporter = func(v any, i int) any { + switch v := v.(*CourseInput); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_generated_service_proto_msgTypes[14].Exporter = func(v any, i int) any { + switch v := v.(*Enrollment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_generated_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 15, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_generated_service_proto_goTypes, + DependencyIndexes: file_generated_service_proto_depIdxs, + MessageInfos: file_generated_service_proto_msgTypes, + }.Build() + File_generated_service_proto = out.File + file_generated_service_proto_rawDesc = nil + file_generated_service_proto_goTypes = nil + file_generated_service_proto_depIdxs = nil +} diff --git a/cosmo-router/plugins/courses/generated/service.proto b/cosmo-router/plugins/courses/generated/service.proto new file mode 100644 index 0000000..2d708c6 --- /dev/null +++ b/cosmo-router/plugins/courses/generated/service.proto @@ -0,0 +1,137 @@ +syntax = "proto3"; +package service; + +// Service definition for CoursesService +service CoursesService { + // Lookup User entity by id: User type from users plugin (extended here) + rpc LookupUserById(LookupUserByIdRequest) returns (LookupUserByIdResponse) {} + // Creates a new course + rpc MutationCreateCourse(MutationCreateCourseRequest) returns (MutationCreateCourseResponse) {} + // Enrolls a user in a course + rpc MutationEnrollUser(MutationEnrollUserRequest) returns (MutationEnrollUserResponse) {} + // Returns a single course by ID + rpc QueryCourse(QueryCourseRequest) returns (QueryCourseResponse) {} + // Returns a list of all courses + rpc QueryCourses(QueryCoursesRequest) returns (QueryCoursesResponse) {} +} + +// Key message for User entity lookup +message LookupUserByIdRequestKey { + // Key field for User entity lookup. + string id = 1; +} + +// Request message for User entity lookup. +message LookupUserByIdRequest { + /* + * List of keys to look up User entities. + * Order matters - each key maps to one entity in LookupUserByIdResponse. + */ + repeated LookupUserByIdRequestKey keys = 1; +} + +// Response message for User entity lookup. +message LookupUserByIdResponse { + /* + * List of User entities in the same order as the keys in LookupUserByIdRequest. + * Always return the same number of entities as keys. Use null for entities that cannot be found. + * + * Example: + * LookupUserByIdRequest: + * keys: + * - id: 1 + * - id: 2 + * LookupUserByIdResponse: + * result: + * - id: 1 # User with id 1 found + * - null # User with id 2 not found + */ + repeated User result = 1; +} + +// Request message for courses operation: Returns a list of all courses. +message QueryCoursesRequest { +} +// Response message for courses operation: Returns a list of all courses. +message QueryCoursesResponse { + // Returns a list of all courses + repeated Course courses = 1; +} +// Request message for course operation: Returns a single course by ID. +message QueryCourseRequest { + string id = 1; +} +// Response message for course operation: Returns a single course by ID. +message QueryCourseResponse { + // Returns a single course by ID + Course course = 1; +} +// Request message for createCourse operation: Creates a new course. +message MutationCreateCourseRequest { + CourseInput input = 1; +} +// Response message for createCourse operation: Creates a new course. +message MutationCreateCourseResponse { + // Creates a new course + Course create_course = 1; +} +// Request message for enrollUser operation: Enrolls a user in a course. +message MutationEnrollUserRequest { + string user_id = 1; + string course_id = 2; +} +// Response message for enrollUser operation: Enrolls a user in a course. +message MutationEnrollUserResponse { + // Enrolls a user in a course + Enrollment enroll_user = 1; +} + +// User type from users plugin (extended here) +message User { + string id = 1; + // Courses where this user is the instructor + repeated Course instructor_courses = 2; + // User's course enrollments + repeated Enrollment enrollments = 3; +} + +// Represents a course in the system +message Course { + // The unique identifier for the course + string id = 1; + // The course title + string title = 2; + // Course description + string description = 3; + // Course instructor (User from users plugin) + User instructor = 4; + // Course duration in hours + int32 duration_hours = 5; + // Whether the course is published + bool published = 6; + // Students enrolled in this course + repeated Enrollment enrollments = 7; +} + +// Input for creating a course +message CourseInput { + string title = 1; + string description = 2; + string instructor_id = 3; + int32 duration_hours = 4; + bool published = 5; +} + +// Represents a user's enrollment in a course +message Enrollment { + // The unique identifier for the enrollment + string id = 1; + // The enrolled user (User from users plugin) + User user = 2; + // The course + Course course = 3; + // Completion percentage (0-100) + int32 progress = 4; + // When the user enrolled + string enrolled_at = 5; +} \ No newline at end of file diff --git a/cosmo-router/plugins/courses/generated/service.proto.lock.json b/cosmo-router/plugins/courses/generated/service.proto.lock.json new file mode 100644 index 0000000..8abdb06 --- /dev/null +++ b/cosmo-router/plugins/courses/generated/service.proto.lock.json @@ -0,0 +1,148 @@ +{ + "version": "1.0.0", + "messages": { + "Query": { + "fields": { + "courses": 2, + "course": 3 + }, + "reservedNumbers": [ + 1 + ] + }, + "QueryHelloRequest": { + "fields": { + "name": 1 + } + }, + "QueryHello": { + "fields": { + "name": 1 + } + }, + "QueryHelloResponse": { + "fields": { + "hello": 1 + } + }, + "World": { + "fields": { + "id": 1, + "name": 2 + } + }, + "LookupUserByIdRequestKey": { + "fields": { + "id": 1 + } + }, + "LookupUserByIdRequest": { + "fields": { + "keys": 1 + } + }, + "LookupUserByIdResponse": { + "fields": { + "result": 1 + } + }, + "QueryCoursesRequest": { + "fields": {} + }, + "QueryCoursesResponse": { + "fields": { + "courses": 1 + } + }, + "QueryCourseRequest": { + "fields": { + "id": 1 + } + }, + "QueryCourse": { + "fields": { + "id": 1 + } + }, + "QueryCourseResponse": { + "fields": { + "course": 1 + } + }, + "Mutation": { + "fields": { + "createCourse": 1, + "enrollUser": 2 + } + }, + "MutationCreateCourseRequest": { + "fields": { + "input": 1 + } + }, + "MutationCreateCourse": { + "fields": { + "input": 1 + } + }, + "MutationCreateCourseResponse": { + "fields": { + "create_course": 1 + } + }, + "MutationEnrollUserRequest": { + "fields": { + "user_id": 1, + "course_id": 2 + } + }, + "MutationEnrollUser": { + "fields": { + "userId": 1, + "courseId": 2 + } + }, + "MutationEnrollUserResponse": { + "fields": { + "enroll_user": 1 + } + }, + "User": { + "fields": { + "id": 1, + "instructorCourses": 2, + "enrollments": 3 + } + }, + "Course": { + "fields": { + "id": 1, + "title": 2, + "description": 3, + "instructor": 4, + "durationHours": 5, + "published": 6, + "enrollments": 7 + } + }, + "CourseInput": { + "fields": { + "title": 1, + "description": 2, + "instructorId": 3, + "durationHours": 4, + "published": 5 + } + }, + "Enrollment": { + "fields": { + "id": 1, + "user": 2, + "course": 3, + "progress": 4, + "enrolledAt": 5 + } + } + }, + "enums": {} +} \ No newline at end of file diff --git a/cosmo-router/plugins/courses/generated/service_grpc.pb.go b/cosmo-router/plugins/courses/generated/service_grpc.pb.go new file mode 100644 index 0000000..f300faa --- /dev/null +++ b/cosmo-router/plugins/courses/generated/service_grpc.pb.go @@ -0,0 +1,287 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.29.3 +// source: generated/service.proto + +package plugin + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + CoursesService_LookupUserById_FullMethodName = "/service.CoursesService/LookupUserById" + CoursesService_MutationCreateCourse_FullMethodName = "/service.CoursesService/MutationCreateCourse" + CoursesService_MutationEnrollUser_FullMethodName = "/service.CoursesService/MutationEnrollUser" + CoursesService_QueryCourse_FullMethodName = "/service.CoursesService/QueryCourse" + CoursesService_QueryCourses_FullMethodName = "/service.CoursesService/QueryCourses" +) + +// CoursesServiceClient is the client API for CoursesService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// Service definition for CoursesService +type CoursesServiceClient interface { + // Lookup User entity by id: User type from users plugin (extended here) + LookupUserById(ctx context.Context, in *LookupUserByIdRequest, opts ...grpc.CallOption) (*LookupUserByIdResponse, error) + // Creates a new course + MutationCreateCourse(ctx context.Context, in *MutationCreateCourseRequest, opts ...grpc.CallOption) (*MutationCreateCourseResponse, error) + // Enrolls a user in a course + MutationEnrollUser(ctx context.Context, in *MutationEnrollUserRequest, opts ...grpc.CallOption) (*MutationEnrollUserResponse, error) + // Returns a single course by ID + QueryCourse(ctx context.Context, in *QueryCourseRequest, opts ...grpc.CallOption) (*QueryCourseResponse, error) + // Returns a list of all courses + QueryCourses(ctx context.Context, in *QueryCoursesRequest, opts ...grpc.CallOption) (*QueryCoursesResponse, error) +} + +type coursesServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewCoursesServiceClient(cc grpc.ClientConnInterface) CoursesServiceClient { + return &coursesServiceClient{cc} +} + +func (c *coursesServiceClient) LookupUserById(ctx context.Context, in *LookupUserByIdRequest, opts ...grpc.CallOption) (*LookupUserByIdResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(LookupUserByIdResponse) + err := c.cc.Invoke(ctx, CoursesService_LookupUserById_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *coursesServiceClient) MutationCreateCourse(ctx context.Context, in *MutationCreateCourseRequest, opts ...grpc.CallOption) (*MutationCreateCourseResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MutationCreateCourseResponse) + err := c.cc.Invoke(ctx, CoursesService_MutationCreateCourse_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *coursesServiceClient) MutationEnrollUser(ctx context.Context, in *MutationEnrollUserRequest, opts ...grpc.CallOption) (*MutationEnrollUserResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MutationEnrollUserResponse) + err := c.cc.Invoke(ctx, CoursesService_MutationEnrollUser_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *coursesServiceClient) QueryCourse(ctx context.Context, in *QueryCourseRequest, opts ...grpc.CallOption) (*QueryCourseResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(QueryCourseResponse) + err := c.cc.Invoke(ctx, CoursesService_QueryCourse_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *coursesServiceClient) QueryCourses(ctx context.Context, in *QueryCoursesRequest, opts ...grpc.CallOption) (*QueryCoursesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(QueryCoursesResponse) + err := c.cc.Invoke(ctx, CoursesService_QueryCourses_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CoursesServiceServer is the server API for CoursesService service. +// All implementations must embed UnimplementedCoursesServiceServer +// for forward compatibility. +// +// Service definition for CoursesService +type CoursesServiceServer interface { + // Lookup User entity by id: User type from users plugin (extended here) + LookupUserById(context.Context, *LookupUserByIdRequest) (*LookupUserByIdResponse, error) + // Creates a new course + MutationCreateCourse(context.Context, *MutationCreateCourseRequest) (*MutationCreateCourseResponse, error) + // Enrolls a user in a course + MutationEnrollUser(context.Context, *MutationEnrollUserRequest) (*MutationEnrollUserResponse, error) + // Returns a single course by ID + QueryCourse(context.Context, *QueryCourseRequest) (*QueryCourseResponse, error) + // Returns a list of all courses + QueryCourses(context.Context, *QueryCoursesRequest) (*QueryCoursesResponse, error) + mustEmbedUnimplementedCoursesServiceServer() +} + +// UnimplementedCoursesServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedCoursesServiceServer struct{} + +func (UnimplementedCoursesServiceServer) LookupUserById(context.Context, *LookupUserByIdRequest) (*LookupUserByIdResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method LookupUserById not implemented") +} +func (UnimplementedCoursesServiceServer) MutationCreateCourse(context.Context, *MutationCreateCourseRequest) (*MutationCreateCourseResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MutationCreateCourse not implemented") +} +func (UnimplementedCoursesServiceServer) MutationEnrollUser(context.Context, *MutationEnrollUserRequest) (*MutationEnrollUserResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method MutationEnrollUser not implemented") +} +func (UnimplementedCoursesServiceServer) QueryCourse(context.Context, *QueryCourseRequest) (*QueryCourseResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryCourse not implemented") +} +func (UnimplementedCoursesServiceServer) QueryCourses(context.Context, *QueryCoursesRequest) (*QueryCoursesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryCourses not implemented") +} +func (UnimplementedCoursesServiceServer) mustEmbedUnimplementedCoursesServiceServer() {} +func (UnimplementedCoursesServiceServer) testEmbeddedByValue() {} + +// UnsafeCoursesServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CoursesServiceServer will +// result in compilation errors. +type UnsafeCoursesServiceServer interface { + mustEmbedUnimplementedCoursesServiceServer() +} + +func RegisterCoursesServiceServer(s grpc.ServiceRegistrar, srv CoursesServiceServer) { + // If the following call pancis, it indicates UnimplementedCoursesServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&CoursesService_ServiceDesc, srv) +} + +func _CoursesService_LookupUserById_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(LookupUserByIdRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoursesServiceServer).LookupUserById(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CoursesService_LookupUserById_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoursesServiceServer).LookupUserById(ctx, req.(*LookupUserByIdRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CoursesService_MutationCreateCourse_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MutationCreateCourseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoursesServiceServer).MutationCreateCourse(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CoursesService_MutationCreateCourse_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoursesServiceServer).MutationCreateCourse(ctx, req.(*MutationCreateCourseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CoursesService_MutationEnrollUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MutationEnrollUserRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoursesServiceServer).MutationEnrollUser(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CoursesService_MutationEnrollUser_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoursesServiceServer).MutationEnrollUser(ctx, req.(*MutationEnrollUserRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CoursesService_QueryCourse_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryCourseRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoursesServiceServer).QueryCourse(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CoursesService_QueryCourse_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoursesServiceServer).QueryCourse(ctx, req.(*QueryCourseRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CoursesService_QueryCourses_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryCoursesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CoursesServiceServer).QueryCourses(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CoursesService_QueryCourses_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CoursesServiceServer).QueryCourses(ctx, req.(*QueryCoursesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// CoursesService_ServiceDesc is the grpc.ServiceDesc for CoursesService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var CoursesService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "service.CoursesService", + HandlerType: (*CoursesServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "LookupUserById", + Handler: _CoursesService_LookupUserById_Handler, + }, + { + MethodName: "MutationCreateCourse", + Handler: _CoursesService_MutationCreateCourse_Handler, + }, + { + MethodName: "MutationEnrollUser", + Handler: _CoursesService_MutationEnrollUser_Handler, + }, + { + MethodName: "QueryCourse", + Handler: _CoursesService_QueryCourse_Handler, + }, + { + MethodName: "QueryCourses", + Handler: _CoursesService_QueryCourses_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "generated/service.proto", +} diff --git a/cosmo-router/plugins/courses/generated/service_grpc_pb.d.ts b/cosmo-router/plugins/courses/generated/service_grpc_pb.d.ts new file mode 100644 index 0000000..f36a6c0 --- /dev/null +++ b/cosmo-router/plugins/courses/generated/service_grpc_pb.d.ts @@ -0,0 +1,109 @@ +// package: service +// file: service.proto + +/* tslint:disable */ +/* eslint-disable */ + +import * as grpc from "@grpc/grpc-js"; +import * as service_pb from "./service_pb"; + +interface ICoursesServiceService extends grpc.ServiceDefinition { + lookupUserById: ICoursesServiceService_ILookupUserById; + mutationCreateCourse: ICoursesServiceService_IMutationCreateCourse; + mutationEnrollUser: ICoursesServiceService_IMutationEnrollUser; + queryCourse: ICoursesServiceService_IQueryCourse; + queryCourses: ICoursesServiceService_IQueryCourses; +} + +interface ICoursesServiceService_ILookupUserById extends grpc.MethodDefinition { + path: "/service.CoursesService/LookupUserById"; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} +interface ICoursesServiceService_IMutationCreateCourse extends grpc.MethodDefinition { + path: "/service.CoursesService/MutationCreateCourse"; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} +interface ICoursesServiceService_IMutationEnrollUser extends grpc.MethodDefinition { + path: "/service.CoursesService/MutationEnrollUser"; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} +interface ICoursesServiceService_IQueryCourse extends grpc.MethodDefinition { + path: "/service.CoursesService/QueryCourse"; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} +interface ICoursesServiceService_IQueryCourses extends grpc.MethodDefinition { + path: "/service.CoursesService/QueryCourses"; + requestStream: false; + responseStream: false; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} + +export const CoursesServiceService: ICoursesServiceService; + +export interface ICoursesServiceServer extends grpc.UntypedServiceImplementation { + lookupUserById: grpc.handleUnaryCall; + mutationCreateCourse: grpc.handleUnaryCall; + mutationEnrollUser: grpc.handleUnaryCall; + queryCourse: grpc.handleUnaryCall; + queryCourses: grpc.handleUnaryCall; +} + +export interface ICoursesServiceClient { + lookupUserById(request: service_pb.LookupUserByIdRequest, callback: (error: grpc.ServiceError | null, response: service_pb.LookupUserByIdResponse) => void): grpc.ClientUnaryCall; + lookupUserById(request: service_pb.LookupUserByIdRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.LookupUserByIdResponse) => void): grpc.ClientUnaryCall; + lookupUserById(request: service_pb.LookupUserByIdRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.LookupUserByIdResponse) => void): grpc.ClientUnaryCall; + mutationCreateCourse(request: service_pb.MutationCreateCourseRequest, callback: (error: grpc.ServiceError | null, response: service_pb.MutationCreateCourseResponse) => void): grpc.ClientUnaryCall; + mutationCreateCourse(request: service_pb.MutationCreateCourseRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.MutationCreateCourseResponse) => void): grpc.ClientUnaryCall; + mutationCreateCourse(request: service_pb.MutationCreateCourseRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.MutationCreateCourseResponse) => void): grpc.ClientUnaryCall; + mutationEnrollUser(request: service_pb.MutationEnrollUserRequest, callback: (error: grpc.ServiceError | null, response: service_pb.MutationEnrollUserResponse) => void): grpc.ClientUnaryCall; + mutationEnrollUser(request: service_pb.MutationEnrollUserRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.MutationEnrollUserResponse) => void): grpc.ClientUnaryCall; + mutationEnrollUser(request: service_pb.MutationEnrollUserRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.MutationEnrollUserResponse) => void): grpc.ClientUnaryCall; + queryCourse(request: service_pb.QueryCourseRequest, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCourseResponse) => void): grpc.ClientUnaryCall; + queryCourse(request: service_pb.QueryCourseRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCourseResponse) => void): grpc.ClientUnaryCall; + queryCourse(request: service_pb.QueryCourseRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCourseResponse) => void): grpc.ClientUnaryCall; + queryCourses(request: service_pb.QueryCoursesRequest, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCoursesResponse) => void): grpc.ClientUnaryCall; + queryCourses(request: service_pb.QueryCoursesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCoursesResponse) => void): grpc.ClientUnaryCall; + queryCourses(request: service_pb.QueryCoursesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCoursesResponse) => void): grpc.ClientUnaryCall; +} + +export class CoursesServiceClient extends grpc.Client implements ICoursesServiceClient { + constructor(address: string, credentials: grpc.ChannelCredentials, options?: Partial); + public lookupUserById(request: service_pb.LookupUserByIdRequest, callback: (error: grpc.ServiceError | null, response: service_pb.LookupUserByIdResponse) => void): grpc.ClientUnaryCall; + public lookupUserById(request: service_pb.LookupUserByIdRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.LookupUserByIdResponse) => void): grpc.ClientUnaryCall; + public lookupUserById(request: service_pb.LookupUserByIdRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.LookupUserByIdResponse) => void): grpc.ClientUnaryCall; + public mutationCreateCourse(request: service_pb.MutationCreateCourseRequest, callback: (error: grpc.ServiceError | null, response: service_pb.MutationCreateCourseResponse) => void): grpc.ClientUnaryCall; + public mutationCreateCourse(request: service_pb.MutationCreateCourseRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.MutationCreateCourseResponse) => void): grpc.ClientUnaryCall; + public mutationCreateCourse(request: service_pb.MutationCreateCourseRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.MutationCreateCourseResponse) => void): grpc.ClientUnaryCall; + public mutationEnrollUser(request: service_pb.MutationEnrollUserRequest, callback: (error: grpc.ServiceError | null, response: service_pb.MutationEnrollUserResponse) => void): grpc.ClientUnaryCall; + public mutationEnrollUser(request: service_pb.MutationEnrollUserRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.MutationEnrollUserResponse) => void): grpc.ClientUnaryCall; + public mutationEnrollUser(request: service_pb.MutationEnrollUserRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.MutationEnrollUserResponse) => void): grpc.ClientUnaryCall; + public queryCourse(request: service_pb.QueryCourseRequest, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCourseResponse) => void): grpc.ClientUnaryCall; + public queryCourse(request: service_pb.QueryCourseRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCourseResponse) => void): grpc.ClientUnaryCall; + public queryCourse(request: service_pb.QueryCourseRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCourseResponse) => void): grpc.ClientUnaryCall; + public queryCourses(request: service_pb.QueryCoursesRequest, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCoursesResponse) => void): grpc.ClientUnaryCall; + public queryCourses(request: service_pb.QueryCoursesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCoursesResponse) => void): grpc.ClientUnaryCall; + public queryCourses(request: service_pb.QueryCoursesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: service_pb.QueryCoursesResponse) => void): grpc.ClientUnaryCall; +} diff --git a/cosmo-router/plugins/courses/generated/service_grpc_pb.js b/cosmo-router/plugins/courses/generated/service_grpc_pb.js new file mode 100644 index 0000000..c188a90 --- /dev/null +++ b/cosmo-router/plugins/courses/generated/service_grpc_pb.js @@ -0,0 +1,182 @@ +// GENERATED CODE -- DO NOT EDIT! + +'use strict'; +var grpc = require('@grpc/grpc-js'); +var service_pb = require('./service_pb.js'); + +function serialize_service_LookupUserByIdRequest(arg) { + if (!(arg instanceof service_pb.LookupUserByIdRequest)) { + throw new Error('Expected argument of type service.LookupUserByIdRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_LookupUserByIdRequest(buffer_arg) { + return service_pb.LookupUserByIdRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_LookupUserByIdResponse(arg) { + if (!(arg instanceof service_pb.LookupUserByIdResponse)) { + throw new Error('Expected argument of type service.LookupUserByIdResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_LookupUserByIdResponse(buffer_arg) { + return service_pb.LookupUserByIdResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_MutationCreateCourseRequest(arg) { + if (!(arg instanceof service_pb.MutationCreateCourseRequest)) { + throw new Error('Expected argument of type service.MutationCreateCourseRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_MutationCreateCourseRequest(buffer_arg) { + return service_pb.MutationCreateCourseRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_MutationCreateCourseResponse(arg) { + if (!(arg instanceof service_pb.MutationCreateCourseResponse)) { + throw new Error('Expected argument of type service.MutationCreateCourseResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_MutationCreateCourseResponse(buffer_arg) { + return service_pb.MutationCreateCourseResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_MutationEnrollUserRequest(arg) { + if (!(arg instanceof service_pb.MutationEnrollUserRequest)) { + throw new Error('Expected argument of type service.MutationEnrollUserRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_MutationEnrollUserRequest(buffer_arg) { + return service_pb.MutationEnrollUserRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_MutationEnrollUserResponse(arg) { + if (!(arg instanceof service_pb.MutationEnrollUserResponse)) { + throw new Error('Expected argument of type service.MutationEnrollUserResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_MutationEnrollUserResponse(buffer_arg) { + return service_pb.MutationEnrollUserResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_QueryCourseRequest(arg) { + if (!(arg instanceof service_pb.QueryCourseRequest)) { + throw new Error('Expected argument of type service.QueryCourseRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_QueryCourseRequest(buffer_arg) { + return service_pb.QueryCourseRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_QueryCourseResponse(arg) { + if (!(arg instanceof service_pb.QueryCourseResponse)) { + throw new Error('Expected argument of type service.QueryCourseResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_QueryCourseResponse(buffer_arg) { + return service_pb.QueryCourseResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_QueryCoursesRequest(arg) { + if (!(arg instanceof service_pb.QueryCoursesRequest)) { + throw new Error('Expected argument of type service.QueryCoursesRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_QueryCoursesRequest(buffer_arg) { + return service_pb.QueryCoursesRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_service_QueryCoursesResponse(arg) { + if (!(arg instanceof service_pb.QueryCoursesResponse)) { + throw new Error('Expected argument of type service.QueryCoursesResponse'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_service_QueryCoursesResponse(buffer_arg) { + return service_pb.QueryCoursesResponse.deserializeBinary(new Uint8Array(buffer_arg)); +} + + +// Service definition for CoursesService +var CoursesServiceService = exports.CoursesServiceService = { + // Lookup User entity by id: User type from users plugin (extended here) +lookupUserById: { + path: '/service.CoursesService/LookupUserById', + requestStream: false, + responseStream: false, + requestType: service_pb.LookupUserByIdRequest, + responseType: service_pb.LookupUserByIdResponse, + requestSerialize: serialize_service_LookupUserByIdRequest, + requestDeserialize: deserialize_service_LookupUserByIdRequest, + responseSerialize: serialize_service_LookupUserByIdResponse, + responseDeserialize: deserialize_service_LookupUserByIdResponse, + }, + // Creates a new course +mutationCreateCourse: { + path: '/service.CoursesService/MutationCreateCourse', + requestStream: false, + responseStream: false, + requestType: service_pb.MutationCreateCourseRequest, + responseType: service_pb.MutationCreateCourseResponse, + requestSerialize: serialize_service_MutationCreateCourseRequest, + requestDeserialize: deserialize_service_MutationCreateCourseRequest, + responseSerialize: serialize_service_MutationCreateCourseResponse, + responseDeserialize: deserialize_service_MutationCreateCourseResponse, + }, + // Enrolls a user in a course +mutationEnrollUser: { + path: '/service.CoursesService/MutationEnrollUser', + requestStream: false, + responseStream: false, + requestType: service_pb.MutationEnrollUserRequest, + responseType: service_pb.MutationEnrollUserResponse, + requestSerialize: serialize_service_MutationEnrollUserRequest, + requestDeserialize: deserialize_service_MutationEnrollUserRequest, + responseSerialize: serialize_service_MutationEnrollUserResponse, + responseDeserialize: deserialize_service_MutationEnrollUserResponse, + }, + // Returns a single course by ID +queryCourse: { + path: '/service.CoursesService/QueryCourse', + requestStream: false, + responseStream: false, + requestType: service_pb.QueryCourseRequest, + responseType: service_pb.QueryCourseResponse, + requestSerialize: serialize_service_QueryCourseRequest, + requestDeserialize: deserialize_service_QueryCourseRequest, + responseSerialize: serialize_service_QueryCourseResponse, + responseDeserialize: deserialize_service_QueryCourseResponse, + }, + // Returns a list of all courses +queryCourses: { + path: '/service.CoursesService/QueryCourses', + requestStream: false, + responseStream: false, + requestType: service_pb.QueryCoursesRequest, + responseType: service_pb.QueryCoursesResponse, + requestSerialize: serialize_service_QueryCoursesRequest, + requestDeserialize: deserialize_service_QueryCoursesRequest, + responseSerialize: serialize_service_QueryCoursesResponse, + responseDeserialize: deserialize_service_QueryCoursesResponse, + }, +}; + +exports.CoursesServiceClient = grpc.makeGenericClientConstructor(CoursesServiceService, 'CoursesService'); diff --git a/cosmo-router/plugins/courses/generated/service_pb.d.ts b/cosmo-router/plugins/courses/generated/service_pb.d.ts new file mode 100644 index 0000000..113ac1e --- /dev/null +++ b/cosmo-router/plugins/courses/generated/service_pb.d.ts @@ -0,0 +1,388 @@ +// package: service +// file: service.proto + +/* tslint:disable */ +/* eslint-disable */ + +import * as jspb from "google-protobuf"; + +export class LookupUserByIdRequestKey extends jspb.Message { + getId(): string; + setId(value: string): LookupUserByIdRequestKey; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LookupUserByIdRequestKey.AsObject; + static toObject(includeInstance: boolean, msg: LookupUserByIdRequestKey): LookupUserByIdRequestKey.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LookupUserByIdRequestKey, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LookupUserByIdRequestKey; + static deserializeBinaryFromReader(message: LookupUserByIdRequestKey, reader: jspb.BinaryReader): LookupUserByIdRequestKey; +} + +export namespace LookupUserByIdRequestKey { + export type AsObject = { + id: string, + } +} + +export class LookupUserByIdRequest extends jspb.Message { + clearKeysList(): void; + getKeysList(): Array; + setKeysList(value: Array): LookupUserByIdRequest; + addKeys(value?: LookupUserByIdRequestKey, index?: number): LookupUserByIdRequestKey; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LookupUserByIdRequest.AsObject; + static toObject(includeInstance: boolean, msg: LookupUserByIdRequest): LookupUserByIdRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LookupUserByIdRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LookupUserByIdRequest; + static deserializeBinaryFromReader(message: LookupUserByIdRequest, reader: jspb.BinaryReader): LookupUserByIdRequest; +} + +export namespace LookupUserByIdRequest { + export type AsObject = { + keysList: Array, + } +} + +export class LookupUserByIdResponse extends jspb.Message { + clearResultList(): void; + getResultList(): Array; + setResultList(value: Array): LookupUserByIdResponse; + addResult(value?: User, index?: number): User; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): LookupUserByIdResponse.AsObject; + static toObject(includeInstance: boolean, msg: LookupUserByIdResponse): LookupUserByIdResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: LookupUserByIdResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): LookupUserByIdResponse; + static deserializeBinaryFromReader(message: LookupUserByIdResponse, reader: jspb.BinaryReader): LookupUserByIdResponse; +} + +export namespace LookupUserByIdResponse { + export type AsObject = { + resultList: Array, + } +} + +export class QueryCoursesRequest extends jspb.Message { + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): QueryCoursesRequest.AsObject; + static toObject(includeInstance: boolean, msg: QueryCoursesRequest): QueryCoursesRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: QueryCoursesRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): QueryCoursesRequest; + static deserializeBinaryFromReader(message: QueryCoursesRequest, reader: jspb.BinaryReader): QueryCoursesRequest; +} + +export namespace QueryCoursesRequest { + export type AsObject = { + } +} + +export class QueryCoursesResponse extends jspb.Message { + clearCoursesList(): void; + getCoursesList(): Array; + setCoursesList(value: Array): QueryCoursesResponse; + addCourses(value?: Course, index?: number): Course; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): QueryCoursesResponse.AsObject; + static toObject(includeInstance: boolean, msg: QueryCoursesResponse): QueryCoursesResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: QueryCoursesResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): QueryCoursesResponse; + static deserializeBinaryFromReader(message: QueryCoursesResponse, reader: jspb.BinaryReader): QueryCoursesResponse; +} + +export namespace QueryCoursesResponse { + export type AsObject = { + coursesList: Array, + } +} + +export class QueryCourseRequest extends jspb.Message { + getId(): string; + setId(value: string): QueryCourseRequest; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): QueryCourseRequest.AsObject; + static toObject(includeInstance: boolean, msg: QueryCourseRequest): QueryCourseRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: QueryCourseRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): QueryCourseRequest; + static deserializeBinaryFromReader(message: QueryCourseRequest, reader: jspb.BinaryReader): QueryCourseRequest; +} + +export namespace QueryCourseRequest { + export type AsObject = { + id: string, + } +} + +export class QueryCourseResponse extends jspb.Message { + + hasCourse(): boolean; + clearCourse(): void; + getCourse(): Course | undefined; + setCourse(value?: Course): QueryCourseResponse; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): QueryCourseResponse.AsObject; + static toObject(includeInstance: boolean, msg: QueryCourseResponse): QueryCourseResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: QueryCourseResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): QueryCourseResponse; + static deserializeBinaryFromReader(message: QueryCourseResponse, reader: jspb.BinaryReader): QueryCourseResponse; +} + +export namespace QueryCourseResponse { + export type AsObject = { + course?: Course.AsObject, + } +} + +export class MutationCreateCourseRequest extends jspb.Message { + + hasInput(): boolean; + clearInput(): void; + getInput(): CourseInput | undefined; + setInput(value?: CourseInput): MutationCreateCourseRequest; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): MutationCreateCourseRequest.AsObject; + static toObject(includeInstance: boolean, msg: MutationCreateCourseRequest): MutationCreateCourseRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: MutationCreateCourseRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): MutationCreateCourseRequest; + static deserializeBinaryFromReader(message: MutationCreateCourseRequest, reader: jspb.BinaryReader): MutationCreateCourseRequest; +} + +export namespace MutationCreateCourseRequest { + export type AsObject = { + input?: CourseInput.AsObject, + } +} + +export class MutationCreateCourseResponse extends jspb.Message { + + hasCreateCourse(): boolean; + clearCreateCourse(): void; + getCreateCourse(): Course | undefined; + setCreateCourse(value?: Course): MutationCreateCourseResponse; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): MutationCreateCourseResponse.AsObject; + static toObject(includeInstance: boolean, msg: MutationCreateCourseResponse): MutationCreateCourseResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: MutationCreateCourseResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): MutationCreateCourseResponse; + static deserializeBinaryFromReader(message: MutationCreateCourseResponse, reader: jspb.BinaryReader): MutationCreateCourseResponse; +} + +export namespace MutationCreateCourseResponse { + export type AsObject = { + createCourse?: Course.AsObject, + } +} + +export class MutationEnrollUserRequest extends jspb.Message { + getUserId(): string; + setUserId(value: string): MutationEnrollUserRequest; + getCourseId(): string; + setCourseId(value: string): MutationEnrollUserRequest; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): MutationEnrollUserRequest.AsObject; + static toObject(includeInstance: boolean, msg: MutationEnrollUserRequest): MutationEnrollUserRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: MutationEnrollUserRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): MutationEnrollUserRequest; + static deserializeBinaryFromReader(message: MutationEnrollUserRequest, reader: jspb.BinaryReader): MutationEnrollUserRequest; +} + +export namespace MutationEnrollUserRequest { + export type AsObject = { + userId: string, + courseId: string, + } +} + +export class MutationEnrollUserResponse extends jspb.Message { + + hasEnrollUser(): boolean; + clearEnrollUser(): void; + getEnrollUser(): Enrollment | undefined; + setEnrollUser(value?: Enrollment): MutationEnrollUserResponse; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): MutationEnrollUserResponse.AsObject; + static toObject(includeInstance: boolean, msg: MutationEnrollUserResponse): MutationEnrollUserResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: MutationEnrollUserResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): MutationEnrollUserResponse; + static deserializeBinaryFromReader(message: MutationEnrollUserResponse, reader: jspb.BinaryReader): MutationEnrollUserResponse; +} + +export namespace MutationEnrollUserResponse { + export type AsObject = { + enrollUser?: Enrollment.AsObject, + } +} + +export class User extends jspb.Message { + getId(): string; + setId(value: string): User; + clearInstructorCoursesList(): void; + getInstructorCoursesList(): Array; + setInstructorCoursesList(value: Array): User; + addInstructorCourses(value?: Course, index?: number): Course; + clearEnrollmentsList(): void; + getEnrollmentsList(): Array; + setEnrollmentsList(value: Array): User; + addEnrollments(value?: Enrollment, index?: number): Enrollment; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): User.AsObject; + static toObject(includeInstance: boolean, msg: User): User.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: User, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): User; + static deserializeBinaryFromReader(message: User, reader: jspb.BinaryReader): User; +} + +export namespace User { + export type AsObject = { + id: string, + instructorCoursesList: Array, + enrollmentsList: Array, + } +} + +export class Course extends jspb.Message { + getId(): string; + setId(value: string): Course; + getTitle(): string; + setTitle(value: string): Course; + getDescription(): string; + setDescription(value: string): Course; + + hasInstructor(): boolean; + clearInstructor(): void; + getInstructor(): User | undefined; + setInstructor(value?: User): Course; + getDurationHours(): number; + setDurationHours(value: number): Course; + getPublished(): boolean; + setPublished(value: boolean): Course; + clearEnrollmentsList(): void; + getEnrollmentsList(): Array; + setEnrollmentsList(value: Array): Course; + addEnrollments(value?: Enrollment, index?: number): Enrollment; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Course.AsObject; + static toObject(includeInstance: boolean, msg: Course): Course.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: Course, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Course; + static deserializeBinaryFromReader(message: Course, reader: jspb.BinaryReader): Course; +} + +export namespace Course { + export type AsObject = { + id: string, + title: string, + description: string, + instructor?: User.AsObject, + durationHours: number, + published: boolean, + enrollmentsList: Array, + } +} + +export class CourseInput extends jspb.Message { + getTitle(): string; + setTitle(value: string): CourseInput; + getDescription(): string; + setDescription(value: string): CourseInput; + getInstructorId(): string; + setInstructorId(value: string): CourseInput; + getDurationHours(): number; + setDurationHours(value: number): CourseInput; + getPublished(): boolean; + setPublished(value: boolean): CourseInput; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): CourseInput.AsObject; + static toObject(includeInstance: boolean, msg: CourseInput): CourseInput.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: CourseInput, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): CourseInput; + static deserializeBinaryFromReader(message: CourseInput, reader: jspb.BinaryReader): CourseInput; +} + +export namespace CourseInput { + export type AsObject = { + title: string, + description: string, + instructorId: string, + durationHours: number, + published: boolean, + } +} + +export class Enrollment extends jspb.Message { + getId(): string; + setId(value: string): Enrollment; + + hasUser(): boolean; + clearUser(): void; + getUser(): User | undefined; + setUser(value?: User): Enrollment; + + hasCourse(): boolean; + clearCourse(): void; + getCourse(): Course | undefined; + setCourse(value?: Course): Enrollment; + getProgress(): number; + setProgress(value: number): Enrollment; + getEnrolledAt(): string; + setEnrolledAt(value: string): Enrollment; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Enrollment.AsObject; + static toObject(includeInstance: boolean, msg: Enrollment): Enrollment.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: Enrollment, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Enrollment; + static deserializeBinaryFromReader(message: Enrollment, reader: jspb.BinaryReader): Enrollment; +} + +export namespace Enrollment { + export type AsObject = { + id: string, + user?: User.AsObject, + course?: Course.AsObject, + progress: number, + enrolledAt: string, + } +} diff --git a/cosmo-router/plugins/courses/generated/service_pb.js b/cosmo-router/plugins/courses/generated/service_pb.js new file mode 100644 index 0000000..cfb4c59 --- /dev/null +++ b/cosmo-router/plugins/courses/generated/service_pb.js @@ -0,0 +1,3099 @@ +// source: service.proto +/** + * @fileoverview + * @enhanceable + * @suppress {missingRequire} reports error on implicit type usages. + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! +/* eslint-disable */ +// @ts-nocheck + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = globalThis; + +goog.exportSymbol('proto.service.Course', null, global); +goog.exportSymbol('proto.service.CourseInput', null, global); +goog.exportSymbol('proto.service.Enrollment', null, global); +goog.exportSymbol('proto.service.LookupUserByIdRequest', null, global); +goog.exportSymbol('proto.service.LookupUserByIdRequestKey', null, global); +goog.exportSymbol('proto.service.LookupUserByIdResponse', null, global); +goog.exportSymbol('proto.service.MutationCreateCourseRequest', null, global); +goog.exportSymbol('proto.service.MutationCreateCourseResponse', null, global); +goog.exportSymbol('proto.service.MutationEnrollUserRequest', null, global); +goog.exportSymbol('proto.service.MutationEnrollUserResponse', null, global); +goog.exportSymbol('proto.service.QueryCourseRequest', null, global); +goog.exportSymbol('proto.service.QueryCourseResponse', null, global); +goog.exportSymbol('proto.service.QueryCoursesRequest', null, global); +goog.exportSymbol('proto.service.QueryCoursesResponse', null, global); +goog.exportSymbol('proto.service.User', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.LookupUserByIdRequestKey = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.LookupUserByIdRequestKey, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.LookupUserByIdRequestKey.displayName = 'proto.service.LookupUserByIdRequestKey'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.LookupUserByIdRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.service.LookupUserByIdRequest.repeatedFields_, null); +}; +goog.inherits(proto.service.LookupUserByIdRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.LookupUserByIdRequest.displayName = 'proto.service.LookupUserByIdRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.LookupUserByIdResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.service.LookupUserByIdResponse.repeatedFields_, null); +}; +goog.inherits(proto.service.LookupUserByIdResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.LookupUserByIdResponse.displayName = 'proto.service.LookupUserByIdResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.QueryCoursesRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.QueryCoursesRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.QueryCoursesRequest.displayName = 'proto.service.QueryCoursesRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.QueryCoursesResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.service.QueryCoursesResponse.repeatedFields_, null); +}; +goog.inherits(proto.service.QueryCoursesResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.QueryCoursesResponse.displayName = 'proto.service.QueryCoursesResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.QueryCourseRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.QueryCourseRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.QueryCourseRequest.displayName = 'proto.service.QueryCourseRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.QueryCourseResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.QueryCourseResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.QueryCourseResponse.displayName = 'proto.service.QueryCourseResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.MutationCreateCourseRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.MutationCreateCourseRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.MutationCreateCourseRequest.displayName = 'proto.service.MutationCreateCourseRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.MutationCreateCourseResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.MutationCreateCourseResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.MutationCreateCourseResponse.displayName = 'proto.service.MutationCreateCourseResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.MutationEnrollUserRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.MutationEnrollUserRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.MutationEnrollUserRequest.displayName = 'proto.service.MutationEnrollUserRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.MutationEnrollUserResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.MutationEnrollUserResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.MutationEnrollUserResponse.displayName = 'proto.service.MutationEnrollUserResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.User = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.service.User.repeatedFields_, null); +}; +goog.inherits(proto.service.User, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.User.displayName = 'proto.service.User'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.Course = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.service.Course.repeatedFields_, null); +}; +goog.inherits(proto.service.Course, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.Course.displayName = 'proto.service.Course'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.CourseInput = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.CourseInput, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.CourseInput.displayName = 'proto.service.CourseInput'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.service.Enrollment = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.service.Enrollment, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.service.Enrollment.displayName = 'proto.service.Enrollment'; +} + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.LookupUserByIdRequestKey.prototype.toObject = function(opt_includeInstance) { + return proto.service.LookupUserByIdRequestKey.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.LookupUserByIdRequestKey} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.LookupUserByIdRequestKey.toObject = function(includeInstance, msg) { + var f, obj = { +id: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.LookupUserByIdRequestKey} + */ +proto.service.LookupUserByIdRequestKey.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.LookupUserByIdRequestKey; + return proto.service.LookupUserByIdRequestKey.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.LookupUserByIdRequestKey} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.LookupUserByIdRequestKey} + */ +proto.service.LookupUserByIdRequestKey.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setId(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.LookupUserByIdRequestKey.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.LookupUserByIdRequestKey.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.LookupUserByIdRequestKey} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.LookupUserByIdRequestKey.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string id = 1; + * @return {string} + */ +proto.service.LookupUserByIdRequestKey.prototype.getId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.LookupUserByIdRequestKey} returns this + */ +proto.service.LookupUserByIdRequestKey.prototype.setId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.service.LookupUserByIdRequest.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.LookupUserByIdRequest.prototype.toObject = function(opt_includeInstance) { + return proto.service.LookupUserByIdRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.LookupUserByIdRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.LookupUserByIdRequest.toObject = function(includeInstance, msg) { + var f, obj = { +keysList: jspb.Message.toObjectList(msg.getKeysList(), + proto.service.LookupUserByIdRequestKey.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.LookupUserByIdRequest} + */ +proto.service.LookupUserByIdRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.LookupUserByIdRequest; + return proto.service.LookupUserByIdRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.LookupUserByIdRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.LookupUserByIdRequest} + */ +proto.service.LookupUserByIdRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.service.LookupUserByIdRequestKey; + reader.readMessage(value,proto.service.LookupUserByIdRequestKey.deserializeBinaryFromReader); + msg.addKeys(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.LookupUserByIdRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.LookupUserByIdRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.LookupUserByIdRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.LookupUserByIdRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getKeysList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.service.LookupUserByIdRequestKey.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated LookupUserByIdRequestKey keys = 1; + * @return {!Array} + */ +proto.service.LookupUserByIdRequest.prototype.getKeysList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.service.LookupUserByIdRequestKey, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.service.LookupUserByIdRequest} returns this +*/ +proto.service.LookupUserByIdRequest.prototype.setKeysList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.service.LookupUserByIdRequestKey=} opt_value + * @param {number=} opt_index + * @return {!proto.service.LookupUserByIdRequestKey} + */ +proto.service.LookupUserByIdRequest.prototype.addKeys = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.service.LookupUserByIdRequestKey, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.service.LookupUserByIdRequest} returns this + */ +proto.service.LookupUserByIdRequest.prototype.clearKeysList = function() { + return this.setKeysList([]); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.service.LookupUserByIdResponse.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.LookupUserByIdResponse.prototype.toObject = function(opt_includeInstance) { + return proto.service.LookupUserByIdResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.LookupUserByIdResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.LookupUserByIdResponse.toObject = function(includeInstance, msg) { + var f, obj = { +resultList: jspb.Message.toObjectList(msg.getResultList(), + proto.service.User.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.LookupUserByIdResponse} + */ +proto.service.LookupUserByIdResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.LookupUserByIdResponse; + return proto.service.LookupUserByIdResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.LookupUserByIdResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.LookupUserByIdResponse} + */ +proto.service.LookupUserByIdResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.service.User; + reader.readMessage(value,proto.service.User.deserializeBinaryFromReader); + msg.addResult(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.LookupUserByIdResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.LookupUserByIdResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.LookupUserByIdResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.LookupUserByIdResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getResultList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.service.User.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated User result = 1; + * @return {!Array} + */ +proto.service.LookupUserByIdResponse.prototype.getResultList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.service.User, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.service.LookupUserByIdResponse} returns this +*/ +proto.service.LookupUserByIdResponse.prototype.setResultList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.service.User=} opt_value + * @param {number=} opt_index + * @return {!proto.service.User} + */ +proto.service.LookupUserByIdResponse.prototype.addResult = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.service.User, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.service.LookupUserByIdResponse} returns this + */ +proto.service.LookupUserByIdResponse.prototype.clearResultList = function() { + return this.setResultList([]); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.QueryCoursesRequest.prototype.toObject = function(opt_includeInstance) { + return proto.service.QueryCoursesRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.QueryCoursesRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.QueryCoursesRequest.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.QueryCoursesRequest} + */ +proto.service.QueryCoursesRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.QueryCoursesRequest; + return proto.service.QueryCoursesRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.QueryCoursesRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.QueryCoursesRequest} + */ +proto.service.QueryCoursesRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.QueryCoursesRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.QueryCoursesRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.QueryCoursesRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.QueryCoursesRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.service.QueryCoursesResponse.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.QueryCoursesResponse.prototype.toObject = function(opt_includeInstance) { + return proto.service.QueryCoursesResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.QueryCoursesResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.QueryCoursesResponse.toObject = function(includeInstance, msg) { + var f, obj = { +coursesList: jspb.Message.toObjectList(msg.getCoursesList(), + proto.service.Course.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.QueryCoursesResponse} + */ +proto.service.QueryCoursesResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.QueryCoursesResponse; + return proto.service.QueryCoursesResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.QueryCoursesResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.QueryCoursesResponse} + */ +proto.service.QueryCoursesResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.service.Course; + reader.readMessage(value,proto.service.Course.deserializeBinaryFromReader); + msg.addCourses(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.QueryCoursesResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.QueryCoursesResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.QueryCoursesResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.QueryCoursesResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getCoursesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.service.Course.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated Course courses = 1; + * @return {!Array} + */ +proto.service.QueryCoursesResponse.prototype.getCoursesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.service.Course, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.service.QueryCoursesResponse} returns this +*/ +proto.service.QueryCoursesResponse.prototype.setCoursesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.service.Course=} opt_value + * @param {number=} opt_index + * @return {!proto.service.Course} + */ +proto.service.QueryCoursesResponse.prototype.addCourses = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.service.Course, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.service.QueryCoursesResponse} returns this + */ +proto.service.QueryCoursesResponse.prototype.clearCoursesList = function() { + return this.setCoursesList([]); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.QueryCourseRequest.prototype.toObject = function(opt_includeInstance) { + return proto.service.QueryCourseRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.QueryCourseRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.QueryCourseRequest.toObject = function(includeInstance, msg) { + var f, obj = { +id: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.QueryCourseRequest} + */ +proto.service.QueryCourseRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.QueryCourseRequest; + return proto.service.QueryCourseRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.QueryCourseRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.QueryCourseRequest} + */ +proto.service.QueryCourseRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setId(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.QueryCourseRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.QueryCourseRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.QueryCourseRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.QueryCourseRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string id = 1; + * @return {string} + */ +proto.service.QueryCourseRequest.prototype.getId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.QueryCourseRequest} returns this + */ +proto.service.QueryCourseRequest.prototype.setId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.QueryCourseResponse.prototype.toObject = function(opt_includeInstance) { + return proto.service.QueryCourseResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.QueryCourseResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.QueryCourseResponse.toObject = function(includeInstance, msg) { + var f, obj = { +course: (f = msg.getCourse()) && proto.service.Course.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.QueryCourseResponse} + */ +proto.service.QueryCourseResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.QueryCourseResponse; + return proto.service.QueryCourseResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.QueryCourseResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.QueryCourseResponse} + */ +proto.service.QueryCourseResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.service.Course; + reader.readMessage(value,proto.service.Course.deserializeBinaryFromReader); + msg.setCourse(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.QueryCourseResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.QueryCourseResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.QueryCourseResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.QueryCourseResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getCourse(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.service.Course.serializeBinaryToWriter + ); + } +}; + + +/** + * optional Course course = 1; + * @return {?proto.service.Course} + */ +proto.service.QueryCourseResponse.prototype.getCourse = function() { + return /** @type{?proto.service.Course} */ ( + jspb.Message.getWrapperField(this, proto.service.Course, 1)); +}; + + +/** + * @param {?proto.service.Course|undefined} value + * @return {!proto.service.QueryCourseResponse} returns this +*/ +proto.service.QueryCourseResponse.prototype.setCourse = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.service.QueryCourseResponse} returns this + */ +proto.service.QueryCourseResponse.prototype.clearCourse = function() { + return this.setCourse(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.service.QueryCourseResponse.prototype.hasCourse = function() { + return jspb.Message.getField(this, 1) != null; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.MutationCreateCourseRequest.prototype.toObject = function(opt_includeInstance) { + return proto.service.MutationCreateCourseRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.MutationCreateCourseRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.MutationCreateCourseRequest.toObject = function(includeInstance, msg) { + var f, obj = { +input: (f = msg.getInput()) && proto.service.CourseInput.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.MutationCreateCourseRequest} + */ +proto.service.MutationCreateCourseRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.MutationCreateCourseRequest; + return proto.service.MutationCreateCourseRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.MutationCreateCourseRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.MutationCreateCourseRequest} + */ +proto.service.MutationCreateCourseRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.service.CourseInput; + reader.readMessage(value,proto.service.CourseInput.deserializeBinaryFromReader); + msg.setInput(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.MutationCreateCourseRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.MutationCreateCourseRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.MutationCreateCourseRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.MutationCreateCourseRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getInput(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.service.CourseInput.serializeBinaryToWriter + ); + } +}; + + +/** + * optional CourseInput input = 1; + * @return {?proto.service.CourseInput} + */ +proto.service.MutationCreateCourseRequest.prototype.getInput = function() { + return /** @type{?proto.service.CourseInput} */ ( + jspb.Message.getWrapperField(this, proto.service.CourseInput, 1)); +}; + + +/** + * @param {?proto.service.CourseInput|undefined} value + * @return {!proto.service.MutationCreateCourseRequest} returns this +*/ +proto.service.MutationCreateCourseRequest.prototype.setInput = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.service.MutationCreateCourseRequest} returns this + */ +proto.service.MutationCreateCourseRequest.prototype.clearInput = function() { + return this.setInput(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.service.MutationCreateCourseRequest.prototype.hasInput = function() { + return jspb.Message.getField(this, 1) != null; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.MutationCreateCourseResponse.prototype.toObject = function(opt_includeInstance) { + return proto.service.MutationCreateCourseResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.MutationCreateCourseResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.MutationCreateCourseResponse.toObject = function(includeInstance, msg) { + var f, obj = { +createCourse: (f = msg.getCreateCourse()) && proto.service.Course.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.MutationCreateCourseResponse} + */ +proto.service.MutationCreateCourseResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.MutationCreateCourseResponse; + return proto.service.MutationCreateCourseResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.MutationCreateCourseResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.MutationCreateCourseResponse} + */ +proto.service.MutationCreateCourseResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.service.Course; + reader.readMessage(value,proto.service.Course.deserializeBinaryFromReader); + msg.setCreateCourse(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.MutationCreateCourseResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.MutationCreateCourseResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.MutationCreateCourseResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.MutationCreateCourseResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getCreateCourse(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.service.Course.serializeBinaryToWriter + ); + } +}; + + +/** + * optional Course create_course = 1; + * @return {?proto.service.Course} + */ +proto.service.MutationCreateCourseResponse.prototype.getCreateCourse = function() { + return /** @type{?proto.service.Course} */ ( + jspb.Message.getWrapperField(this, proto.service.Course, 1)); +}; + + +/** + * @param {?proto.service.Course|undefined} value + * @return {!proto.service.MutationCreateCourseResponse} returns this +*/ +proto.service.MutationCreateCourseResponse.prototype.setCreateCourse = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.service.MutationCreateCourseResponse} returns this + */ +proto.service.MutationCreateCourseResponse.prototype.clearCreateCourse = function() { + return this.setCreateCourse(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.service.MutationCreateCourseResponse.prototype.hasCreateCourse = function() { + return jspb.Message.getField(this, 1) != null; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.MutationEnrollUserRequest.prototype.toObject = function(opt_includeInstance) { + return proto.service.MutationEnrollUserRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.MutationEnrollUserRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.MutationEnrollUserRequest.toObject = function(includeInstance, msg) { + var f, obj = { +userId: jspb.Message.getFieldWithDefault(msg, 1, ""), +courseId: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.MutationEnrollUserRequest} + */ +proto.service.MutationEnrollUserRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.MutationEnrollUserRequest; + return proto.service.MutationEnrollUserRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.MutationEnrollUserRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.MutationEnrollUserRequest} + */ +proto.service.MutationEnrollUserRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setUserId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setCourseId(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.MutationEnrollUserRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.MutationEnrollUserRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.MutationEnrollUserRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.MutationEnrollUserRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getUserId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getCourseId(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string user_id = 1; + * @return {string} + */ +proto.service.MutationEnrollUserRequest.prototype.getUserId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.MutationEnrollUserRequest} returns this + */ +proto.service.MutationEnrollUserRequest.prototype.setUserId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string course_id = 2; + * @return {string} + */ +proto.service.MutationEnrollUserRequest.prototype.getCourseId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.MutationEnrollUserRequest} returns this + */ +proto.service.MutationEnrollUserRequest.prototype.setCourseId = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.MutationEnrollUserResponse.prototype.toObject = function(opt_includeInstance) { + return proto.service.MutationEnrollUserResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.MutationEnrollUserResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.MutationEnrollUserResponse.toObject = function(includeInstance, msg) { + var f, obj = { +enrollUser: (f = msg.getEnrollUser()) && proto.service.Enrollment.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.MutationEnrollUserResponse} + */ +proto.service.MutationEnrollUserResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.MutationEnrollUserResponse; + return proto.service.MutationEnrollUserResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.MutationEnrollUserResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.MutationEnrollUserResponse} + */ +proto.service.MutationEnrollUserResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.service.Enrollment; + reader.readMessage(value,proto.service.Enrollment.deserializeBinaryFromReader); + msg.setEnrollUser(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.MutationEnrollUserResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.MutationEnrollUserResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.MutationEnrollUserResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.MutationEnrollUserResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getEnrollUser(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.service.Enrollment.serializeBinaryToWriter + ); + } +}; + + +/** + * optional Enrollment enroll_user = 1; + * @return {?proto.service.Enrollment} + */ +proto.service.MutationEnrollUserResponse.prototype.getEnrollUser = function() { + return /** @type{?proto.service.Enrollment} */ ( + jspb.Message.getWrapperField(this, proto.service.Enrollment, 1)); +}; + + +/** + * @param {?proto.service.Enrollment|undefined} value + * @return {!proto.service.MutationEnrollUserResponse} returns this +*/ +proto.service.MutationEnrollUserResponse.prototype.setEnrollUser = function(value) { + return jspb.Message.setWrapperField(this, 1, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.service.MutationEnrollUserResponse} returns this + */ +proto.service.MutationEnrollUserResponse.prototype.clearEnrollUser = function() { + return this.setEnrollUser(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.service.MutationEnrollUserResponse.prototype.hasEnrollUser = function() { + return jspb.Message.getField(this, 1) != null; +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.service.User.repeatedFields_ = [2,3]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.User.prototype.toObject = function(opt_includeInstance) { + return proto.service.User.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.User} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.User.toObject = function(includeInstance, msg) { + var f, obj = { +id: jspb.Message.getFieldWithDefault(msg, 1, ""), +instructorCoursesList: jspb.Message.toObjectList(msg.getInstructorCoursesList(), + proto.service.Course.toObject, includeInstance), +enrollmentsList: jspb.Message.toObjectList(msg.getEnrollmentsList(), + proto.service.Enrollment.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.User} + */ +proto.service.User.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.User; + return proto.service.User.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.User} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.User} + */ +proto.service.User.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setId(value); + break; + case 2: + var value = new proto.service.Course; + reader.readMessage(value,proto.service.Course.deserializeBinaryFromReader); + msg.addInstructorCourses(value); + break; + case 3: + var value = new proto.service.Enrollment; + reader.readMessage(value,proto.service.Enrollment.deserializeBinaryFromReader); + msg.addEnrollments(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.User.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.User.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.User} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.User.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getInstructorCoursesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 2, + f, + proto.service.Course.serializeBinaryToWriter + ); + } + f = message.getEnrollmentsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 3, + f, + proto.service.Enrollment.serializeBinaryToWriter + ); + } +}; + + +/** + * optional string id = 1; + * @return {string} + */ +proto.service.User.prototype.getId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.User} returns this + */ +proto.service.User.prototype.setId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * repeated Course instructor_courses = 2; + * @return {!Array} + */ +proto.service.User.prototype.getInstructorCoursesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.service.Course, 2)); +}; + + +/** + * @param {!Array} value + * @return {!proto.service.User} returns this +*/ +proto.service.User.prototype.setInstructorCoursesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 2, value); +}; + + +/** + * @param {!proto.service.Course=} opt_value + * @param {number=} opt_index + * @return {!proto.service.Course} + */ +proto.service.User.prototype.addInstructorCourses = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.service.Course, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.service.User} returns this + */ +proto.service.User.prototype.clearInstructorCoursesList = function() { + return this.setInstructorCoursesList([]); +}; + + +/** + * repeated Enrollment enrollments = 3; + * @return {!Array} + */ +proto.service.User.prototype.getEnrollmentsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.service.Enrollment, 3)); +}; + + +/** + * @param {!Array} value + * @return {!proto.service.User} returns this +*/ +proto.service.User.prototype.setEnrollmentsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 3, value); +}; + + +/** + * @param {!proto.service.Enrollment=} opt_value + * @param {number=} opt_index + * @return {!proto.service.Enrollment} + */ +proto.service.User.prototype.addEnrollments = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.service.Enrollment, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.service.User} returns this + */ +proto.service.User.prototype.clearEnrollmentsList = function() { + return this.setEnrollmentsList([]); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.service.Course.repeatedFields_ = [7]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.Course.prototype.toObject = function(opt_includeInstance) { + return proto.service.Course.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.Course} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.Course.toObject = function(includeInstance, msg) { + var f, obj = { +id: jspb.Message.getFieldWithDefault(msg, 1, ""), +title: jspb.Message.getFieldWithDefault(msg, 2, ""), +description: jspb.Message.getFieldWithDefault(msg, 3, ""), +instructor: (f = msg.getInstructor()) && proto.service.User.toObject(includeInstance, f), +durationHours: jspb.Message.getFieldWithDefault(msg, 5, 0), +published: jspb.Message.getBooleanFieldWithDefault(msg, 6, false), +enrollmentsList: jspb.Message.toObjectList(msg.getEnrollmentsList(), + proto.service.Enrollment.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.Course} + */ +proto.service.Course.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.Course; + return proto.service.Course.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.Course} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.Course} + */ +proto.service.Course.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setTitle(value); + break; + case 3: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setDescription(value); + break; + case 4: + var value = new proto.service.User; + reader.readMessage(value,proto.service.User.deserializeBinaryFromReader); + msg.setInstructor(value); + break; + case 5: + var value = /** @type {number} */ (reader.readInt32()); + msg.setDurationHours(value); + break; + case 6: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setPublished(value); + break; + case 7: + var value = new proto.service.Enrollment; + reader.readMessage(value,proto.service.Enrollment.deserializeBinaryFromReader); + msg.addEnrollments(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.Course.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.Course.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.Course} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.Course.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getTitle(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getDescription(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getInstructor(); + if (f != null) { + writer.writeMessage( + 4, + f, + proto.service.User.serializeBinaryToWriter + ); + } + f = message.getDurationHours(); + if (f !== 0) { + writer.writeInt32( + 5, + f + ); + } + f = message.getPublished(); + if (f) { + writer.writeBool( + 6, + f + ); + } + f = message.getEnrollmentsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 7, + f, + proto.service.Enrollment.serializeBinaryToWriter + ); + } +}; + + +/** + * optional string id = 1; + * @return {string} + */ +proto.service.Course.prototype.getId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.Course} returns this + */ +proto.service.Course.prototype.setId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string title = 2; + * @return {string} + */ +proto.service.Course.prototype.getTitle = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.Course} returns this + */ +proto.service.Course.prototype.setTitle = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string description = 3; + * @return {string} + */ +proto.service.Course.prototype.getDescription = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.Course} returns this + */ +proto.service.Course.prototype.setDescription = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional User instructor = 4; + * @return {?proto.service.User} + */ +proto.service.Course.prototype.getInstructor = function() { + return /** @type{?proto.service.User} */ ( + jspb.Message.getWrapperField(this, proto.service.User, 4)); +}; + + +/** + * @param {?proto.service.User|undefined} value + * @return {!proto.service.Course} returns this +*/ +proto.service.Course.prototype.setInstructor = function(value) { + return jspb.Message.setWrapperField(this, 4, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.service.Course} returns this + */ +proto.service.Course.prototype.clearInstructor = function() { + return this.setInstructor(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.service.Course.prototype.hasInstructor = function() { + return jspb.Message.getField(this, 4) != null; +}; + + +/** + * optional int32 duration_hours = 5; + * @return {number} + */ +proto.service.Course.prototype.getDurationHours = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 5, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.service.Course} returns this + */ +proto.service.Course.prototype.setDurationHours = function(value) { + return jspb.Message.setProto3IntField(this, 5, value); +}; + + +/** + * optional bool published = 6; + * @return {boolean} + */ +proto.service.Course.prototype.getPublished = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 6, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.service.Course} returns this + */ +proto.service.Course.prototype.setPublished = function(value) { + return jspb.Message.setProto3BooleanField(this, 6, value); +}; + + +/** + * repeated Enrollment enrollments = 7; + * @return {!Array} + */ +proto.service.Course.prototype.getEnrollmentsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.service.Enrollment, 7)); +}; + + +/** + * @param {!Array} value + * @return {!proto.service.Course} returns this +*/ +proto.service.Course.prototype.setEnrollmentsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 7, value); +}; + + +/** + * @param {!proto.service.Enrollment=} opt_value + * @param {number=} opt_index + * @return {!proto.service.Enrollment} + */ +proto.service.Course.prototype.addEnrollments = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 7, opt_value, proto.service.Enrollment, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.service.Course} returns this + */ +proto.service.Course.prototype.clearEnrollmentsList = function() { + return this.setEnrollmentsList([]); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.CourseInput.prototype.toObject = function(opt_includeInstance) { + return proto.service.CourseInput.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.CourseInput} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.CourseInput.toObject = function(includeInstance, msg) { + var f, obj = { +title: jspb.Message.getFieldWithDefault(msg, 1, ""), +description: jspb.Message.getFieldWithDefault(msg, 2, ""), +instructorId: jspb.Message.getFieldWithDefault(msg, 3, ""), +durationHours: jspb.Message.getFieldWithDefault(msg, 4, 0), +published: jspb.Message.getBooleanFieldWithDefault(msg, 5, false) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.CourseInput} + */ +proto.service.CourseInput.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.CourseInput; + return proto.service.CourseInput.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.CourseInput} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.CourseInput} + */ +proto.service.CourseInput.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setTitle(value); + break; + case 2: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setDescription(value); + break; + case 3: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setInstructorId(value); + break; + case 4: + var value = /** @type {number} */ (reader.readInt32()); + msg.setDurationHours(value); + break; + case 5: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setPublished(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.CourseInput.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.CourseInput.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.CourseInput} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.CourseInput.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTitle(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getDescription(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getInstructorId(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getDurationHours(); + if (f !== 0) { + writer.writeInt32( + 4, + f + ); + } + f = message.getPublished(); + if (f) { + writer.writeBool( + 5, + f + ); + } +}; + + +/** + * optional string title = 1; + * @return {string} + */ +proto.service.CourseInput.prototype.getTitle = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.CourseInput} returns this + */ +proto.service.CourseInput.prototype.setTitle = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string description = 2; + * @return {string} + */ +proto.service.CourseInput.prototype.getDescription = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.CourseInput} returns this + */ +proto.service.CourseInput.prototype.setDescription = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string instructor_id = 3; + * @return {string} + */ +proto.service.CourseInput.prototype.getInstructorId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.CourseInput} returns this + */ +proto.service.CourseInput.prototype.setInstructorId = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional int32 duration_hours = 4; + * @return {number} + */ +proto.service.CourseInput.prototype.getDurationHours = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.service.CourseInput} returns this + */ +proto.service.CourseInput.prototype.setDurationHours = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); +}; + + +/** + * optional bool published = 5; + * @return {boolean} + */ +proto.service.CourseInput.prototype.getPublished = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.service.CourseInput} returns this + */ +proto.service.CourseInput.prototype.setPublished = function(value) { + return jspb.Message.setProto3BooleanField(this, 5, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.service.Enrollment.prototype.toObject = function(opt_includeInstance) { + return proto.service.Enrollment.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.service.Enrollment} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.Enrollment.toObject = function(includeInstance, msg) { + var f, obj = { +id: jspb.Message.getFieldWithDefault(msg, 1, ""), +user: (f = msg.getUser()) && proto.service.User.toObject(includeInstance, f), +course: (f = msg.getCourse()) && proto.service.Course.toObject(includeInstance, f), +progress: jspb.Message.getFieldWithDefault(msg, 4, 0), +enrolledAt: jspb.Message.getFieldWithDefault(msg, 5, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.service.Enrollment} + */ +proto.service.Enrollment.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.service.Enrollment; + return proto.service.Enrollment.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.service.Enrollment} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.service.Enrollment} + */ +proto.service.Enrollment.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setId(value); + break; + case 2: + var value = new proto.service.User; + reader.readMessage(value,proto.service.User.deserializeBinaryFromReader); + msg.setUser(value); + break; + case 3: + var value = new proto.service.Course; + reader.readMessage(value,proto.service.Course.deserializeBinaryFromReader); + msg.setCourse(value); + break; + case 4: + var value = /** @type {number} */ (reader.readInt32()); + msg.setProgress(value); + break; + case 5: + var value = /** @type {string} */ (reader.readStringRequireUtf8()); + msg.setEnrolledAt(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.service.Enrollment.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.service.Enrollment.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.service.Enrollment} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.service.Enrollment.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getUser(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.service.User.serializeBinaryToWriter + ); + } + f = message.getCourse(); + if (f != null) { + writer.writeMessage( + 3, + f, + proto.service.Course.serializeBinaryToWriter + ); + } + f = message.getProgress(); + if (f !== 0) { + writer.writeInt32( + 4, + f + ); + } + f = message.getEnrolledAt(); + if (f.length > 0) { + writer.writeString( + 5, + f + ); + } +}; + + +/** + * optional string id = 1; + * @return {string} + */ +proto.service.Enrollment.prototype.getId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.Enrollment} returns this + */ +proto.service.Enrollment.prototype.setId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional User user = 2; + * @return {?proto.service.User} + */ +proto.service.Enrollment.prototype.getUser = function() { + return /** @type{?proto.service.User} */ ( + jspb.Message.getWrapperField(this, proto.service.User, 2)); +}; + + +/** + * @param {?proto.service.User|undefined} value + * @return {!proto.service.Enrollment} returns this +*/ +proto.service.Enrollment.prototype.setUser = function(value) { + return jspb.Message.setWrapperField(this, 2, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.service.Enrollment} returns this + */ +proto.service.Enrollment.prototype.clearUser = function() { + return this.setUser(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.service.Enrollment.prototype.hasUser = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional Course course = 3; + * @return {?proto.service.Course} + */ +proto.service.Enrollment.prototype.getCourse = function() { + return /** @type{?proto.service.Course} */ ( + jspb.Message.getWrapperField(this, proto.service.Course, 3)); +}; + + +/** + * @param {?proto.service.Course|undefined} value + * @return {!proto.service.Enrollment} returns this +*/ +proto.service.Enrollment.prototype.setCourse = function(value) { + return jspb.Message.setWrapperField(this, 3, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.service.Enrollment} returns this + */ +proto.service.Enrollment.prototype.clearCourse = function() { + return this.setCourse(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.service.Enrollment.prototype.hasCourse = function() { + return jspb.Message.getField(this, 3) != null; +}; + + +/** + * optional int32 progress = 4; + * @return {number} + */ +proto.service.Enrollment.prototype.getProgress = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.service.Enrollment} returns this + */ +proto.service.Enrollment.prototype.setProgress = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); +}; + + +/** + * optional string enrolled_at = 5; + * @return {string} + */ +proto.service.Enrollment.prototype.getEnrolledAt = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * @param {string} value + * @return {!proto.service.Enrollment} returns this + */ +proto.service.Enrollment.prototype.setEnrolledAt = function(value) { + return jspb.Message.setProto3StringField(this, 5, value); +}; + + +goog.object.extend(exports, proto.service); diff --git a/cosmo-router/plugins/courses/package.json b/cosmo-router/plugins/courses/package.json new file mode 100644 index 0000000..aa90310 --- /dev/null +++ b/cosmo-router/plugins/courses/package.json @@ -0,0 +1,28 @@ +{ + "name": "plugin-bun", + "version": "1.0.0", + "description": "gRPC Plugin using Bun runtime", + "type": "module", + "scripts": { + "build": "bun build src/plugin.ts --compile --outfile bin/plugin", + "dev": "bun run src/plugin.ts", + "postinstall": "bun ./node_modules/@protocolbuffers/protoc-gen-js/download-protoc-gen-js.js" + }, + "dependencies": { + "@grpc/grpc-js": "^1.14.0", + "google-protobuf": "^4.0.0", + "grpc-health-check": "2.1.0" + }, + "devDependencies": { + "@protocolbuffers/protoc-gen-js": "4.0.0", + "@types/bun": "^1.3.1", + "@types/google-protobuf": "^3.15.12", + "@types/node": "^20.11.5", + "grpc-tools": "^1.12.4", + "grpc_tools_node_protoc_ts": "^5.3.3" + }, + "patchedDependencies": { + "grpc-health-check@2.1.0": "patches/grpc-health-check@2.1.0.patch", + "@protobufjs/inquire@1.1.0": "patches/@protobufjs_inquire@1.1.0.patch" + } +} diff --git a/cosmo-router/plugins/courses/patches/@protobufjs_inquire@1.1.0.patch b/cosmo-router/plugins/courses/patches/@protobufjs_inquire@1.1.0.patch new file mode 100644 index 0000000..955a8de --- /dev/null +++ b/cosmo-router/plugins/courses/patches/@protobufjs_inquire@1.1.0.patch @@ -0,0 +1,51 @@ +diff --git a/index.js b/index.js +index 33778b5539b7fcd7a1e99474a4ecb1745fdfe508..c1520ca11267fc4726ea8b10fe89c8386a2d6e8f 100644 +--- a/index.js ++++ b/index.js +@@ -1,6 +1,10 @@ + "use strict"; + module.exports = inquire; + ++// Note: This code is already present in the repository here: ++// https://github.com/protobufjs/protobuf.js/blob/master/lib/inquire/index.js ++// However the problem is that the build process is not working so it has not gotten released ++ + /** + * Requires a module only if available. + * @memberof util +@@ -9,9 +13,29 @@ module.exports = inquire; + */ + function inquire(moduleName) { + try { +- var mod = eval("quire".replace(/^/,"re"))(moduleName); // eslint-disable-line no-eval +- if (mod && (mod.length || Object.keys(mod).length)) +- return mod; +- } catch (e) {} // eslint-disable-line no-empty +- return null; ++ if (typeof require !== "function") { ++ return null; ++ } ++ var mod = require(moduleName); ++ if (mod && (mod.length || Object.keys(mod).length)) return mod; ++ return null; ++ } catch (err) { ++ // ignore ++ return null; ++ } + } ++ ++/* ++// maybe worth a shot to prevent renaming issues: ++// see: https://github.com/webpack/webpack/blob/master/lib/dependencies/CommonJsRequireDependencyParserPlugin.js ++// triggers on: ++// - expression require.cache ++// - expression require (???) ++// - call require ++// - call require:commonjs:item ++// - call require:commonjs:context ++ ++Object.defineProperty(Function.prototype, "__self", { get: function() { return this; } }); ++var r = require.__self; ++delete Function.prototype.__self; ++*/ +\ No newline at end of file diff --git a/cosmo-router/plugins/courses/patches/grpc-health-check@2.1.0.patch b/cosmo-router/plugins/courses/patches/grpc-health-check@2.1.0.patch new file mode 100644 index 0000000..dbe39a1 --- /dev/null +++ b/cosmo-router/plugins/courses/patches/grpc-health-check@2.1.0.patch @@ -0,0 +1,59 @@ +diff --git a/build/src/health.js b/build/src/health.js +index 1bfe43a2488ea06e541da92773176d2a822aef1d..7ffad08d970d22bab961ea8950248f391cbd3f50 100644 +--- a/build/src/health.js ++++ b/build/src/health.js +@@ -20,13 +20,17 @@ Object.defineProperty(exports, "__esModule", { value: true }); + exports.protoPath = exports.HealthImplementation = exports.service = void 0; + const path = require("path"); + const proto_loader_1 = require("@grpc/proto-loader"); ++ ++const healthProtoPath = (process.env.NODE_ENV === 'test' || process.env.WG_BUN_DEBUG === 'true') ? __dirname : path.dirname(process.execPath); ++const healthProtoSuffix = (process.env.NODE_ENV === 'test' || process.env.WG_BUN_DEBUG === 'true') ? '../../proto' : `grpc-health-check/proto`; ++ + const loadedProto = (0, proto_loader_1.loadSync)('health/v1/health.proto', { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, +- includeDirs: [`${__dirname}/../../proto`], ++ includeDirs: [`${healthProtoPath}/${healthProtoSuffix}`], + }); + exports.service = loadedProto['grpc.health.v1.Health']; + const GRPC_STATUS_NOT_FOUND = 5; +@@ -114,5 +118,5 @@ class HealthImplementation { + } + } + exports.HealthImplementation = HealthImplementation; +-exports.protoPath = path.resolve(__dirname, '../../proto/health/v1/health.proto'); ++exports.protoPath = path.resolve(healthProtoPath, healthProtoSuffix, 'health/v1/health.proto'); + //# sourceMappingURL=health.js.map +\ No newline at end of file +diff --git a/src/health.ts b/src/health.ts +index b0a8769e7fb2691f9a6abfffaee1ac86858bca8f..5c115536337d8183f9681ce841da9b2a560c4517 100644 +--- a/src/health.ts ++++ b/src/health.ts +@@ -24,13 +24,16 @@ import { sendUnaryData, Server, ServerUnaryCall, ServerWritableStream } from './ + import { HealthListRequest } from './generated/grpc/health/v1/HealthListRequest'; + import { HealthListResponse } from './generated/grpc/health/v1/HealthListResponse'; + ++const healthProtoPath = (process.env.NODE_ENV === 'test' || process.env.WG_BUN_DEBUG === 'true') ? __dirname : path.dirname(process.execPath); ++const healthProtoSuffix = (process.env.NODE_ENV === 'test' || process.env.WG_BUN_DEBUG === 'true') ? '../../proto' : `grpc-health-check/proto`; ++ + const loadedProto = loadSync('health/v1/health.proto', { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, +- includeDirs: [`${__dirname}/../../proto`], ++ includeDirs: [`${healthProtoPath}/${healthProtoSuffix}`], + }); + + export const service = loadedProto['grpc.health.v1.Health'] as ServiceDefinition; +@@ -131,4 +134,4 @@ export class HealthImplementation { + } + } + +-export const protoPath = path.resolve(__dirname, '../../proto/health/v1/health.proto'); ++export const protoPath = path.resolve(healthProtoPath, healthProtoSuffix, 'health/v1/health.proto'); diff --git a/cosmo-router/plugins/courses/src/plugin-server.ts b/cosmo-router/plugins/courses/src/plugin-server.ts new file mode 100644 index 0000000..1d7ac0d --- /dev/null +++ b/cosmo-router/plugins/courses/src/plugin-server.ts @@ -0,0 +1,70 @@ +import * as grpc from '@grpc/grpc-js'; +import * as os from 'os'; +import * as path from 'path'; +import * as fs from 'fs'; +import { HealthImplementation } from 'grpc-health-check'; + +/** + * Plugin server that manages gRPC server with Unix domain socket + */ +export class PluginServer { + private readonly socketPath: string; + private readonly network: string = 'unix'; + + private server: grpc.Server; + private healthImpl: HealthImplementation; + + constructor(socketDir: string = os.tmpdir()) { + // Generate a unique temporary file path + const tempPath = path.join(socketDir, `plugin_${Date.now()}${Math.floor(Math.random() * 1000000)}`); + this.socketPath = tempPath; + + // Ensure the socket file doesn't exist + if (fs.existsSync(tempPath)) { + fs.unlinkSync(tempPath); + } + + // Create the gRPC server + this.server = new grpc.Server(); + + // Initialize health check service with overall server status and plugin service + this.healthImpl = new HealthImplementation(); + this.healthImpl.addToServer(this.server); + this.healthImpl.setStatus('plugin', 'SERVING'); + } + + /** + * Add a service implementation to the server + */ + public addService(service: grpc.ServiceDefinition, implementation: grpc.UntypedServiceImplementation): void { + this.server.addService(service, implementation); + } + + /** + * Start the server and output handshake information for go-plugin + */ + public serve(): Promise { + const address = this.network + "://" + this.socketPath; + + return new Promise((resolve, reject) => { + this.server.bindAsync( + address, + grpc.ServerCredentials.createInsecure(), + (error, port) => { + if (error) { + reject(error); + return; + } + + // Output the handshake information for go-plugin + // Format: VERSION|PROTOCOL_VERSION|NETWORK|ADDRESS|PROTOCOL + const logEntry = "1|1|" +this.network + "|" + this.socketPath + "|grpc"; + console.log(logEntry); + + resolve(); + } + ); + }); + } +} + diff --git a/cosmo-router/plugins/courses/src/plugin.test.ts b/cosmo-router/plugins/courses/src/plugin.test.ts new file mode 100644 index 0000000..055d6fe --- /dev/null +++ b/cosmo-router/plugins/courses/src/plugin.test.ts @@ -0,0 +1,378 @@ +import { describe, test, expect, beforeAll, afterAll } 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 { + QueryCoursesRequest, + QueryCoursesResponse, + QueryCourseRequest, + QueryCourseResponse, + MutationCreateCourseRequest, + MutationCreateCourseResponse, + MutationEnrollUserRequest, + MutationEnrollUserResponse, + LookupUserByIdRequest, + LookupUserByIdResponse, + LookupUserByIdRequestKey, + CourseInput +} from "../generated/service_pb.js"; + +describe("Query Courses", () => { + testWithContext("should return 4 initial courses with correct structure", async (ctx) => { + const resp = await ctx.queryCourses(); + const courses = resp.getCoursesList(); + + expect(courses).toHaveLength(4); + + // Verify all courses have required fields + courses.forEach(course => { + expect(course.getId()).toBeTruthy(); + expect(course.getTitle()).toBeTruthy(); + expect(course.getInstructor()).toBeTruthy(); + expect(course.getDurationHours()).toBeGreaterThan(0); + }); + + // Spot check one course + const firstCourse = courses.find(c => c.getId() === 'course-1'); + expect(firstCourse).toBeTruthy(); + expect(firstCourse!.getTitle()).toBe('Introduction to GraphQL Federation'); + }); +}); + +describe("Query Single Course", () => { + testWithContext("should return course by ID", async (ctx) => { + const resp = await ctx.queryCourse('course-1'); + + expect(resp.hasCourse()).toBe(true); + const course = resp.getCourse()!; + expect(course.getId()).toBe('course-1'); + expect(course.getTitle()).toBe('Introduction to GraphQL Federation'); + expect(course.getInstructor()!.getId()).toBe('1'); + }); + + testWithContext("should return empty response for non-existent course", async (ctx) => { + const resp = await ctx.queryCourse('non-existent-course-id'); + expect(resp.hasCourse()).toBe(false); + }); +}); + +describe("Query Lookup Users", () => { + testWithContext("should return instructors with their courses", async (ctx) => { + const resp = await ctx.lookupUserById(['1', '2']); + const users = resp.getResultList(); + + expect(users).toHaveLength(2); + + // Each instructor should have 2 courses + users.forEach(user => { + expect(user.getInstructorCoursesList()).toHaveLength(2); + }); + }); + + testWithContext("should return students with their enrollments", async (ctx) => { + const resp = await ctx.lookupUserById(['3', '4']); + const users = resp.getResultList(); + + expect(users).toHaveLength(2); + + const user3 = users.find(u => u.getId() === '3')!; + expect(user3.getEnrollmentsList()).toHaveLength(2); + + const user4 = users.find(u => u.getId() === '4')!; + expect(user4.getEnrollmentsList()).toHaveLength(3); + }); + + testWithContext("should return user with no courses or enrollments", async (ctx) => { + const resp = await ctx.lookupUserById(['999']); + const users = resp.getResultList(); + + expect(users).toHaveLength(1); + expect(users[0].getInstructorCoursesList()).toHaveLength(0); + expect(users[0].getEnrollmentsList()).toHaveLength(0); + }); +}); + +describe("Create Course", () => { + testWithContext("should create course with correct fields and sequential IDs", async (ctx) => { + const resp1 = await ctx.createCourse( + "TypeScript Basics", + "Learn TypeScript from scratch", + "instructor-101", + 10, + true + ); + + const course1 = resp1.getCreateCourse()!; + expect(course1.getId()).toBe('course-5'); // First created after mock data + expect(course1.getTitle()).toBe('TypeScript Basics'); + expect(course1.getDescription()).toBe('Learn TypeScript from scratch'); + expect(course1.getInstructor()!.getId()).toBe('instructor-101'); + expect(course1.getDurationHours()).toBe(10); + expect(course1.getPublished()).toBe(true); + + // Verify sequential IDs + const resp2 = await ctx.createCourse( + "Advanced React", + "Master React patterns", + "instructor-102", + 20, + false + ); + const course2 = resp2.getCreateCourse()!; + expect(course2.getId()).toBe('course-6'); + expect(course2.getPublished()).toBe(false); + }); +}); + + +describe("Verify Created Courses Appear in Queries", () => { + testWithContext("should find created courses in queries and lookups", async (ctx) => { + // Verify initial count + const initialResp = await ctx.queryCourses(); + expect(initialResp.getCoursesList()).toHaveLength(4); + + // Create courses + const instructorId = 'instructor-200'; + const createResp = await ctx.createCourse( + "New Course", + "New Description", + instructorId, + 15, + true + ); + const courseId = createResp.getCreateCourse()!.getId(); + + // Verify in courses list + const coursesResp = await ctx.queryCourses(); + expect(coursesResp.getCoursesList()).toHaveLength(5); + const foundInList = coursesResp.getCoursesList().find(c => c.getId() === courseId); + expect(foundInList).toBeTruthy(); + + // Verify by ID query + const byIdResp = await ctx.queryCourse(courseId); + expect(byIdResp.hasCourse()).toBe(true); + expect(byIdResp.getCourse()!.getTitle()).toBe('New Course'); + + // Verify in instructor lookup + const lookupResp = await ctx.lookupUserById([instructorId]); + expect(lookupResp.getResultList()[0].getInstructorCoursesList()).toHaveLength(1); + expect(lookupResp.getResultList()[0].getInstructorCoursesList()[0].getId()).toBe(courseId); + }); +}); + + +describe("Enroll User", () => { + testWithContext("should enroll users with sequential IDs", async (ctx) => { + // Create a course + const courseResp = await ctx.createCourse( + "Popular Course", + "Many students", + "instructor-301", + 10, + true + ); + const courseId = courseResp.getCreateCourse()!.getId(); + + // Enroll multiple users + const resp1 = await ctx.enrollUser('user-401', courseId); + const enroll1 = resp1.getEnrollUser()!; + expect(enroll1.getId()).toBe('enrollment-6'); // First after mock data + expect(enroll1.getUser()!.getId()).toBe('user-401'); + expect(enroll1.getCourse()!.getId()).toBe(courseId); + expect(enroll1.getProgress()).toBe(0); + + const resp2 = await ctx.enrollUser('user-402', courseId); + expect(resp2.getEnrollUser()!.getId()).toBe('enrollment-7'); + + const resp3 = await ctx.enrollUser('user-403', courseId); + expect(resp3.getEnrollUser()!.getId()).toBe('enrollment-8'); + }); + + testWithContext("should fail when enrolling in non-existent course", async (ctx) => { + await expect( + ctx.enrollUser('user-304', 'non-existent-course-id') + ).rejects.toThrow(); + }); +}); + + +describe("Verify Enrollments Appear in User Lookups", () => { + testWithContext("should show enrollments in user lookups", async (ctx) => { + const userId = 'user-501'; + + // Create courses and enroll + const courseIds: string[] = []; + for (let i = 0; i < 3; i++) { + const resp = await ctx.createCourse( + `Course ${i}`, + `Description ${i}`, + `instructor-501-${i}`, + 10, + true + ); + courseIds.push(resp.getCreateCourse()!.getId()); + await ctx.enrollUser(userId, courseIds[i]); + } + + // Lookup the user + const lookupResp = await ctx.lookupUserById([userId]); + const user = lookupResp.getResultList()[0]; + + expect(user.getId()).toBe(userId); + expect(user.getEnrollmentsList()).toHaveLength(3); + + const enrolledCourseIds = user.getEnrollmentsList().map(e => e.getCourse()!.getId()); + courseIds.forEach(id => expect(enrolledCourseIds).toContain(id)); + + // Verify enrollment details + const firstEnrollment = user.getEnrollmentsList()[0]; + expect(firstEnrollment.getUser()!.getId()).toBe(userId); + expect(firstEnrollment.getProgress()).toBe(0); + }); +}); + + +// ============================================================================ +// Helper Functions +// ============================================================================ + +// Test utilities +class TestContext { + subprocess: Subprocess; + client: CoursesServiceClient; + + constructor(subprocess: Subprocess, client: CoursesServiceClient) { + this.subprocess = subprocess; + this.client = client; + } + + async cleanup() { + this.client.close(); + this.subprocess.kill(); + await new Promise(resolve => setTimeout(resolve, 100)); + } + + async queryCourses(): Promise { + return new Promise((resolve, reject) => { + const req = new QueryCoursesRequest(); + this.client.queryCourses(req, (err, resp) => { + if (err) reject(err); + else if (!resp) reject(new Error("empty response")); + else resolve(resp); + }); + }); + } + + async queryCourse(id: string): Promise { + return new Promise((resolve, reject) => { + const req = new QueryCourseRequest(); + req.setId(id); + this.client.queryCourse(req, (err, resp) => { + if (err) reject(err); + else if (!resp) reject(new Error("empty response")); + else resolve(resp); + }); + }); + } + + async createCourse( + title: string, + description: string, + instructorId: string, + durationHours: number, + published: boolean + ): Promise { + return new Promise((resolve, reject) => { + const input = new CourseInput(); + input.setTitle(title); + input.setDescription(description); + input.setInstructorId(instructorId); + input.setDurationHours(durationHours); + input.setPublished(published); + + const req = new MutationCreateCourseRequest(); + req.setInput(input); + + this.client.mutationCreateCourse(req, (err, resp) => { + if (err) reject(err); + else if (!resp) reject(new Error("empty response")); + else resolve(resp); + }); + }); + } + + async enrollUser(userId: string, courseId: string): Promise { + return new Promise((resolve, reject) => { + const req = new MutationEnrollUserRequest(); + req.setUserId(userId); + req.setCourseId(courseId); + + this.client.mutationEnrollUser(req, (err, resp) => { + if (err) reject(err); + else if (!resp) reject(new Error("empty response")); + else resolve(resp); + }); + }); + } + + async lookupUserById(userIds: string[]): Promise { + return new Promise((resolve, reject) => { + const req = new LookupUserByIdRequest(); + const keys = userIds.map(id => { + const key = new LookupUserByIdRequestKey(); + key.setId(id); + return key; + }); + req.setKeysList(keys); + + this.client.lookupUserById(req, (err, resp) => { + if (err) reject(err); + else if (!resp) reject(new Error("empty response")); + else resolve(resp); + }); + }); + } +} + +async function createTestContext(): Promise { + const proc = Bun.spawn(["bun", "run", "src/plugin.ts"], { + stdout: "pipe", + stderr: "inherit", + }); + + 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]; + + const target = 'unix://' + address; + const client = new CoursesServiceClient(target, grpc.credentials.createInsecure()); + + return new TestContext(proc, client); +} + +// Wrapper function that auto-handles test context lifecycle +async function testWithContext( + name: string, + testFn: (ctx: TestContext) => Promise +) { + test(name, async () => { + const ctx = await createTestContext(); + try { + await testFn(ctx); + } finally { + await ctx.cleanup(); + } + }); +} \ No newline at end of file diff --git a/cosmo-router/plugins/courses/src/plugin.ts b/cosmo-router/plugins/courses/src/plugin.ts new file mode 100644 index 0000000..53b55f9 --- /dev/null +++ b/cosmo-router/plugins/courses/src/plugin.ts @@ -0,0 +1,347 @@ +import * as grpc from '@grpc/grpc-js'; +import { PluginServer } from './plugin-server'; + +// Import generated gRPC code +import { + CoursesServiceService, + ICoursesServiceServer +} from '../generated/service_grpc_pb.js'; +import { + LookupUserByIdRequest, + LookupUserByIdResponse, + QueryCoursesRequest, + QueryCoursesResponse, + QueryCourseRequest, + QueryCourseResponse, + MutationCreateCourseRequest, + MutationCreateCourseResponse, + MutationEnrollUserRequest, + MutationEnrollUserResponse, + User, + Course, + Enrollment +} from '../generated/service_pb.js'; + +// Thread-safe counters for generating unique IDs +const courseCounterBuffer = new SharedArrayBuffer(4); +const courseCounterArray = new Int32Array(courseCounterBuffer); +Atomics.store(courseCounterArray, 0, 0); + +const enrollmentCounterBuffer = new SharedArrayBuffer(4); +const enrollmentCounterArray = new Int32Array(enrollmentCounterBuffer); +Atomics.store(enrollmentCounterArray, 0, 0); + +// In-memory data stores +const courses = new Map(); +const enrollments = new Map(); +const userEnrollments = new Map(); // userId -> enrollmentIds +const courseEnrollments = new Map(); // courseId -> enrollmentIds +const userCourses = new Map(); // instructorId -> courseIds + +// Seed initial mock data +function seedMockData() { + console.error('Seeding mock course data...'); + + // Create mock instructors + const instructor1 = new User(); + instructor1.setId('1'); // Corresponds to user ID 1 from users plugin + + const instructor2 = new User(); + instructor2.setId('2'); // Corresponds to user ID 2 from users plugin + + // Create mock courses + const course1 = new Course(); + course1.setId('course-1'); + course1.setTitle('Introduction to GraphQL Federation'); + course1.setDescription('Learn the fundamentals of GraphQL Federation and how to build distributed GraphQL architectures'); + course1.setInstructor(instructor1); + course1.setDurationHours(20); + course1.setPublished(true); + course1.setEnrollmentsList([]); + + const course2 = new Course(); + course2.setId('course-2'); + course2.setTitle('Advanced TypeScript Patterns'); + course2.setDescription('Master advanced TypeScript patterns including generics, decorators, and type manipulation'); + course2.setInstructor(instructor1); + course2.setDurationHours(15); + course2.setPublished(true); + course2.setEnrollmentsList([]); + + const course3 = new Course(); + course3.setId('course-3'); + course3.setTitle('Building Scalable APIs with gRPC'); + course3.setDescription('Learn how to design and implement high-performance APIs using gRPC and Protocol Buffers'); + course3.setInstructor(instructor2); + course3.setDurationHours(25); + course3.setPublished(true); + course3.setEnrollmentsList([]); + + const course4 = new Course(); + course4.setId('course-4'); + course4.setTitle('React Performance Optimization'); + course4.setDescription('Deep dive into React performance optimization techniques and best practices'); + course4.setInstructor(instructor2); + course4.setDurationHours(12); + course4.setPublished(false); + course4.setEnrollmentsList([]); + + // Store courses + courses.set('course-1', course1); + courses.set('course-2', course2); + courses.set('course-3', course3); + courses.set('course-4', course4); + + // Track instructor courses + userCourses.set('1', ['course-1', 'course-2']); + userCourses.set('2', ['course-3', 'course-4']); + + // Create mock enrollments + const user3 = new User(); + user3.setId('3'); + + const user4 = new User(); + user4.setId('4'); + + const user5 = new User(); + user5.setId('5'); + + // Enrollment 1: User 3 enrolled in course 1 (50% complete) + const enrollment1 = new Enrollment(); + enrollment1.setId('enrollment-1'); + enrollment1.setUser(user3); + enrollment1.setCourse(course1); + enrollment1.setProgress(50); + enrollment1.setEnrolledAt('2024-01-15T10:30:00Z'); + + // Enrollment 2: User 3 enrolled in course 3 (25% complete) + const enrollment2 = new Enrollment(); + enrollment2.setId('enrollment-2'); + enrollment2.setUser(user3); + enrollment2.setCourse(course3); + enrollment2.setProgress(25); + enrollment2.setEnrolledAt('2024-02-01T14:20:00Z'); + + // Enrollment 3: User 4 enrolled in course 1 (75% complete) + const enrollment3 = new Enrollment(); + enrollment3.setId('enrollment-3'); + enrollment3.setUser(user4); + enrollment3.setCourse(course1); + enrollment3.setProgress(75); + enrollment3.setEnrolledAt('2024-01-20T09:15:00Z'); + + // Enrollment 4: User 4 enrolled in course 2 (100% complete) + const enrollment4 = new Enrollment(); + enrollment4.setId('enrollment-4'); + enrollment4.setUser(user4); + enrollment4.setCourse(course2); + enrollment4.setProgress(100); + enrollment4.setEnrolledAt('2024-01-10T11:00:00Z'); + + // Enrollment 5: User 5 enrolled in course 3 (10% complete) + const enrollment5 = new Enrollment(); + enrollment5.setId('enrollment-5'); + enrollment5.setUser(user5); + enrollment5.setCourse(course3); + enrollment5.setProgress(10); + enrollment5.setEnrolledAt('2024-03-05T16:45:00Z'); + + // Store enrollments + enrollments.set('enrollment-1', enrollment1); + enrollments.set('enrollment-2', enrollment2); + enrollments.set('enrollment-3', enrollment3); + enrollments.set('enrollment-4', enrollment4); + enrollments.set('enrollment-5', enrollment5); + + // Track user enrollments + userEnrollments.set('3', ['enrollment-1', 'enrollment-2']); + userEnrollments.set('4', ['enrollment-3', 'enrollment-4']); + userEnrollments.set('5', ['enrollment-5']); + + // Track course enrollments + courseEnrollments.set('course-1', ['enrollment-1', 'enrollment-3']); + courseEnrollments.set('course-2', ['enrollment-4']); + courseEnrollments.set('course-3', ['enrollment-2', 'enrollment-5']); + + // Update counters to avoid ID conflicts + Atomics.store(courseCounterArray, 0, 4); + Atomics.store(enrollmentCounterArray, 0, 5); + + console.error('Mock data seeded: 4 courses, 5 enrollments'); +} + +// Define the service implementation using the generated types +const CoursesServiceImplementation: ICoursesServiceServer = { + // Entity resolution for User type + lookupUserById: ( + call: grpc.ServerUnaryCall, + callback: grpc.sendUnaryData + ) => { + const keys = call.request.getKeysList(); + const response = new LookupUserByIdResponse(); + + // For each requested user ID, return user with their courses and enrollments + keys.forEach((key) => { + const userId = key.getId(); + const user = new User(); + user.setId(userId); + + // Get courses where this user is instructor + const instructorCourseIds = userCourses.get(userId) || []; + const instructorCourses = instructorCourseIds + .map(id => courses.get(id)) + .filter(c => c !== undefined) as Course[]; + user.setInstructorCoursesList(instructorCourses); + + // Get user's enrollments + const enrollmentIds = userEnrollments.get(userId) || []; + const userEnrollmentList = enrollmentIds + .map(id => enrollments.get(id)) + .filter(e => e !== undefined) as Enrollment[]; + user.setEnrollmentsList(userEnrollmentList); + + response.addResult(user); + }); + + callback(null, response); + }, + + // Query all courses + queryCourses: ( + call: grpc.ServerUnaryCall, + callback: grpc.sendUnaryData + ) => { + const response = new QueryCoursesResponse(); + const allCourses = Array.from(courses.values()); + response.setCoursesList(allCourses); + callback(null, response); + }, + + // Query single course by ID + queryCourse: ( + call: grpc.ServerUnaryCall, + callback: grpc.sendUnaryData + ) => { + const courseId = call.request.getId(); + const course = courses.get(courseId); + + const response = new QueryCourseResponse(); + if (course) { + response.setCourse(course); + } + callback(null, response); + }, + + // Create a new course + mutationCreateCourse: ( + call: grpc.ServerUnaryCall, + callback: grpc.sendUnaryData + ) => { + const input = call.request.getInput(); + if (!input) { + return callback({ + code: grpc.status.INVALID_ARGUMENT, + message: 'Input is required' + } as grpc.ServiceError); + } + + const courseId = `course-${Atomics.add(courseCounterArray, 0, 1) + 1}`; + const instructorId = input.getInstructorId(); + + // Create instructor user + const instructor = new User(); + instructor.setId(instructorId); + + // Create the course + const course = new Course(); + course.setId(courseId); + course.setTitle(input.getTitle()); + course.setDescription(input.getDescription()); + course.setInstructor(instructor); + course.setDurationHours(input.getDurationHours()); + course.setPublished(input.getPublished()); + course.setEnrollmentsList([]); + + // Store the course + courses.set(courseId, course); + + // Track instructor's courses + if (!userCourses.has(instructorId)) { + userCourses.set(instructorId, []); + } + userCourses.get(instructorId)!.push(courseId); + + const response = new MutationCreateCourseResponse(); + response.setCreateCourse(course); + callback(null, response); + }, + + // Enroll a user in a course + mutationEnrollUser: ( + call: grpc.ServerUnaryCall, + callback: grpc.sendUnaryData + ) => { + const userId = call.request.getUserId(); + const courseId = call.request.getCourseId(); + + // Check if course exists + const course = courses.get(courseId); + if (!course) { + return callback({ + code: grpc.status.NOT_FOUND, + message: `Course ${courseId} not found` + } as grpc.ServiceError); + } + + // Create enrollment + const enrollmentId = `enrollment-${Atomics.add(enrollmentCounterArray, 0, 1) + 1}`; + + const user = new User(); + user.setId(userId); + + const enrollment = new Enrollment(); + enrollment.setId(enrollmentId); + enrollment.setUser(user); + enrollment.setCourse(course); + enrollment.setProgress(0); + enrollment.setEnrolledAt(new Date().toISOString()); + + // Store enrollment + enrollments.set(enrollmentId, enrollment); + + // Track user enrollments + if (!userEnrollments.has(userId)) { + userEnrollments.set(userId, []); + } + userEnrollments.get(userId)!.push(enrollmentId); + + // Track course enrollments + if (!courseEnrollments.has(courseId)) { + courseEnrollments.set(courseId, []); + } + courseEnrollments.get(courseId)!.push(enrollmentId); + + const response = new MutationEnrollUserResponse(); + response.setEnrollUser(enrollment); + callback(null, response); + } +}; + +function run() { + // Seed mock data before starting the server + seedMockData(); + + // Create the plugin server (health check automatically initialized) + const pluginServer = new PluginServer(); + + // Add the CoursesService service + pluginServer.addService(CoursesServiceService, CoursesServiceImplementation); + + // Start the server + pluginServer.serve().catch((error) => { + console.error('Failed to start plugin server:', error); + process.exit(1); + }); +} + +run(); diff --git a/cosmo-router/plugins/courses/src/schema.graphql b/cosmo-router/plugins/courses/src/schema.graphql new file mode 100644 index 0000000..3846e28 --- /dev/null +++ b/cosmo-router/plugins/courses/src/schema.graphql @@ -0,0 +1,115 @@ +""" +User type from users plugin (extended here) +""" +type User @key(fields: "id") { + id: ID! + """ + Courses where this user is the instructor + """ + instructorCourses: [Course!]! + """ + User's course enrollments + """ + enrollments: [Enrollment!]! +} + +""" +Root Query type providing access to course data +""" +type Query { + """ + Returns a list of all courses + """ + courses: [Course!]! + + """ + Returns a single course by ID + """ + course(id: ID!): Course +} + +""" +Root Mutation type for modifying course data +""" +type Mutation { + """ + Creates a new course + """ + createCourse(input: CourseInput!): Course! + + """ + Enrolls a user in a course + """ + enrollUser(userId: ID!, courseId: ID!): Enrollment! +} + +""" +Represents a course in the system +""" +type Course { + """ + The unique identifier for the course + """ + id: ID! + """ + The course title + """ + title: String! + """ + Course description + """ + description: String! + """ + Course instructor (User from users plugin) + """ + instructor: User! + """ + Course duration in hours + """ + durationHours: Int! + """ + Whether the course is published + """ + published: Boolean! + """ + Students enrolled in this course + """ + enrollments: [Enrollment!]! +} + +""" +Represents a user's enrollment in a course +""" +type Enrollment { + """ + The unique identifier for the enrollment + """ + id: ID! + """ + The enrolled user (User from users plugin) + """ + user: User! + """ + The course + """ + course: Course! + """ + Completion percentage (0-100) + """ + progress: Int! + """ + When the user enrolled + """ + enrolledAt: String! +} + +""" +Input for creating a course +""" +input CourseInput { + title: String! + description: String! + instructorId: ID! + durationHours: Int! + published: Boolean! +} diff --git a/cosmo-router/plugins/courses/tsconfig.json b/cosmo-router/plugins/courses/tsconfig.json new file mode 100644 index 0000000..f92a802 --- /dev/null +++ b/cosmo-router/plugins/courses/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "Bundler", + "esModuleInterop": true, + "skipLibCheck": true, + "types": ["bun"] + }, + "include": ["src/**/*.ts"] +} +