From 1d6fc37be7bce1a83c70cd793ddb98dd9d456757 Mon Sep 17 00:00:00 2001 From: Alex Drankou Date: Tue, 2 Jun 2026 17:26:57 +0200 Subject: [PATCH 01/11] feat(templates): mirror paginated templates endpoints in dashboard-api spec Regenerates the dashboard-api client types for the cursor-paginated GET /templates (single `sort` enum) and GET /templates/{templateID}. --- spec/openapi.dashboard-api.yaml | 35 ++++++++++++++ .../shared/contracts/dashboard-api.types.ts | 48 +++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/spec/openapi.dashboard-api.yaml b/spec/openapi.dashboard-api.yaml index 1bb233b49..036b07cd5 100644 --- a/spec/openapi.dashboard-api.yaml +++ b/spec/openapi.dashboard-api.yaml @@ -121,6 +121,13 @@ components: description: Team slug to resolve. schema: type: string + templateID: + name: templateID + in: path + required: true + description: Identifier of the template. + schema: + type: string templates_limit: name: limit in: query @@ -1359,6 +1366,34 @@ paths: "500": $ref: "#/components/responses/500" + /templates/{templateID}: + get: + summary: Get a single team template + description: Returns a single template owned by the team (or a default template, unless the team is on a dedicated cluster). + tags: [templates] + security: + - Supabase1TokenAuth: [] + Supabase2TeamAuth: [] + - AuthProviderBearerAuth: [] + AuthProviderTeamAuth: [] + parameters: + - $ref: "#/components/parameters/templateID" + responses: + "200": + description: Successfully returned the template. + content: + application/json: + schema: + $ref: "#/components/schemas/TeamTemplate" + "401": + $ref: "#/components/responses/401" + "403": + $ref: "#/components/responses/403" + "404": + $ref: "#/components/responses/404" + "500": + $ref: "#/components/responses/500" + /templates/defaults: get: summary: List default templates diff --git a/src/core/shared/contracts/dashboard-api.types.ts b/src/core/shared/contracts/dashboard-api.types.ts index e4f40b24c..457af44b1 100644 --- a/src/core/shared/contracts/dashboard-api.types.ts +++ b/src/core/shared/contracts/dashboard-api.types.ts @@ -811,6 +811,52 @@ export interface paths { patch?: never trace?: never } + '/templates/{templateID}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Get a single team template + * @description Returns a single template owned by the team (or a default template, unless the team is on a dedicated cluster). + */ + get: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of the template. */ + templateID: components['parameters']['templateID'] + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Successfully returned the template. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['TeamTemplate'] + } + } + 401: components['responses']['401'] + 403: components['responses']['403'] + 404: components['responses']['404'] + 500: components['responses']['500'] + } + } + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } '/templates/defaults': { parameters: { query?: never @@ -1223,6 +1269,8 @@ export interface components { userId: string /** @description Team slug to resolve. */ teamSlug: string + /** @description Identifier of the template. */ + templateID: string /** @description Maximum number of items to return per page. */ templates_limit: number /** @description Cursor returned by the previous list response in `{sort}|{value}|{templateID}` format. Rejected if its sort does not match the request. */ From 538774dc01d0ff5eb4aac5fb4b2ad831ae73157d Mon Sep 17 00:00:00 2001 From: Alex Drankou Date: Tue, 2 Jun 2026 17:26:57 +0200 Subject: [PATCH 02/11] feat(templates): paginated listTeamTemplates repo method and router input getTemplates accepts cursor/limit/filter/search and a single `sort` token and returns a paginated page via the dashboard-api endpoint. The full-list getTeamTemplates (used by the terminal page) is kept unchanged. --- src/core/modules/templates/models.ts | 27 +++++++ .../modules/templates/repository.server.ts | 80 ++++++++++++++++++- src/core/server/api/routers/templates.ts | 43 ++++++++-- 3 files changed, 144 insertions(+), 6 deletions(-) diff --git a/src/core/modules/templates/models.ts b/src/core/modules/templates/models.ts index aa08bebab..72f46e3e2 100644 --- a/src/core/modules/templates/models.ts +++ b/src/core/modules/templates/models.ts @@ -23,3 +23,30 @@ export type DefaultTemplate = Template & { isDefault: true defaultDescription?: string } + +export type TemplatesSort = + | 'name_asc' + | 'name_desc' + | 'cpu_count_asc' + | 'cpu_count_desc' + | 'memory_mb_asc' + | 'memory_mb_desc' + | 'created_at_asc' + | 'created_at_desc' + | 'updated_at_asc' + | 'updated_at_desc' + +export interface ListTeamTemplatesOptions { + cursor?: string + limit?: number + cpuCount?: number + memoryMB?: number + public?: boolean + search?: string + sort?: TemplatesSort +} + +export interface ListTeamTemplatesResult { + data: Array