feat(templates): template list pagination via GET /v2/templates#1479
feat(templates): template list pagination via GET /v2/templates#1479huv1k wants to merge 3 commits into
Conversation
Add a paginated `GET /v2/templates` endpoint to the spec and expose it across all packages: - JS SDK: `Template.list()` -> `TemplatePaginator` returning `TemplateInfo`, matching `Sandbox.list()`. - Python SDK: `Template.list()` / `AsyncTemplate.list()` -> `TemplatePaginator` / `AsyncTemplatePaginator` (sync + async). - CLI: `e2b template list` pages through templates via the SDK paginator and adds a `-l, --limit` option (default 1000, 0 for no limit). Pagination uses `limit`/`nextToken` query params and the `X-Next-Token` response header, consistent with `sandbox list`.
🦋 Changeset detectedLatest commit: df8f73c The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Package ArtifactsBuilt from b2369d3. Download artifacts from this workflow run. JS SDK ( npm install ./e2b-2.30.6-templates-list-pagination-for-cli-en-603.0.tgzCLI ( npm install ./e2b-cli-2.12.3-templates-list-pagination-for-cli-en-603.0.tgzPython SDK ( pip install ./e2b-2.29.5+templates.list.pagination.for.cli.en.603-py3-none-any.whl |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 760d988327
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Template.list builds its own ConnectionConfig, so passing only teamId/limit left config-file logins (e2b auth login) unauthenticated. Resolve the API key via ensureAPIKey() and pass it to the paginator, mirroring sandbox list. This also fixes the delete/publish --select flows.
mishushakov
left a comment
There was a problem hiding this comment.
move template method to template and shared classes to utils
| /** | ||
| * Identifier of the team whose templates should be listed. Defaults to the | ||
| * team the API key belongs to. | ||
| */ | ||
| teamId?: string |
There was a problem hiding this comment.
that makes no sense, API key is scoped per team, I cannot check templates for a different team with same API key
| @@ -0,0 +1,185 @@ | |||
| import { ApiClient, components, handleApiError } from '../api' | |||
| import { ConnectionConfig } from '../connectionConfig' | |||
| import { BasePaginator, SandboxApiOpts } from '../sandbox/sandboxApi' | |||
There was a problem hiding this comment.
importing anything from Sandbox here is no-bueno, if it's shared it should go to shared utils.ts
| * } | ||
| * ``` | ||
| */ | ||
| export class TemplatePaginator extends BasePaginator<TemplateInfo> { |
There was a problem hiding this comment.
BasePaginator might not be re-usable here - its constructor opts are SandboxApiOpts
maybe you can make BasePaginator constructor more generic?
| if (!this.hasNext) { | ||
| throw new Error('No more items to fetch') | ||
| } |
There was a problem hiding this comment.
please check in other places in SDK - but not having next items should not raise any error - instead remove empty []
if that's the case elsewhere - add some comment that we'll be changing this
| return (res.data ?? []).map( | ||
| (template: components['schemas']['Template']) => ({ | ||
| templateId: template.templateID, | ||
| buildId: template.buildID, | ||
| cpuCount: template.cpuCount, | ||
| memoryMB: template.memoryMB, | ||
| diskSizeMB: template.diskSizeMB, | ||
| public: template.public, | ||
| aliases: template.aliases ?? [], | ||
| names: template.names ?? [], | ||
| createdAt: new Date(template.createdAt), | ||
| updatedAt: new Date(template.updatedAt), | ||
| lastSpawnedAt: template.lastSpawnedAt | ||
| ? new Date(template.lastSpawnedAt) | ||
| : null, | ||
| spawnCount: template.spawnCount, | ||
| buildCount: template.buildCount, | ||
| envdVersion: template.envdVersion, | ||
| createdBy: template.createdBy ?? null, | ||
| buildStatus: template.buildStatus, | ||
| }) |
There was a problem hiding this comment.
I think you can just spread most of these
| if not self.has_next: | ||
| raise Exception("No more items to fetch") |
There was a problem hiding this comment.
everything I said above applies here
| from e2b.template.main import TemplateBase, TemplateClass | ||
| from e2b.template.types import BuildInfo, InstructionType, TemplateTag, TemplateTagInfo | ||
| from e2b.template.utils import normalize_build_arguments, read_dockerignore | ||
| from e2b.sandbox_async.paginator import AsyncTemplatePaginator |
There was a problem hiding this comment.
importing from sandbox here is no-bueno
| from .sandbox_async.paginator import ( | ||
| AsyncSandboxPaginator, | ||
| AsyncSnapshotPaginator, | ||
| AsyncTemplatePaginator, |
| throw err | ||
| } | ||
|
|
||
| this.updatePagination(res.response) |
There was a problem hiding this comment.
is there a particular reason we have this method in the JS SDK but not in Python?
|
also, no tests for the Python SDKs? |
| export const listCommand = new commander.Command('list') | ||
| .description('list sandbox templates') | ||
| .alias('ls') | ||
| .addOption(teamOption) |
There was a problem hiding this comment.
this option should be prob deprecated
There was a problem hiding this comment.
please make it integration test instead, not mock
| console.log( | ||
| `Showing first ${limit} templates. Use --limit to change.` | ||
| ) |
There was a problem hiding this comment.
no need for this, our users can count
| // Adapt the SDK's TemplateInfo back to the raw API schema shape the rest of the | ||
| // CLI (table rendering, selection prompts, `--format json`) is built around. | ||
| function toTemplateSchema( |
| import { teamOption } from '../../options' | ||
| import { handleE2BRequestError } from '../../utils/errors' | ||
|
|
||
| const DEFAULT_LIMIT = 1000 |
There was a problem hiding this comment.
I think it's fine for now to just return the whole list, auto-paginate should be cheap op.
the reason is that ppl pipe the CLI output into other tools and we don't have a good way to paginate in the CLI - perhaps next task to figure out?
Summary
Adds support for listing templates with pagination via the new
GET /v2/templatesendpoint (added tospec/openapi.yml, clients regenerated). The JS and Python SDKs gain aTemplate.list()paginator (TemplatePaginator/AsyncTemplatePaginator, yieldingTemplateInfo) mirroringSandbox.list(), ande2b template listnow pages through results behind a new-l, --limitoption (default 1000,0for no limit) with a "Showing first N…" hint. Pagination uses thelimit/nextTokenquery params and theX-Next-Tokenresponse header, consistent withsandbox list. Covered by new unit tests (msw-based SDK test + mocked CLI test); minor version bump for all three packages via changeset.Usage
CLI:
JS SDK:
Python SDK: