diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce0ea62..92ae3b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: - name: Download Fern run: npm install -g fern-api - - name: Release Node.js & Java SDK, Postman, and OpenAPI + - name: Generate SDKs, Postman, and OpenAPI env: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -38,4 +38,9 @@ jobs: POSTMAN_API_KEY: ${{ secrets.POSTMAN_API_KEY }} POSTMAN_WORKSPACE_ID: ${{ secrets.POSTMAN_WORKSPACE_ID }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} - run: fern generate --group external --version ${{ github.ref_name }} --log-level debug + run: fern generate --api english --group external --version ${{ github.ref_name }} --log-level debug + + - name: Generate Docs + env: + FERN_TOKEN: ${{ secrets.FERN_TOKEN }} + run: fern generate --docs diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index cac0e10..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "editor.formatOnSave": true -} \ No newline at end of file diff --git a/README.md b/README.md index 4b39766..9db3467 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,22 @@ # CodeCombat API -See the [API documentation](https://codecombat.mintlify.app/introduction), the [Node.JS SDK](https://github.com/codecombat/codecombat-node), the [Java SDK](https://github.com/codecombat/codecombat-java), and the [Postman collection](https://github.com/codecombat/codecombat-postman). +Tagging a release on this repository will update the following repos: -## Repositories +- [Node.js SDK](https://github.com/codecombat/codecombat-node) +- [Python SDK](https://github.com/codecombat/codecombat-python) +- [Java SDK](https://github.com/codecombat/codecombat-java) +- [Go SDK](https://github.com/codecombat/codecombat-go) +- [OpenAPI spec](https://github.com/codecombat/codecombat-openapi) +- [Postman collection](https://github.com/codecombat/codecombat-postman) -This repository is the source. Tagging a release on this repository will update the destination repos: - -- [Node.js SDK repo](https://github.com/codecombat/codecombat-node) -- [API docs repo](https://github.com/codecombat/docs) -- [OpenAPI spec repo](https://github.com/codecombat/codecombat-openapi) -- [Postman collection repo](https://github.com/codecombat/codecombat-postman) -- (_Coming soon_) [Java SDK repo](https://github.com/codecombat/codecombat-java) -- _More SDKs to come..._ +and the CodeCombat [API docs](https://api-docs.codecombat.com) ## What is in this repository? This repository contains -- CodeCombat's Fern API Definition which lives in the [definition](./fern/api/definition/) folder -- Generators (see [generators.yml](./fern/api/generators.yml)) +- CodeCombat's Fern API Definition in English and Simplified Chinese which lives in the [definition](./fern/) folder +- Generators (see [generators.yml](./fern/english/generators.yml)) ## What is in the API Definition? diff --git a/fern/api/definition/api.yml b/fern/api/definition/api.yml deleted file mode 100644 index 6704bf8..0000000 --- a/fern/api/definition/api.yml +++ /dev/null @@ -1,6 +0,0 @@ -name: api -display-name: CodeCombat API -auth: basic -environments: - Production: https://codecombat.com/api -default-environment: Production \ No newline at end of file diff --git a/fern/api/definition/clans.yml b/fern/api/definition/clans.yml deleted file mode 100644 index 92a9d6d..0000000 --- a/fern/api/definition/clans.yml +++ /dev/null @@ -1,41 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json - -imports: - commons: commons.yml - -service: - display-name: Clans Service - auth: true - base-path: /clan/{handle}/members - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - endpoints: - upsertClan: - display-name: Upsert User Into Clan - path: "" - method: PUT - docs: Upserts a user into the clan. - request: - name: UpsertClanRequest - body: - properties: - userId: - docs: The `_id` or `slug` of the user to add to the clan. - type: string - response: ClanResponse - -types: - ClanResponse: - docs: Subset of properties listed here - properties: - _id: optional - name: optional - displayName: optional - members: optional> - ownerID: optional - description: optional - type: optional - kind: optional - metadata: optional> diff --git a/fern/api/definition/commons.yml b/fern/api/definition/commons.yml deleted file mode 100644 index 7ff061e..0000000 --- a/fern/api/definition/commons.yml +++ /dev/null @@ -1,82 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json - -types: - UserResponse: - docs: Subset of properties listed here - properties: - _id: optional - email: optional - name: optional - slug: optional - role: optional - stats: optional - oAuthIdentities: optional> - subscription: optional - license: optional - - UserStats: - properties: - gamesCompleted: optional - concepts: optional> - playTime: - docs: Included only when specifically requested on the endpoint - type: optional - - AuthIdentity: - properties: - provider: optional - id: optional - - Subscription: - properties: - ends: optional - active: optional - - License: - properties: - ends: optional - active: optional - - objectIdString: string - - roleString: - docs: Usually either 'teacher' or 'student' - type: string - - datetimeString: string - - ClassroomResponseWithCode: - docs: Subset of properties listed here - properties: - _id: optional - name: optional - members: optional> - ownerID: optional - description: optional - code: optional - codeCamel: optional - courses: optional> - clanId: optional - - Course: - properties: - _id: optional - levels: optional>> - enrolled: optional> - instance_id: optional - - ClassroomResponse: - docs: Subset of properties listed here - properties: - _id: optional - name: - type: optional - docs: The name of the classroom - members: - type: optional> - docs: List of _ids of the student members of the classroom - ownerID: - type: optional - docs: The _id of the teacher owner of the classroom. - description: optional - courses: optional> diff --git a/fern/api/definition/stats.yml b/fern/api/definition/stats.yml deleted file mode 100644 index 4092c40..0000000 --- a/fern/api/definition/stats.yml +++ /dev/null @@ -1,57 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json - -service: - display-name: StatsService - auth: true - base-path: / - endpoints: - getPlaytimeStats: - display-name: Get Playtime Stats - path: /playtime-stats - method: GET - docs: Returns the playtime stats - request: - name: GetPlaytimeStats - query-parameters: - startDate: - docs: Earliest an included user was created - type: optional - endDate: - docs: Latest an included user was created - type: optional - country: - docs: Filter by country string - type: optional - response: PlaytimeStatsResponse - - getLicenseStats: - display-name: Get License Stats - path: /license-stats - method: GET - docs: Returns the license stats - response: LicenseStatsResponse - -types: - PlaytimeStatsResponse: - properties: - playTime: - docs: Total play time in seconds - type: optional - gamesPlayed: - docs: Number of levels played - type: optional - - LicenseStatsResponse: - properties: - licenseDaysGranted: - docs: Total number of license days granted - type: optional - licenseDaysUsed: - docs: Number of license days used - type: optional - licenseDaysRemaining: - docs: Number of license days remaining - type: optional - activeLicenses: - docs: Number of active/valid licenses - type: optional diff --git a/fern/api/definition/users.yml b/fern/api/definition/users.yml deleted file mode 100644 index 7dc79f1..0000000 --- a/fern/api/definition/users.yml +++ /dev/null @@ -1,326 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json - -imports: - commons: commons.yml - -service: - display-name: UsersService - auth: true - base-path: / - endpoints: - create: - display-name: Create User - path: /users - method: POST - docs: | - Creates a `User`. - #### Example - ```javascript - url = 'https://codecombat.com/api/users' - json = { email: 'an@email.com', name: 'Some Username', role: 'student' } - request.post({ url, json, auth }) - ``` - request: - name: CreateUserRequest - body: - properties: - name: string - email: string - role: - docs: >- - A `"student"` or `"teacher"`. If unset, a home user will be - created, unable to join classrooms. - type: optional - preferredLanguage: optional - heroConfig: optional - birthday: optional - - get: - display-name: Get User - path: /users/{handle} - method: GET - docs: Returns a `User`. - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: GetUserRequest - query-parameters: - includePlayTime: - docs: Set to non-empty string to include stats.playTime in response - type: optional - response: commons.UserResponse - - update: - display-name: Update User - path: /users/{handle} - method: PUT - docs: Modify name of a `User` - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: UpdateUserRequest - body: - properties: - name: - docs: Set to new name string - type: string - birthday: - docs: Set the birthday - type: optional - response: commons.UserResponse - - getClassrooms: - display-name: Get Classrooms By User - path: /users/{handle}/classrooms - method: GET - docs: >- - Returns a list of `Classrooms` this user is in (if a student) or owns - (if a teacher). - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: GetClassroomsRequest - query-parameters: - retMemberLimit: - docs: limit the return number of members for each classroom - type: optional - response: list - - getHero: - display-name: Get User Hero - path: /users/{handle}/hero-config - method: PUT - docs: Set the user's hero. - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: GetHeroRequest - body: - properties: - thangType: optional - response: commons.UserResponse - - setAceConfig: - path: /users/{handle}/ace-config - method: PUT - docs: >- - Set the user's aceConfig (the settings for the in-game Ace code editor), - such as whether to enable autocomplete. - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: SetAceConfig - body: - properties: - liveCompletion: - docs: >- - controls whether autocompletion snippets show up, the default - value is true - type: optional - behaviors: - docs: >- - controls whether things like automatic parenthesis and quote - completion happens, the default value is false - type: optional - language: - docs: >- - only for home users, should be one of ["python", "javascript", - "cpp", "lua", "coffeescript"] right now - type: optional - response: commons.UserResponse - - addOAuthIdentity: - display-name: Add OAuth2 Identity - path: /users/{handle}/o-auth-identities - method: POST - docs: > - Adds an OAuth2 identity to the user, so that they can be logged in with - that identity. You need to send the OAuth code or the access token to - this endpoint. - 1. If no access token is provided, it will use your OAuth2 token URL to - exchange the given code for an access token. - 1. Then it will use the access token (given by you, or received from - step 1) to look up the user on your service using the lookup URL, and - expects a JSON object in response with an `id` property. - 1. It will then save that user `id` to the user in our db as a new - OAuthIdentity. - #### Example - ```javascript - url = `https://codecombat.com/api/users/${userID}/o-auth-identities` - OAUTH_PROVIDER_ID = 'xyz' - json = { provider: OAUTH_PROVIDER_ID, accessToken: '1234' } - request.post({ url, json, auth}, (err, res) => { - console.log(res.body.oAuthIdentities) // [ { provider: 'xyx', id: 'abcd' } ] - }) - ``` - In this example, we call your lookup URL (let's say, - `https://oauth.provider/user?t=<%= accessToken %>`) with the access - token (`1234`). The lookup URL returns `{ id: 'abcd' }` in this case, - which we save to the user in our db. - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: AddOAuthIdentityRequest - body: - properties: - provider: - docs: Your OAuth Provider ID. - type: string - accessToken: - docs: >- - Will be passed through your lookup URL to get the user ID. - Required if no `code`. - type: optional - code: - docs: >- - Will be passed to the OAuth token endpoint to get a token. - Required if no `accessToken`. - type: optional - response: commons.UserResponse - - updateSubscription: - path: /users/{handle}/subscription - method: PUT - docs: | - Grants a user premium access to the "Home" version up to a certain time. - #### Example - ```javascript - url = `https://codecombat.com/api/users/${userID}/subscription` - json = { ends: new Date('2017-01-01').toISOString() } - request.put({ url, json, auth }, (err, res) => { - console.log(res.body.subscription) // { ends: '2017-01-01T00:00:00.000Z', active: true } - }) - ``` - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: UpdateSubscriptionRequest - body: - properties: - ends: datetime - response: commons.UserResponse - - shortenSubscription: - display-name: Shorten User Subscription - path: /users/{handle}/shorten-subscription - method: PUT - docs: > - If the user already has a premium access up to a certain time, this - shortens/revokes his/her premium access. - If the ends is less than or equal to the current time, it revokes the - subscription and sets the end date to be the current time, else it just - shortens the subscription. - #### Example - ```javascript - url = `https://codecombat.com/api/users/${userID}/shorten-subscription` - json = { ends: new Date().toISOString() } - request.put({ url, json, auth }, (err, res) => { - console.log(res.body.subscription.active) // false - }) - ``` - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: ShortenSubscriptionRequest - body: - properties: - ends: datetime - response: commons.UserResponse - - grantLicense: - display-name: Grant User License - path: /users/{handle}/license - method: PUT - docs: | - Grants a user access to the "Classroom" version up to a certain time. - Sets their role to "student". - #### Example - ```javascript - url = `https://codecombat.com/api/users/${userID}/license` - json = { ends: new Date('2017-01-01').toISOString() } - request.put({ url, json, auth }, (err, res) => { - console.log(res.body.license) // { ends: '2017-01-01T00:00:00.000Z', active: true } - }) - ``` - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: GrantLicenseRequest - body: - properties: - ends: datetime - response: commons.UserResponse - - shortenLicense: - display-name: Shorten User License - path: /users/{handle}/shorten-license - method: PUT - docs: > - If the user already has access to the "Classroom" version up to a - certain time, this shortens/revokes his/her access. - If the ends is less than or equal to the current time, it revokes the - enrollment and sets the end date to be the current time, else it just - shortens the enrollment. - #### Example - ```javascript - url = `https://codecombat.com/api/users/${userID}/shorten-license` - json = { ends: new Date().toISOString() } - request.put({ url, json, auth }, (err, res) => { - console.log(res.body.license.active) // false - }) - ``` - path-parameters: - handle: - docs: The document's `_id` or `slug`. - type: string - request: - name: ShortenLicenseRequest - body: - properties: - ends: datetime - response: commons.UserResponse - - #TODO feels like a chain of endpoint to endpoint actions - findUser: - display-name: Search for User - path: /user-lookup/{property}/{value} - method: GET - docs: Redirects to `/users/{handle}` given a unique, identifying property - path-parameters: - property: - docs: The property to lookup by. May either be `"israel-id"` or `"name"`. - type: string - value: - docs: The value to be looked up. - type: string - -types: - UserRole: - docs: >- - A `"student"` or `"teacher"`. If unset, a home user will be created, - unable to join classrooms. - enum: - - student - - teacher - - HeroConfig: - properties: - thangType: optional diff --git a/fern/apis/chinese/definition/__package__.yml b/fern/apis/chinese/definition/__package__.yml new file mode 100644 index 0000000..8abfb27 --- /dev/null +++ b/fern/apis/chinese/definition/__package__.yml @@ -0,0 +1,246 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +types: + UsersCreateRequestRole: + docs: | + `"student"` 或者 `"teacher"` + enum: + - name: student + value: student + - name: teacher + value: teacher + + UsersCreateRequestHeroConfig: + properties: + thangType: + type: optional + + ClassroomsCreateRequestAceConfig: + properties: + language: + docs: 适合教室的编程语言 + type: optional + + ClassroomsGetMembersStatsResponseItem: + properties: + _id: + type: optional + stats: + type: optional + + ClassroomsGetMembersStatsResponseItemStats: + properties: + gamesCompleted: + type: optional + playtime: + docs: 游戏时间(秒) + type: optional + + roleString: + type: string + docs: 通常这是指`"teacher"`("老师")或者`"student"`("学生") + + datetimeString: + type: string + + objectIdString: + type: string + + UserResponse: + docs: 这里所列类别的子选项 + properties: + _id: + type: optional + email: + type: optional + name: + type: optional + slug: + type: optional + role: + type: optional + stats: + type: optional + oAuthIdentities: + type: optional> + subscription: + type: optional + license: + type: optional + + UserResponseStats: + properties: + gamesCompleted: + type: optional + concepts: + type: optional> + playTime: + docs: 只有在终点询问的时候才包含进去 + type: optional + + UserResponseOAuthIdentitiesItem: + properties: + provider: + type: optional + id: + type: optional + + UserResponseSubscription: + properties: + ends: + type: optional + active: + type: optional + + UserResponseLicense: + properties: + ends: + type: optional + active: + type: optional + + ClassroomResponse: + docs: 这里列出特征的子集 + properties: + _id: + type: optional + name: + type: optional + members: + type: optional> + ownerID: + type: optional + description: + type: optional + courses: + type: optional> + + ClassroomResponseCoursesItem: + properties: + _id: + type: optional + levels: + type: optional>> + enrolled: + type: optional> + instance_id: + type: optional + + ClassroomResponseWithCode: + docs: 这里列出属性的子集 + properties: + _id: + type: optional + name: + type: optional + members: + type: optional> + ownerID: + type: optional + description: + type: optional + code: + type: optional + codeCamel: + type: optional + courses: + type: optional> + clanId: + type: optional + + ClassroomResponseWithCodeCoursesItem: + properties: + _id: + type: optional + levels: + type: optional>> + enrolled: + type: optional> + instance_id: + type: optional + + PlaytimeStatsResponse: + properties: + playTime: + docs: 以秒统计游戏使用时间 + type: optional + gamesPlayed: + docs: 所玩的级别 + type: optional + + LicenseStatsResponse: + properties: + licenseDaysGranted: + docs: 授权订阅天数总数量 + type: optional + licenseDaysUsed: + docs: 订阅许可天数已使用数量 + type: optional + licenseDaysRemaining: + docs: 订阅许可天数剩余数量 + type: optional + activeLicenses: + docs: 活跃/有效订阅许可数量 + type: optional + + LevelSessionResponse: + properties: + state: + type: optional + level: + type: optional + levelID: + docs: 关卡名,如 wakka-maul + type: optional + creator: + type: optional + playtime: + docs: 以秒为单位游戏所玩时间 + type: optional + changed: + type: optional + created: + type: optional + dateFirstCompleted: + type: optional + submitted: + docs: 对于竞技场来说,这一关是否已经加入进阶关卡。 + type: optional + published: + docs: 分享的项目。这些项目是否已经分享给了同学。 + type: optional + + LevelSessionResponseState: + properties: + complete: + type: optional + + LevelSessionResponseLevel: + properties: + original: + docs: 这个`id`代表这个水平 + type: optional + + ClanResponse: + docs: 这里列出特征的子集 + properties: + _id: + type: optional + name: + type: optional + displayName: + type: optional + members: + type: optional> + ownerID: + type: optional + description: + type: optional + type: + type: optional + kind: + type: optional + metadata: + type: optional> + +errors: {} diff --git a/fern/apis/chinese/definition/api.yml b/fern/apis/chinese/definition/api.yml new file mode 100644 index 0000000..ecb9813 --- /dev/null +++ b/fern/apis/chinese/definition/api.yml @@ -0,0 +1,10 @@ +imports: + root: __package__.yml +name: api +display-name: CodeCombat开发者接口 +error-discrimination: + strategy: status-code +auth: basic +default-environment: default +environments: + default: https://koudashijie.com/api diff --git a/fern/apis/chinese/definition/auth.yml b/fern/apis/chinese/definition/auth.yml new file mode 100644 index 0000000..8586183 --- /dev/null +++ b/fern/apis/chinese/definition/auth.yml @@ -0,0 +1,41 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + loginOauth: + path: /auth/login-o-auth + method: GET + auth: true + docs: > + 用 [user](#users) 登陆. + 在这个示例中,我们用准入指令(access token)(`1234`)来call你的查找的URL(lookup URL)(比方说,是 + `https://oauth.provider/user?t=<%=accessToken%>` 。在这个例子中,返回的查找URL(lookup + URL)是 `{ id: 'abcd' + }`。我们将数据库中储存的OAuthIdentity用户信息与这个`id`匹配。如果匹配成功,用户即可登录并被引导到主页。 + display-name: 登录用户 + request: + name: LoginOauthRequest + query-parameters: + provider: + docs: 你的授权(oAuth)提供者ID + type: string + accessToken: + docs: 通过传输你的查询网址以便于拿到用户ID。如果没有“代码”这一环节是必须项。 + type: optional + code: + docs: >- + 通过传输到授权指令的终端以便于拿到指令。如果没有“代码”这一环节是必须项。如果没有`accessToken`(“访问指令”)这一环节是必须项。 + type: optional + redirect: + docs: 登陆成功后,用户导航路径会被清除。 + type: optional + errorRedirect: + docs: >- + 如果错误出现,将用户重置于这个网址,请求参数至少需要`code`(“代码”)、`errorName`(“错误名称”)和`message`(“消息”)等字段。 + type: optional + errors: [] diff --git a/fern/apis/chinese/definition/clans.yml b/fern/apis/chinese/definition/clans.yml new file mode 100644 index 0000000..22f977b --- /dev/null +++ b/fern/apis/chinese/definition/clans.yml @@ -0,0 +1,30 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + upsertMember: + path: /clan/{handle}/members + method: PUT + auth: true + docs: 在部落中加入一个用户 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 将用户添加到部落 + request: + name: ClansUpsertMemberRequest + body: + properties: + userId: + type: string + docs: 使用字符串 `_id` 或 `slug` 来识别要加入部落的用户. + response: + docs: 返回加入了新成员的部落 + type: root.ClanResponse + errors: [] diff --git a/fern/apis/chinese/definition/classrooms.yml b/fern/apis/chinese/definition/classrooms.yml new file mode 100644 index 0000000..b562ef5 --- /dev/null +++ b/fern/apis/chinese/definition/classrooms.yml @@ -0,0 +1,213 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + get: + path: /classrooms + method: GET + auth: true + docs: 教室模式之返回教室细节. + display-name: 获得一间教室 + request: + name: ClassroomsGetRequest + query-parameters: + code: + docs: 教室 `code`(”代码”) + type: string + retMemberLimit: + docs: 设置返回的教室中显示的学生数量 + type: optional + response: + docs: 教室细节 + type: root.ClassroomResponseWithCode + errors: [] + + create: + path: /classrooms + method: POST + auth: true + docs: 创建一个新的空“教室” + display-name: 创建一个教室 + request: + name: ClassroomsCreateRequest + body: + properties: + name: + type: string + docs: 教室名称 + ownerID: + type: root.objectIdString + aceConfig: + type: root.ClassroomsCreateRequestAceConfig + response: + docs: 创建的教室 + type: root.ClassroomResponseWithCode + errors: [] + + upsertMember: + path: /classrooms/{handle}/members + method: PUT + auth: true + docs: 在教室插入一个用户. + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 添加会员 + request: + name: ClassroomsUpsertMemberRequest + body: + properties: + code: + type: string + docs: 加入教室需使用代码 + userId: + type: string + docs: 使用字符串 `_id` 或`slug` 用来在教室中增加用户. + retMemberLimit: + docs: 设置返回的教室中显示的学生数量, 默认值为 1000 + type: optional + response: + docs: 教室中新增新成员 + type: root.ClassroomResponse + errors: [] + + removeMember: + path: /classrooms/{handle}/members + method: DELETE + auth: true + docs: 从教室中移出一个学生 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 从教室中移出一个学生 + request: + name: ClassroomsRemoveMemberRequest + body: + properties: + userId: + type: string + docs: 使用字符串 `_id` 或`slug` 用来从教室中移出用户. + retMemberLimit: + docs: 设置返回的教室中显示的学生数量, 默认值为 1000 + type: optional + response: + docs: 移出了学生的教室 + type: root.ClassroomResponse + errors: [] + + enrollUserInCourse: + path: /classrooms/{classroomHandle}/courses/{courseHandle}/enrolled + method: PUT + auth: true + docs: | + 在一个教室里的一门课程上注册一个用户。 + 如果课程是付费课程,用户需要一个有效的订阅许可。 + 用户必须是教室中的一个成员。 + path-parameters: + classroomHandle: + docs: 教室 `_id`. + type: string + courseHandle: + docs: 课程 `_id`. + type: string + display-name: 在课程中注册用户 + request: + name: ClassroomsEnrollUserInCourseRequest + query-parameters: + retMemberLimit: + docs: 设置返回的教室中显示的学生数量, 默认值为 1000 + type: optional + body: + properties: + userId: + type: root.objectIdString + response: + docs: 教室并且用户加入其中。 + type: root.ClassroomResponse + errors: [] + + removeEnrolledUser: + path: /classrooms/{classroomHandle}/courses/{courseHandle}/remove-enrolled + method: PUT + auth: true + docs: | + 将用户从注册的课程和教室中移除。 + path-parameters: + classroomHandle: + docs: 教室`_id`. + type: string + courseHandle: + docs: 课程`_id`. + type: string + display-name: 删除注册用户 + request: + name: ClassroomsRemoveEnrolledUserRequest + query-parameters: + retMemberLimit: + docs: 设置返回的教室中显示的学生数量, 默认值为 1000 + type: optional + body: + properties: + userId: + type: root.objectIdString + response: + docs: 教室中,将用户移除课程。 + type: root.ClassroomResponse + errors: [] + + getMembersStats: + path: /classrooms/{classroomHandle}/stats + method: GET + auth: true + docs: | + 返回教室中所有学生的相关数据 + path-parameters: + classroomHandle: + docs: 教室 `_id`. + type: string + display-name: 获取会员统计信息 + request: + name: ClassroomsGetMembersStatsRequest + query-parameters: + project: + docs: > + 限制返回的数据内容, 由以下字符串按逗号连接组成: ["creator", "playtime", + "state.complete"...] + type: optional + memberLimit: + docs: 返回值中的学生数量, 默认为 10, 最大值为 100 + type: optional + memberSkip: + docs: 返回值中跳过的学生数量, 和 memberLimit 共同起到分页作用 + type: optional + response: + docs: | + 返回教室中所有学生的相关数据 + type: list + errors: [] + + getLevelsPlayed: + path: /classrooms/{classroomHandle}/members/{memberHandle}/sessions + method: GET + auth: true + docs: | + 返回这个教室中用户所玩得所有关卡. + path-parameters: + classroomHandle: + docs: 教室 `_id`. + type: string + memberHandle: + docs: 教室成员 `_id`. + type: string + display-name: 玩过关卡 + response: + docs: 教室的用户已经注册. + type: list + errors: [] diff --git a/fern/apis/chinese/definition/stats.yml b/fern/apis/chinese/definition/stats.yml new file mode 100644 index 0000000..75647eb --- /dev/null +++ b/fern/apis/chinese/definition/stats.yml @@ -0,0 +1,42 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + getPlaytimeStats: + path: /playtime-stats + method: GET + auth: true + docs: 返回游戏时间统计 + display-name: 获取游戏时间统计数据 + request: + name: StatsGetPlaytimeStatsRequest + query-parameters: + startDate: + docs: 早先有一个已经注册的用户重新创建 + type: optional + endDate: + docs: 早先有一个已经注册的用户重新创建 + type: optional + country: + docs: 按照国家字符串进行过滤 + type: optional + response: + docs: 反馈所有自有用户的游戏时间统计. + type: root.PlaytimeStatsResponse + errors: [] + + getLicenseStats: + path: /license-stats + method: GET + auth: true + docs: 返回订阅数据统计 + display-name: 获取许可证统计信息 + response: + docs: 对于教室/家庭订阅许可返回订阅统计数据。 + type: root.LicenseStatsResponse + errors: [] diff --git a/fern/apis/chinese/definition/users.yml b/fern/apis/chinese/definition/users.yml new file mode 100644 index 0000000..6fcda57 --- /dev/null +++ b/fern/apis/chinese/definition/users.yml @@ -0,0 +1,299 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + create: + path: /users + method: POST + auth: true + docs: | + 创建一个`User`(“用户”) + display-name: 创建用户 + request: + name: UsersCreateRequest + body: + properties: + name: + type: string + email: + type: string + role: + docs: | + `"student"` 或者 `"teacher"` + type: optional + preferredLanguage: + type: optional + heroConfig: + type: optional + birthday: + type: optional + response: + docs: 已经创建的用户 + type: root.UserResponse + errors: [] + + get: + path: /users/{handle} + method: GET + auth: true + docs: 返回一个`User`(“用户”)。 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 获取用户 + request: + name: UsersGetRequest + query-parameters: + includePlayTime: + docs: 设置非空字符串包括反馈函数stats.playTime + type: optional + response: + docs: 需求用户 + type: root.UserResponse + errors: [] + + update: + path: /users/{handle} + method: PUT + auth: true + docs: 修改一个 `User`("用户") 的姓名 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + request: + name: UsersUpdateRequest + body: + properties: + name: + docs: 设置一个新姓名 + type: optional + birthday: + docs: 设置生日 + type: optional + response: + docs: 影响的用户 + type: root.UserResponse + errors: [] + + getClassrooms: + path: /users/{handle}/classrooms + method: GET + auth: true + docs: 返回`Clasrooms`(“教室”)清单,这个用户(如果是学生)在教室里或者是教室的主人(如果是老师)。 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 按用户获取教室 + request: + name: UsersGetClassroomsRequest + query-parameters: + retMemberLimit: + docs: 设置返回的教室中显示的学生数量 + type: optional + response: + docs: 教室需求 + type: list + errors: [] + + setHero: + path: /users/{handle}/hero-config + method: PUT + auth: true + docs: 设置用户的英雄。 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 获取用户英雄 + request: + name: UsersSetHeroRequest + body: + properties: + thangType: + type: optional + response: + docs: 受影响的客户 + type: root.UserResponse + errors: [] + + setAceConfig: + path: /users/{handle}/ace-config + method: PUT + auth: true + docs: 设置用户的代码配置 ( 指用户在编辑器中可以修改的设置 ) , 如代码补全等. + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 设置用户的代码配置 + request: + name: UsersSetAceConfigRequest + body: + properties: + liveCompletion: + docs: 控制代码自动补全提示是否出现, 默认值是 true + type: optional + behaviors: + docs: 控制括号, 引号是否自动补齐, 默认值是 false + type: optional + language: + docs: >- + 控制个人账号(学生账号无效)使用的语言, 目前仅支持 python, javascript, cpp, lua, + coffeescript + type: optional + response: + docs: 受影响的客户 + type: root.UserResponse + errors: [] + + linkOauthIdentity: + path: /users/{handle}/o-auth-identities + method: POST + auth: true + docs: > + 将一个OAuth2身份(OAuth2 identity)加给用户,用户可以以此身份登录。你需要将一个OAuth代码或者准入指令(access + token)发送到这个端口。 + 1. 如果没有获得准入指令(access token)的话,系统会使用OAuth2指令URL(OAuth2 token + URL)来交换获得的代码,以此获得准入指令(access token)。 + 2. 然后系统会在你的服务上使用查找URL(lookup URL)爱你的通过准入指令(access token) + (改指令可能是你之前给予的,或者是在第一步中获得的)来查找这名用户。 并预计获得一个回应一个`id`属性的JSON对象。 + 3. 之后系统将保存用户`id`到我们的用户数据库中,作为一个新的OAuthIdentity. + 在这个示例中, 我们用准入指令(access token)(`1234`)来call你的查找网址(lookup URL)(比方说是 + `https://oauth.provider/user?t=<%= accessToken %>`)然后查找网址(lookup + URL)返回`{ id: 'abcd' }`,我们已经将这个用户储存到我们的数据库中了。 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 将一个OAuth2身份 + request: + name: UsersLinkOauthIdentityRequest + body: + properties: + provider: + type: string + docs: 你的授权提供者 ID (OAuth Provider ID)。 + accessToken: + docs: 将传输查询网址得到用户ID。如果没有`code`(“代码”)需要这一项。 + type: optional + code: + docs: 将传输授权指令终点得到令牌。如果没有`accessToken`(“访问令牌”)需要这一项。 + type: optional + response: + docs: 受影响用户 + type: root.UserResponse + errors: [] + + grantPremiumSubscription: + path: /users/{handle}/subscription + method: PUT + auth: true + docs: | + 在一段时间内授权用户访问“主页”版本的高级访问权限。 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 授予订阅 + request: + name: UsersGrantPremiumSubscriptionRequest + body: + properties: + ends: + type: root.datetimeString + response: + docs: 受影响用户 + type: root.UserResponse + errors: [] + + shortenSubscription: + path: /users/{handle}/shorten-subscription + method: PUT + auth: true + docs: | + 如果用户在一段时间已经有了高级访问权限,这将缩短/撤销他的高级访问权限。 + 如果结束时间少于或者等于现在时间,将撤销订阅权限并将结束时间设置为现在时间,否则将缩短订阅时间。 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 撤销他的高级访问权限 + request: + name: UsersShortenSubscriptionRequest + body: + properties: + ends: + type: root.datetimeString + response: + docs: 受影响客户 + type: root.UserResponse + errors: [] + + grantLicense: + path: /users/{handle}/license + method: PUT + auth: true + docs: | + 在一段时间内给予用户使用“教室”版本的权限。定义他们的角色为`"student"`(“学生”)。 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 格兰特“课堂”版 + request: + name: UsersGrantLicenseRequest + body: + properties: + ends: + type: root.datetimeString + response: + docs: 受影响用户 + type: root.UserResponse + errors: [] + + shortenLicense: + path: /users/{handle}/shorten-license + method: PUT + auth: true + docs: | + 如果用户在一定时间内已经登陆“教室”版本,这将缩短或撤销他的权限。 + 如果结束比现在时间短或者和现在时间相同, 这将撤销登陆,并将结束时间设置为当前时间,否则这将缩短注册时间。 + path-parameters: + handle: + docs: 文件中的 `_id` 或者 `slug`. + type: string + display-name: 缩短用户许可 + request: + name: UsersShortenLicenseRequest + body: + properties: + ends: + type: root.datetimeString + response: + docs: 受影响客户 + type: root.UserResponse + errors: [] + + lookup: + path: /user-lookup/{property}/{value} + method: GET + auth: true + docs: 采用唯一、可识别属性重新定向到`/users/{handle}` + path-parameters: + property: + docs: 查找属性对应字符串,也许是 `"israel-id"` 或者 `"name"`. + type: string + value: + docs: 查找的值. + type: string + display-name: 搜索用户 + errors: [] + display-name: users diff --git a/fern/apis/chinese/generators.yml b/fern/apis/chinese/generators.yml new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/fern/apis/chinese/generators.yml @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/fern/apis/english/definition/__package__.yml b/fern/apis/english/definition/__package__.yml new file mode 100644 index 0000000..1ee3894 --- /dev/null +++ b/fern/apis/english/definition/__package__.yml @@ -0,0 +1,299 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +types: + UsersCreateRequestRole: + docs: > + `"student"` or `"teacher"`. If unset, a home user will be created, unable + to join classrooms. + enum: + - name: student + value: student + - name: teacher + value: teacher + + UsersCreateRequestHeroConfig: + properties: + thangType: + type: optional + + ClassroomsCreateRequestAceConfig: + properties: + language: + docs: Programming language for the classroom + type: optional + + ClassroomsGetMembersStatsResponseItem: + properties: + _id: + type: optional + stats: + type: optional + + ClassroomsGetMembersStatsResponseItemStats: + properties: + gamesCompleted: + type: optional + playtime: + docs: Total play time in seconds + type: optional + + roleString: + type: string + docs: Usually either 'teacher' or 'student' + + datetimeString: + type: string + + objectIdString: + type: string + + UserResponse: + docs: Subset of properties listed here + properties: + _id: + type: optional + email: + type: optional + name: + type: optional + slug: + type: optional + role: + type: optional + stats: + type: optional + oAuthIdentities: + type: optional> + subscription: + type: optional + license: + type: optional + + UserResponseStats: + properties: + gamesCompleted: + type: optional + concepts: + type: optional> + playTime: + docs: Included only when specifically requested on the endpoint + type: optional + + UserResponseOAuthIdentitiesItem: + properties: + provider: + type: optional + id: + type: optional + + UserResponseSubscription: + properties: + ends: + type: optional + active: + type: optional + + UserResponseLicense: + properties: + ends: + type: optional + active: + type: optional + + ClassroomResponse: + docs: Subset of properties listed here + properties: + _id: + type: optional + name: + type: optional + members: + type: optional> + ownerID: + type: optional + description: + type: optional + courses: + type: optional> + + ClassroomResponseCoursesItem: + properties: + _id: + type: optional + levels: + type: optional>> + enrolled: + type: optional> + instance_id: + type: optional + + ClassroomResponseWithCode: + docs: Subset of properties listed here + properties: + _id: + type: optional + name: + type: optional + members: + type: optional> + ownerID: + type: optional + description: + type: optional + code: + type: optional + codeCamel: + type: optional + courses: + type: optional> + clanId: + type: optional + + ClassroomResponseWithCodeCoursesItem: + properties: + _id: + type: optional + levels: + type: optional>> + enrolled: + type: optional> + instance_id: + type: optional + + PlaytimeStatsResponse: + properties: + playTime: + docs: Total play time in seconds + type: optional + gamesPlayed: + docs: Number of levels played + type: optional + + LicenseStatsResponse: + properties: + licenseDaysGranted: + docs: Total number of license days granted + type: optional + licenseDaysUsed: + docs: Number of license days used + type: optional + licenseDaysRemaining: + docs: Number of license days remaining + type: optional + activeLicenses: + docs: Number of active/valid licenses + type: optional + + LevelSessionResponse: + properties: + state: + type: optional + level: + type: optional + levelID: + docs: Level slug like `wakka-maul` + type: optional + creator: + type: optional + playtime: + docs: Time played in seconds. + type: optional + changed: + type: optional + created: + type: optional + dateFirstCompleted: + type: optional + submitted: + docs: For arenas. Whether or not the level has been added to the ladder. + type: optional + published: + docs: >- + For shareable projects. Whether or not the project has been shared + with classmates. + type: optional + + LevelSessionResponseState: + properties: + complete: + type: optional + + LevelSessionResponseLevel: + properties: + original: + docs: The id for the level. + type: optional + + ClanResponse: + docs: Subset of properties listed here + properties: + _id: + type: optional + name: + type: optional + displayName: + type: optional + members: + type: optional> + ownerID: + type: optional + description: + type: optional + type: + type: optional + kind: + type: optional + metadata: + type: optional> + +service: + auth: false + base-path: "" + endpoints: + postUsersHandleOAuthIdentities: + path: /users/{handle}/o-auth-identities + method: POST + auth: true + docs: > + Adds an OAuth2 identity to the user, so that they can be logged in with + that identity. You need to send the OAuth code or the access token to + this endpoint. + 1. If no access token is provided, it will use your OAuth2 token URL to + exchange the given code for an access token. + 2. Then it will use the access token (given by you, or received from + step 1) to look up the user on your service using the lookup URL, and + expects a JSON object in response with an `id` property. + 3. It will then save that user `id` to the user in our db as a new + OAuthIdentity. + In this example, we call your lookup URL (let's say, + `https://oauth.provider/user?t=<%= accessToken %>`) with the access + token (`1234`). The lookup URL returns `{ id: 'abcd' }` in this case, + which we save to the user in our db. + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Add Oauth2 Identity + request: + name: PostUsersHandleOAuthIdentitiesRequest + body: + properties: + provider: + type: string + docs: Your OAuth Provider ID. + accessToken: + docs: >- + Will be passed through your lookup URL to get the user ID. + Required if no `code`. + type: optional + code: + docs: >- + Will be passed to the OAuth token endpoint to get a token. + Required if no `accessToken`. + type: optional + response: + docs: The affected user + type: UserResponse + errors: [] + +errors: {} diff --git a/fern/apis/english/definition/api.yml b/fern/apis/english/definition/api.yml new file mode 100644 index 0000000..07d4373 --- /dev/null +++ b/fern/apis/english/definition/api.yml @@ -0,0 +1,10 @@ +imports: + root: __package__.yml +name: api +display-name: CodeCombat API +error-discrimination: + strategy: status-code +auth: basic +default-environment: default +environments: + default: https://codecombat.com/api diff --git a/fern/api/definition/auth.yml b/fern/apis/english/definition/auth.yml similarity index 74% rename from fern/api/definition/auth.yml rename to fern/apis/english/definition/auth.yml index 78e7345..876470e 100644 --- a/fern/api/definition/auth.yml +++ b/fern/apis/english/definition/auth.yml @@ -1,33 +1,27 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json -service: - display-name: UserService - auth: true - base-path: /auth/login-o-auth +imports: + root: __package__.yml + +service: + auth: false + base-path: "" endpoints: - get: - display-name: Login User - path: "" + loginOauth: + path: /auth/login-o-auth method: GET + auth: true docs: > - Logs a [user](#users) in. - #### Example - ```javascript - url = - `https://codecombat.com/auth/login-o-auth?provider=${OAUTH_PROVIDER_ID}&accessToken=1234` - res.redirect(url) - // User is sent to this CodeCombat URL and assuming everything checks - out, - // is logged in and redirected to the home page. - ``` + Logs a user in. In this example, we call your lookup URL (let's say, `https://oauth.provider/user?t=<%= accessToken %>`) with the access token (`1234`). The lookup URL returns `{ id: 'abcd' }` in this case. We will match this `id` with the OAuthIdentity stored in the user information in our db. If everything checks out, the user is logged in and redirected to the home page. + display-name: Login User request: - name: GetUserAuthRequest + name: LoginOauthRequest query-parameters: provider: docs: Your OAuth Provider ID @@ -52,3 +46,4 @@ service: If an error happens, redirects the user to this url, with at least query parameters `code`, `errorName` and `message`. type: optional + errors: [] diff --git a/fern/apis/english/definition/clans.yml b/fern/apis/english/definition/clans.yml new file mode 100644 index 0000000..97bfe63 --- /dev/null +++ b/fern/apis/english/definition/clans.yml @@ -0,0 +1,30 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + upsertMember: + path: /clan/{handle}/members + method: PUT + auth: true + docs: Upserts a user into the clan. + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Upsert User Into Clan + request: + name: ClansUpsertMemberRequest + body: + properties: + userId: + type: string + docs: The `_id` or `slug` of the user to add to the clan. + response: + docs: The clan with the member added. + type: root.ClanResponse + errors: [] diff --git a/fern/api/definition/classrooms.yml b/fern/apis/english/definition/classrooms.yml similarity index 59% rename from fern/api/definition/classrooms.yml rename to fern/apis/english/definition/classrooms.yml index cf83012..c9c66de 100644 --- a/fern/api/definition/classrooms.yml +++ b/fern/apis/english/definition/classrooms.yml @@ -1,20 +1,20 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json imports: - commons: commons.yml + root: __package__.yml service: - display-name: ClassroomsService - auth: true - base-path: /classrooms + auth: false + base-path: "" endpoints: get: - display-name: Get Classroom Details - path: "" + path: /classrooms method: GET + auth: true docs: Returns the classroom details for a class code. + display-name: Get Classroom Details request: - name: GetClassroomDetailsRequest + name: ClassroomsGetRequest query-parameters: code: docs: The classroom's `code`. @@ -22,76 +22,94 @@ service: retMemberLimit: docs: limit the return number of members for the classroom type: optional - response: commons.ClassroomResponseWithCode + response: + docs: The classroom details. + type: root.ClassroomResponseWithCode + errors: [] create: - display-name: Create a Classroom - path: "" + path: /classrooms method: POST + auth: true docs: Creates a new empty `Classroom`. + display-name: Create a classroom request: - name: CreateClassroomRequest + name: ClassroomsCreateRequest body: properties: name: - docs: Name of the classroom type: string - ownerID: commons.objectIdString - aceConfig: AceConfig + docs: Name of the classroom + ownerID: + type: root.objectIdString + aceConfig: + type: root.ClassroomsCreateRequestAceConfig + response: + docs: The created classroom + type: root.ClassroomResponseWithCode + errors: [] - upsertFromClassroom: - display-name: Upsert a User from Classroom - path: /{handle}/members + upsertMember: + path: /classrooms/{handle}/members method: PUT + auth: true docs: Upserts a user into the classroom. path-parameters: handle: docs: The document's `_id` or `slug`. type: string + display-name: Upsert a user from classroom request: - name: UpsertClassroomRequest + name: ClassroomsUpsertMemberRequest body: properties: code: - docs: The code for joining this classroom type: string + docs: The code for joining this classroom userId: - docs: The `_id` or `slug` of the user to add to the class. type: string + docs: The `_id` or `slug` of the user to add to the class. retMemberLimit: docs: >- limit the return number of members for the classroom, the default value is 1000 type: optional - response: commons.ClassroomResponse + response: + docs: The classroom with the member added. + type: root.ClassroomResponse + errors: [] - deleteUserFromClassroom: - display-name: Delete User from Classroom - path: /{handle}/members + removeMember: + path: /classrooms/{handle}/members method: DELETE + auth: true docs: Remove a user from the classroom. path-parameters: handle: docs: The document's `_id` or `slug`. type: string + display-name: Delete User from Classroom request: - name: DeleteUserFromClassroomRequest + name: ClassroomsRemoveMemberRequest body: properties: userId: - docs: The `_id` or `slug` of the user to remove from the class. type: string + docs: The `_id` or `slug` of the user to remove from the class. retMemberLimit: docs: >- limit the return number of members for the classroom, the default value is 1000 type: optional - response: commons.ClassroomResponse + response: + docs: The classroom with the member removed. + type: root.ClassroomResponse + errors: [] enrollUserInCourse: - display-name: Enroll a User in a Course - path: /{classroomHandle}/courses/{courseHandle}/enrolled + path: /classrooms/{classroomHandle}/courses/{courseHandle}/enrolled method: PUT + auth: true docs: | Enrolls a user in a course in a classroom. If the course is paid, user must have an active license. @@ -103,8 +121,9 @@ service: courseHandle: docs: The course's `_id`. type: string + display-name: Enroll User in a Course request: - name: EnrollUserInCourseRequest + name: ClassroomsEnrollUserInCourseRequest query-parameters: retMemberLimit: docs: >- @@ -113,13 +132,17 @@ service: type: optional body: properties: - userId: commons.objectIdString - response: commons.ClassroomResponse + userId: + type: root.objectIdString + response: + docs: The classroom with the user enrolled. + type: root.ClassroomResponse + errors: [] - removeUserFromClassroom: - display-name: Remove a User from a Classroom - path: /{classroomHandle}/courses/{courseHandle}/remove-enrolled + removeEnrolledUser: + path: /classrooms/{classroomHandle}/courses/{courseHandle}/remove-enrolled method: PUT + auth: true docs: | Removes an enrolled user from a course in a classroom. path-parameters: @@ -129,8 +152,9 @@ service: courseHandle: docs: The course's `_id`. type: string + display-name: Remove User from a classroom request: - name: RemoveUserFromClassroomRequest + name: ClassroomsRemoveEnrolledUserRequest query-parameters: retMemberLimit: docs: >- @@ -139,21 +163,26 @@ service: type: optional body: properties: - userId: commons.objectIdString - response: commons.ClassroomResponse + userId: + type: root.objectIdString + response: + docs: The classroom with the user removed from the course. + type: root.ClassroomResponse + errors: [] getMembersStats: - display-name: Get Members Stats for a Classroom - path: /{classroomHandle}/stats + path: /classrooms/{classroomHandle}/stats method: GET + auth: true docs: | Returns a list of all members stats for the classroom. path-parameters: classroomHandle: docs: The classroom's `_id`. type: string + display-name: Get Member Stats request: - name: GetMembersStatsRequest + name: ClassroomsGetMembersStatsRequest query-parameters: project: docs: > @@ -170,12 +199,15 @@ service: docs: | Skip the members that doesn't need to return, for pagination type: optional - response: list + response: + docs: The members stats for the classroom. + type: list + errors: [] - getLevelSession: - display-name: Get Level Session - path: /{classroomHandle}/members/{memberHandle}/sessions + getLevelsPlayed: + path: /classrooms/{classroomHandle}/members/{memberHandle}/sessions method: GET + auth: true docs: | Returns a list of all levels played by the user for the classroom. path-parameters: @@ -185,56 +217,8 @@ service: memberHandle: docs: The classroom member's `_id`. type: string - response: list - -types: - LevelSessionResponse: - properties: - state: optional - level: optional - levelID: - docs: Level slug like `wakka-maul` - type: optional - creator: optional - playtime: - docs: Time played in seconds. - type: optional - changed: optional - created: optional - dateFirstCompleted: optional - submitted: - docs: For arenas. Whether or not the level has been added to the ladder. - type: optional - published: - docs: >- - For shareable projects. Whether or not the project has been shared - with classmates. - type: optional - - State: - properties: - complete: optional - - Level: - properties: - original: - docs: The id for the level. - type: optional - - AceConfig: - properties: - language: - docs: Programming language for the classroom - type: optional - - PlayStats: - properties: - gamesCompleted: optional - playtime: - docs: Total play time in seconds - type: optional - - MemberStat: - properties: - _id: optional - stats: optional + display-name: Get Level Session + response: + docs: The classroom with the user enrolled. + type: list + errors: [] diff --git a/fern/apis/english/definition/stats.yml b/fern/apis/english/definition/stats.yml new file mode 100644 index 0000000..bdcf624 --- /dev/null +++ b/fern/apis/english/definition/stats.yml @@ -0,0 +1,42 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + getPlaytimeStats: + path: /playtime-stats + method: GET + auth: true + docs: Returns the playtime stats + display-name: Get Playtime Stats + request: + name: StatsGetPlaytimeStatsRequest + query-parameters: + startDate: + docs: Earliest an included user was created + type: optional + endDate: + docs: Latest an included user was created + type: optional + country: + docs: Filter by country string + type: optional + response: + docs: Returns the playtime stats accross all owned users. + type: root.PlaytimeStatsResponse + errors: [] + + getLicenseStats: + path: /license-stats + method: GET + auth: true + docs: Returns the license stats + display-name: Get License Stats + response: + docs: Returns the license stats for classroom/home subscription licenses. + type: root.LicenseStatsResponse + errors: [] diff --git a/fern/apis/english/definition/users.yml b/fern/apis/english/definition/users.yml new file mode 100644 index 0000000..e0e7a14 --- /dev/null +++ b/fern/apis/english/definition/users.yml @@ -0,0 +1,278 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/fern-api/fern/main/fern.schema.json + +imports: + root: __package__.yml + +service: + auth: false + base-path: "" + endpoints: + create: + path: /users + method: POST + auth: true + docs: | + Creates a `User`. + display-name: Create User + request: + name: UsersCreateRequest + body: + properties: + name: + type: string + email: + type: string + role: + docs: > + `"student"` or `"teacher"`. If unset, a home user will be + created, unable to join classrooms. + type: optional + preferredLanguage: + type: optional + heroConfig: + type: optional + birthday: + type: optional + response: + docs: The created user + type: root.UserResponse + errors: [] + + get: + path: /users/{handle} + method: GET + auth: true + docs: Returns a `User`. + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Get User + request: + name: UsersGetRequest + query-parameters: + includePlayTime: + docs: Set to non-empty string to include stats.playTime in response + type: optional + response: + docs: The requested user + type: root.UserResponse + errors: [] + + update: + path: /users/{handle} + method: PUT + auth: true + docs: Modify name of a `User` + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Update User + request: + name: UsersUpdateRequest + body: + properties: + name: + type: string + docs: Set to new name string + birthday: + docs: Set the birthday + type: optional + response: + docs: The affected user + type: root.UserResponse + errors: [] + + getClassrooms: + path: /users/{handle}/classrooms + method: GET + auth: true + docs: >- + Returns a list of `Classrooms` this user is in (if a student) or owns + (if a teacher). + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Get Classrooms By User + request: + name: UsersGetClassroomsRequest + query-parameters: + retMemberLimit: + docs: limit the return number of members for each classroom + type: optional + response: + docs: The requested classrooms + type: list + errors: [] + + setHero: + path: /users/{handle}/hero-config + method: PUT + auth: true + docs: Set the user's hero. + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Get User Hero + request: + name: UsersSetHeroRequest + body: + properties: + thangType: + type: optional + response: + docs: The affected user + type: root.UserResponse + errors: [] + + setAceConfig: + path: /users/{handle}/ace-config + method: PUT + auth: true + docs: >- + Set the user's aceConfig (the settings for the in-game Ace code editor), + such as whether to enable autocomplete. + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Put Ace Config + request: + name: UsersSetAceConfigRequest + body: + properties: + liveCompletion: + docs: >- + controls whether autocompletion snippets show up, the default + value is true + type: optional + behaviors: + docs: >- + controls whether things like automatic parenthesis and quote + completion happens, the default value is false + type: optional + language: + docs: >- + only for home users, should be one of ["python", "javascript", + "cpp", "lua", "coffeescript"] right now + type: optional + response: + docs: The affected user + type: root.UserResponse + errors: [] + + grantPremiumSubscription: + path: /users/{handle}/subscription + method: PUT + auth: true + docs: | + Grants a user premium access to the "Home" version up to a certain time. + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Put Subscription + request: + name: UsersGrantPremiumSubscriptionRequest + body: + properties: + ends: + type: root.datetimeString + response: + docs: The affected user + type: root.UserResponse + errors: [] + + shortenSubscription: + path: /users/{handle}/shorten-subscription + method: PUT + auth: true + docs: > + If the user already has a premium access up to a certain time, this + shortens/revokes his/her premium access. + If the ends is less than or equal to the current time, it revokes the + subscription and sets the end date to be the current time, else it just + shortens the subscription. + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Shorten User Subscription + request: + name: UsersShortenSubscriptionRequest + body: + properties: + ends: + type: root.datetimeString + response: + docs: The affected user + type: root.UserResponse + errors: [] + + grantLicense: + path: /users/{handle}/license + method: PUT + auth: true + docs: | + Grants a user access to the "Classroom" version up to a certain time. + Sets their role to "student". + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Grant User License + request: + name: UsersGrantLicenseRequest + body: + properties: + ends: + type: root.datetimeString + response: + docs: The affected user + type: root.UserResponse + errors: [] + + shortenLicense: + path: /users/{handle}/shorten-license + method: PUT + auth: true + docs: > + If the user already has access to the "Classroom" version up to a + certain time, this shortens/revokes his/her access. + If the ends is less than or equal to the current time, it revokes the + enrollment and sets the end date to be the current time, else it just + shortens the enrollment. + path-parameters: + handle: + docs: The document's `_id` or `slug`. + type: string + display-name: Shorten User License + request: + name: UsersShortenLicenseRequest + body: + properties: + ends: + type: root.datetimeString + response: + docs: The affected user + type: root.UserResponse + errors: [] + + lookup: + path: /user-lookup/{property}/{value} + method: GET + auth: true + docs: Redirects to `/users/{handle}` given a unique, identifying property + path-parameters: + property: + docs: The property to lookup by. May either be `"israel-id"` or `"name"`. + type: string + value: + docs: The value to be looked up. + type: string + display-name: Search for User + errors: [] + display-name: users diff --git a/fern/api/generators.yml b/fern/apis/english/generators.yml similarity index 60% rename from fern/api/generators.yml rename to fern/apis/english/generators.yml index cc47f81..7e22b07 100644 --- a/fern/api/generators.yml +++ b/fern/apis/english/generators.yml @@ -1,8 +1,8 @@ groups: external: generators: - - name: fernapi/fern-typescript-sdk - version: 0.5.11 + - name: fernapi/fern-typescript-node-sdk + version: 0.7.2 output: location: npm package-name: '@fern-api/codecombat' @@ -12,7 +12,7 @@ groups: config: namespaceExport: CodeCombat - name: fernapi/fern-python-sdk - version: 0.3.0-1-g2d609525 + version: 0.4.4 output: location: pypi package-name: codecombat @@ -21,19 +21,32 @@ groups: repository: codecombat/codecombat-python config: client_class_name: CodeCombat + - name: fernapi/fern-go-sdk + version: 0.3.0 + github: + repository: codecombat/codecombat-go + - name: fernapi/fern-java-sdk + version: 0.4.9 + output: + location: maven + coordinate: com.codecombat:codecombat-java + username: ${MAVEN_USERNAME} + password: ${MAVEN_PASSWORD} + github: + repository: fern-codecombat/codecombat-java - name: fernapi/fern-openapi version: 0.0.19 github: repository: codecombat/codecombat-openapi - name: fernapi/fern-openapi - version: 0.0.19 + version: 0.0.28 github: repository: codecombat/docs - name: fernapi/fern-postman - version: 0.0.34 + version: 0.0.44 output: location: postman api-key: ${POSTMAN_API_KEY} workspace-id: ${POSTMAN_WORKSPACE_ID} github: - repository: codecombat/codecombat-postman + repository: codecombat/codecombat-postman \ No newline at end of file diff --git a/fern/assets/favicon.png b/fern/assets/favicon.png new file mode 100644 index 0000000..2eff160 Binary files /dev/null and b/fern/assets/favicon.png differ diff --git a/fern/assets/logo.png b/fern/assets/logo.png new file mode 100644 index 0000000..a278961 Binary files /dev/null and b/fern/assets/logo.png differ diff --git a/fern/docs.yml b/fern/docs.yml new file mode 100644 index 0000000..c36dda2 --- /dev/null +++ b/fern/docs.yml @@ -0,0 +1,39 @@ +instances: + - url: codecombat.docs.buildwithfern.com + custom-domain: api-docs.codecombat.com + +navigation: + - version: English + layout: + - section: Overview + contents: + - page: Introduction + path: ./intro-en.mdx + - api-name: english + api: API Reference + - version: Chinese + layout: + - section: 概述 + contents: + - page: 介绍 + path: ./intro-ch.mdx + - api-name: chinese + api: API 参考 + +title: CodeCombat | API Reference +colors: + accentPrimary: + dark: "#1FBAB4" + light: "#63DFDA" +logo: + dark: ./assets/logo.png + light: ./assets/logo.png + height: 40 +favicon: ./assets/favicon.png +navbar-links: + - type: secondary + text: Contact us + url: "mailto:support@codecombat.com" + - type: primary + text: Sign up + url: https://codecombat.com/ \ No newline at end of file diff --git a/fern/fern.config.json b/fern/fern.config.json index 5586432..efcc285 100644 --- a/fern/fern.config.json +++ b/fern/fern.config.json @@ -1,4 +1,4 @@ { "organization": "codecombat", - "version": "0.6.10" + "version": "0.15.0-rc3" } \ No newline at end of file diff --git a/fern/intro-ch.mdx b/fern/intro-ch.mdx new file mode 100644 index 0000000..2d26ca8 --- /dev/null +++ b/fern/intro-ch.mdx @@ -0,0 +1,31 @@ +## 基本情况 + +* 开发者在Node/Express服务器上安装了以下 [请求](https://github.com/request/request),示例采用JavaScript形式。 +* 请求和反馈形式为JSON。 +* API接口是创建或者参考的基础资源。因此,举例来说,所有的开发路径(routes)是以'/api/users'开始,返回[User](#users)开发资源。 + + ## 客户设置 +目前我们没有让您创建或者设置您自己的客户级开发者接口(API Client)或者OAuth提供者(OAuth Privider)信息。请直接联系我们启动您的开发进程。 + +## 用户授权 +系统必须通过基础HTTP授权(Basic HTTP Authentication)来启动API路径。在我们的系统中创建你的API客户(API_CLIENT)之后,你会获得一个用户名(CLIENT_ID)和密码(CLIENT_SECRET)。对于每一个API请求,请提供你的姓名(CLIENT_ID)和密码(CLIENT_SECRET)。 + +```javascript +url = 'https://koudashijie.com/api/users' +json = { name: 'A username' } +auth = { name: CLIENT_ID, pass: CLIENT_SECRET } +request.get({ url, json, auth }, (err, res) => console.log(res.statusCode, res.body)) +``` + +## 用户授权 +通过您的服务在CodeCombat平台上认证一个用户,您需要采用以下oAuth 2流程. CodeCombat作为一个客户,您的服务作为服务提供者。首先,您需要提供一个可信的查找网址(lookup URL 或者 token URL),来进行创建设置(参见以上客户创建说明),这个创建账户和登陆的过程如以下所示: + +1. **创建用户** +2. **把CodeCombat用户和一个oAuth身份对接** + 你可以使用代码或者准入指令(access token)来启动这个API嵌入。如果你没有获得准入指令(access token),我们会用这个URL指令来替换原有的代码来获得一个准入指令(access token)。 + 然后我们用准入指令(access token)来启动查找网址(lookup URL),以此从你的系统中获得用户信息(`id`),这些信息已被储存在我们的用户数据库中。 +3. **用户登陆** + 你可以用这个代码/准入指令(access token)来call API, 然后我们会通过类似于第二步中的步骤来获得用户信息。 + 最后,我们将数据库在第二步中获得的信息与这个信息进行匹配,如果匹配成功,用户即可完成登录并被引导到主页。 + +这里还有一个描述以上过程的 [实例](https://s3.amazonaws.com/files.codecombat.com/codecombat_oauth_example.tar.gz),以便理解。 同时,你也可以参考这个 [图表](https://s3.amazonaws.com/files.codecombat.com/Example_OAuth_Flow.png)。 \ No newline at end of file diff --git a/fern/intro-en.mdx b/fern/intro-en.mdx new file mode 100644 index 0000000..b8b30df --- /dev/null +++ b/fern/intro-en.mdx @@ -0,0 +1,58 @@ +## Basics + +- Examples are in JavaScript on a Node/Express server with + [request](https://github.com/request/request) installed. +- Request and responses are in JSON +- API responses are the base resource being created/referenced. So, for example, + all routes starting with `/api/users` return [User](/users/post-users) + resources. + +## Client Setup + +We currently do not have a way for you to create or set up your own API Client +or OAuth Provider information. Please contact us directly to get started. + +## Client Authentication + +API routes must be called with Basic HTTP Authentication. You will receive a +username (CLIENT_ID) and password (CLIENT_SECRET) upon creation of your API +Client in our system. Provide those credentials with each API request. + +```javascript +url = "https://codecombat.com/api/users"; +json = { name: "A username" }; +auth = { name: CLIENT_ID, pass: CLIENT_SECRET }; +request.get({ url, json, auth }, (err, res) => + console.log(res.statusCode, res.body) +); +``` + +We strongly recommend using a secrets manager for storing your client secret. +Plain text files like dotenv lead to accidental, costly leaks. Use +[Doppler](https://www.doppler.com/) for a developer-friendly experience. AWS and +Google Cloud have native solutions as well. + +## User Authentication + +To authenticate a user on CodeCombat through your service, you will need to use +the below OAuth 2 process. CodeCombat will act as the client, and your service +will act as the provider. First, you will need to provide a trusted lookup URL +and/or a token URL for the setup(See Client Setup above). Then the process from +user account creation to log in will look like this: + +1. **Create the user** +2. **Link the CodeCombat user to an OAuth identity** + You can call this API with a code or an access token. If no access token is + given, we will use the token URL to exchange the given code for an access + token. Then we call the lookup URL with the access token to receive the user + information (id) from your system which is saved to the user in our db. +3. **Log the user in** + You can call this API with the code/access token, and we will get the user + information from your system similarly to step 2. Finally, we match this + information with what is stored in our database in step 2. If everything + checks out, the user is logged in and redirected to the home page. + +There is also a +[concrete example](https://s3.amazonaws.com/files.codecombat.com/codecombat_oauth_example.tar.gz) +depicting the above process for better understanding. You can also refer to this +[diagram](https://s3.amazonaws.com/files.codecombat.com/Example_OAuth_Flow.png).