diff --git a/README.md b/README.md index 2e1c523..824878f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ A lightweight, self-hosted Function-as-a-Service platform written in Go with Lua * **Execution History** - Monitor function executions and logs * **Beautiful Error Messages** - Human-friendly error messages with code context, line numbers, and actionable suggestions * **Web Dashboard** - Manage functions through a clean web interface -* **API Documentation** - Swagger UI available at `/docs` +* **GraphQL API** - Typed, introspectable management API with a GraphiQL playground at `/graphql` * **Lightweight** - Single binary, no external dependencies ## Screenshots @@ -265,20 +265,28 @@ The dashboard requires authentication via API key. You can: 1. **Auto-generate** (recommended) - Let Lunar generate a secure key on first run 2. **Set manually** - Provide your own key via the `API_KEY` environment variable -API calls can authenticate using either: +The management API is served over **GraphQL** at `/graphql` (with a GraphiQL +playground in the browser). Requests authenticate using either: - **Cookie** - Automatically handled by the dashboard after login - **Bearer token** - Include `Authorization: Bearer YOUR_API_KEY` header -Example API call with Bearer token: +Example GraphQL call with a Bearer token: ```bash -curl -H "Authorization: Bearer YOUR_API_KEY" http://localhost:3000/api/functions +curl -H "Authorization: Bearer YOUR_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"query":"{ functions(limit: 20, offset: 0) { nodes { id name } } }"}' \ + http://localhost:3000/graphql ``` Note: Function execution endpoints (`/fn/{id}`) do not require authentication. +The handful of endpoints that stay REST — cookie login/logout, the CLI device +authorization flow, and function execution — are documented in +[`docs/rest-endpoints.md`](docs/rest-endpoints.md). + ## CLI -Lunar ships a command-line client (`lunar-cli`) that is auto-generated from the OpenAPI spec, so it always stays in sync with the API. +Lunar ships a command-line client (`lunar-cli`) built on the server's GraphQL API, so it always stays in sync with the schema. ### Installation @@ -409,10 +417,13 @@ lunar-cli invoke --method POST --body - # read body from stdin ### Keeping the CLI in Sync with the API -The CLI commands are auto-generated from `internal/api/docs/openapi.yaml`. When the API changes, regenerate with: +The CLI talks to the server's GraphQL API (`/graphql`) using a thin +[hasura/go-graphql-client](https://github.com/hasura/go-graphql-client) wrapper. +The GraphQL schema is the single source of truth: the server won't compile until +every field has a resolver, and the CLI's queries are checked against the live +schema by introspection. After changing a command, rebuild with: ```bash -mise run generate-cli mise run build-cli ``` diff --git a/cmd/app.go b/cmd/app.go index 5abe0a9..6420fd8 100644 --- a/cmd/app.go +++ b/cmd/app.go @@ -14,6 +14,7 @@ import ( "github.com/dimiro1/lunar/internal/config" internalcron "github.com/dimiro1/lunar/internal/cron" "github.com/dimiro1/lunar/internal/engine" + "github.com/dimiro1/lunar/internal/graph" "github.com/dimiro1/lunar/internal/housekeeping" "github.com/dimiro1/lunar/internal/migrate" "github.com/dimiro1/lunar/internal/runner" @@ -79,6 +80,7 @@ func appOptions() fx.Option { engine.Module, internalcron.Module, housekeeping.Module, + graph.Module, api.Module, ) } diff --git a/docs/adr/0012-graphql-management-api.md b/docs/adr/0012-graphql-management-api.md new file mode 100644 index 0000000..d677282 --- /dev/null +++ b/docs/adr/0012-graphql-management-api.md @@ -0,0 +1,70 @@ +# 0012. GraphQL for the management API + +- Status: Accepted +- Date: 2026-06-03 + +## Context + +Lunar's management API (functions, versions, executions, tokens) was a +hand-written REST surface under `/api/*`, described by a hand-maintained +OpenAPI document at `internal/api/docs/openapi.yaml`. Nothing connected the two: +the spec was a *document* kept in step with the handlers by discipline, not by +the compiler, so the two could — and did — drift. The CLI was generated *from* +that spec (oapi-codegen for the client, a custom `lunar-cli/tools/gen` generator +for the Cobra commands), inheriting any drift the spec carried. + +Two concrete problems pushed us off this design: + +- **Overfetching.** `GET /api/functions` returned every function's full active + version — including the entire Lua source — plus its env and KV maps, just to + render a list of names and statuses. +- **No enforced contract.** A field added to a handler but not the spec (or vice + versa) compiled and shipped. A latent example surfaced during the migration: + the KV editor's request shape had drifted from what the REST handler accepted. + +## Decision + +We will serve the entire management API over **GraphQL** using +[`gqlgen`](https://github.com/99designs/gqlgen), with the schema in +`internal/graph/schema/*.graphqls` as the single source of truth. gqlgen +generates the resolver interfaces, so the Go compiler refuses to build until +every schema field has an implementation — drift becomes a compile error rather +than a review responsibility. `gqlgen.yml` binds GraphQL types directly to the +existing `internal/store` structs, so there are no duplicate DTOs. + +GraphQL is mounted at `POST /graphql` (behind the same auth middleware as the +old REST routes) with a public GraphiQL playground at `GET /graphql`, following +the per-subsystem `fx.Module` pattern from +[ADR-0006](0006-dependency-injection-with-fx.md). The frontend (`frontend/js/api.js`) +and the CLI (via `hasura/go-graphql-client`) both consume it; validation logic +shared by the resolvers lives in `internal/validation`. + +Two endpoints deliberately **stay REST**, because they do not fit a query +language: + +- `/fn/{id}` — public function invocation with arbitrary verbs, paths, request + bodies, and a verbatim response passthrough. +- `/api/auth/*` — login/logout (HttpOnly cookies) and the CLI device-authorization + flow, which runs *before* a caller is authenticated. + +We removed the REST `/api/*` management handlers, the hand-written +`openapi.yaml`, the Swagger `/docs` UI, and the oapi-codegen + `tools/gen` CLI +generators. + +## Consequences + +- The schema can no longer drift from the code: adding a field without a + resolver fails to compile, and removing one leaves dead code the compiler + flags. +- The overfetch is gone — list views select only the fields they render, and + env/KV/source are lazy field resolvers fetched only when asked for. +- Clients collapse multi-call detail views into a single query, and the CLI is + now hand-written Go (no codegen step) validated against the live schema by + introspection. +- We trade Swagger's familiarity and REST's HTTP-status semantics for GraphQL's + `200 + errors` model; clients translate the `errors` array, and the auth + middleware still returns a real HTTP 401 ahead of the resolver. +- Field resolvers can be N+1 if env/KV are ever selected across a list; at + SQLite scale this is fine, and dataloaders remain an option if it ever isn't. +- Timestamps are still carried as `Int`; introducing a dedicated + `Timestamp`/`Int64` scalar is deferred follow-up work. diff --git a/docs/adr/README.md b/docs/adr/README.md index 4e0eb1a..c20714f 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -29,3 +29,4 @@ to reverse-engineer it or interrupt the people who were there. | [0009](0009-lua-as-the-function-language.md) | Lua as the function language | Accepted | | [0010](0010-in-house-i18n.md) | In-house i18n with locale modules | Accepted | | [0011](0011-testing-strategy.md) | Layered testing strategy without a JS test runner | Accepted | +| [0012](0012-graphql-management-api.md) | GraphQL for the management API | Accepted | diff --git a/docs/rest-endpoints.md b/docs/rest-endpoints.md new file mode 100644 index 0000000..d330d9d --- /dev/null +++ b/docs/rest-endpoints.md @@ -0,0 +1,136 @@ +# REST endpoints + +Lunar's management API (functions, versions, executions, tokens) is served over +**GraphQL** at `/graphql` — see [ADR-0012](adr/0012-graphql-management-api.md) +and the GraphiQL playground at `GET /graphql` for that surface. + +A few endpoints stay REST because they don't fit a query language. They are +intentionally few, and — unlike the GraphQL schema, which the compiler keeps in +sync — they are documented here by hand. This file is that reference. + +All request and response bodies are JSON unless noted. + +## Cookie authentication (dashboard) + +Used by the web dashboard. The cookie carries the admin API key. + +### `POST /api/auth/login` + +No auth required. + +Request: + +```json +{ "apiKey": "" } +``` + +Responses: + +- `200` — `{ "success": true }`, plus a `Set-Cookie: auth_token=...` (HttpOnly, + SameSite=Strict, `Secure` when served over HTTPS, 1-day expiry). +- `400` — `{ "success": false, "error": "Invalid request body" }` +- `401` — `{ "success": false, "error": "Invalid API key" }` + +### `POST /api/auth/logout` + +No auth required. Clears the `auth_token` cookie. + +- `200` — `{ "success": true }` + +## Device authorization (CLI login) + +An OAuth-style device flow so the CLI can obtain an API token without the user +pasting one. The CLI calls `device-request`, the user approves in the dashboard +(which calls `device-approve`), and the CLI polls `device-token` until a token +is issued. See `lunar-cli login`. + +### `POST /api/auth/device-request` + +No auth required. Starts a flow. + +- `200`: + +```json +{ + "device_code": "", + "user_code": "ABCD2345", + "approval_url": "/#!/device-approve/", + "expires_in": 300, + "interval": 5 +} +``` + +`expires_in` and `interval` are seconds; the device code lives for 5 minutes. + +### `GET /api/auth/device-token?code=` + +No auth required. Polled by the CLI every `interval` seconds. + +- `200` — `{ "status": "pending" }` while waiting, + `{ "status": "denied" }` if rejected, or + `{ "status": "approved", "token": "" }` once approved. +- `400` — missing `code`. +- `404` — unknown or expired `code`. + +### `GET /api/auth/device-approve?code=` + +**Auth required** (dashboard cookie/bearer). Returns the pending request so the +SPA can render the approval screen. + +- `200`: + +```json +{ + "device_code": "", + "user_code": "ABCD2345", + "status": "pending", + "expires_at": 1780000000 +} +``` + +- `400` — missing `code`; `404` — unknown or expired `code`. + +### `POST /api/auth/device-approve` + +**Auth required.** The dashboard approves or denies a pending request. On +approval a new API token named `CLI ()` is created and handed to the +polling CLI. + +Request: + +```json +{ "device_code": "", "action": "allow" } +``` + +`action` is `"allow"` or `"deny"`. + +- `200` — `{ "success": true }` +- `400` — missing `device_code` or invalid `action`. +- `404` — unknown or expired `device_code`. + +## Function execution + +### ` /fn/{function_id}` and `/fn/{function_id}/{path...}` + +**No auth required** — functions are public. This is a passthrough: any HTTP +method, path suffix, headers, query, and body are delivered to the function as +its event, and the function's HTTP response (status, headers, body) is relayed +back verbatim. + +Request headers Lunar interprets: + +- `X-Trigger: cron` records the execution's trigger as `cron` (default is + `http`). + +Response headers Lunar adds: + +- `X-Function-Id`, `X-Function-Version-Id`, `X-Execution-Id` +- `X-Execution-Duration-Ms` + +Status codes: + +- `2xx`/whatever the function returns on success (defaults to `200` and + `Content-Type: application/json` if the function doesn't set them). +- `404` — function not found. +- `403` — function disabled. +- `500` — no active version, or the function errored during execution. diff --git a/frontend/js/api.js b/frontend/js/api.js index 4a101c7..9fc0f67 100644 --- a/frontend/js/api.js +++ b/frontend/js/api.js @@ -58,6 +58,234 @@ m.request = function (options) { }); }; +/** + * Executes a GraphQL operation against /graphql. + * + * GraphQL returns HTTP 200 with an `errors` array for resolver/validation + * failures, so those are surfaced here as a thrown Error (message from the + * first error). HTTP-level failures (e.g. an unauthenticated 401 from the auth + * middleware that fronts /graphql) reject through the global m.request handler + * above, which redirects to /login — exactly as the REST calls did. + * + * @param {string} query - GraphQL query or mutation document + * @param {Object} [variables] - GraphQL variables + * @returns {Promise<*>} The `data` payload of the response + * @throws {Error} When the response contains GraphQL errors + */ +const gqlRequest = async (query, variables = {}) => { + const res = await m.request({ + method: "POST", + url: "/graphql", + body: { query, variables }, + credentials: "same-origin", + }); + if (res && res.errors && res.errors.length > 0) { + const error = new Error(res.errors[0].message); + error.graphqlErrors = res.errors; + throw error; + } + return res ? res.data : null; +}; + +/** + * Maps a GraphQL FunctionVersion to the snake_case shape the views consume. + * Fields a query did not select are simply left undefined. + * @param {Object} v - GraphQL FunctionVersion + * @returns {Object} snake_case version + */ +const mapVersion = (v) => + v == null ? v : { + id: v.id, + function_id: v.functionId, + version: v.version, + code: v.code, + created_at: v.createdAt, + created_by: v.createdBy, + is_active: v.isActive, + }; + +/** + * Maps a GraphQL Function to the snake_case shape the views consume. Works for + * both trimmed (list) and full (detail) selections; absent fields stay undefined. + * @param {Object} f - GraphQL Function + * @returns {Object} snake_case function + */ +const mapFunction = (f) => + f == null ? f : { + id: f.id, + name: f.name, + description: f.description, + disabled: f.disabled, + retention_days: f.retentionDays, + cron_schedule: f.cronSchedule, + cron_status: f.cronStatus, + save_response: f.saveResponse, + created_at: f.createdAt, + updated_at: f.updatedAt, + active_version: f.activeVersion + ? mapVersion(f.activeVersion) + : f.activeVersion, + env_vars: f.envVars, + scoped_data: f.scopedData, + global_data: f.globalData, + }; + +/** Maps a GraphQL Execution to the snake_case shape the views consume. */ +const mapExecution = (e) => + e == null ? e : { + id: e.id, + function_id: e.functionId, + function_version_id: e.functionVersionId, + status: e.status, + duration_ms: e.durationMs, + error_message: e.errorMessage, + event_json: e.eventJson, + response_json: e.responseJson, + trigger: e.trigger, + created_at: e.createdAt, + }; + +/** Maps a GraphQL AIRequest to the snake_case shape the views consume. */ +const mapAIRequest = (a) => + a == null ? a : { + id: a.id, + execution_id: a.executionId, + provider: a.provider, + model: a.model, + endpoint: a.endpoint, + request_json: a.requestJson, + response_json: a.responseJson, + status: a.status, + error_message: a.errorMessage, + input_tokens: a.inputTokens, + output_tokens: a.outputTokens, + duration_ms: a.durationMs, + created_at: a.createdAt, + }; + +/** Maps a GraphQL EmailRequest to the snake_case shape the views consume. */ +const mapEmailRequest = (em) => + em == null ? em : { + id: em.id, + execution_id: em.executionId, + from: em.from, + to: em.to, + subject: em.subject, + has_text: em.hasText, + has_html: em.hasHtml, + request_json: em.requestJson, + response_json: em.responseJson, + status: em.status, + error_message: em.errorMessage, + email_id: em.emailId, + duration_ms: em.durationMs, + created_at: em.createdAt, + }; + +/** Maps a GraphQL LogEntry to the snake_case shape the views consume. */ +const mapLog = (l) => + l == null + ? l + : { level: l.level, message: l.message, created_at: l.createdAt }; + +/** Maps a GraphQL APIToken to the snake_case shape the views consume. */ +const mapToken = (tk) => + tk == null ? tk : { + id: tk.id, + name: tk.name, + created_at: tk.createdAt, + last_used: tk.lastUsed, + revoked: tk.revoked, + }; + +/** Maps a GraphQL NextRun to the snake_case shape the views consume. */ +const mapNextRun = (n) => + n == null ? n : { + has_schedule: n.hasSchedule, + cron_schedule: n.cronSchedule, + cron_status: n.cronStatus, + is_paused: n.isPaused, + next_run: n.nextRun, + next_run_human: n.nextRunHuman, + }; + +/** Maps a GraphQL VersionDiff to the snake_case shape the diff view consumes. */ +const mapDiff = (d) => + d == null ? d : { + old_version: d.oldVersion, + new_version: d.newVersion, + diff: (d.lines || []).map((l) => ({ + line_type: l.lineType, + content: l.content, + old_line: l.oldLine, + new_line: l.newLine, + })), + }; + +/** + * Builds a GraphQL UpdateFunctionInput from the snake_case update object the + * views pass, including only the fields actually present. + * @param {Object} data - snake_case update fields + * @returns {Object} camelCase UpdateFunctionInput + */ +const toUpdateFunctionInput = (data) => { + const input = {}; + if (data.name !== undefined) input.name = data.name; + if (data.description !== undefined) input.description = data.description; + if (data.code !== undefined) input.code = data.code; + if (data.disabled !== undefined) input.disabled = data.disabled; + if (data.retention_days !== undefined) { + input.retentionDays = data.retention_days; + } + if (data.cron_schedule !== undefined) input.cronSchedule = data.cron_schedule; + if (data.cron_status !== undefined) input.cronStatus = data.cron_status; + if (data.save_response !== undefined) input.saveResponse = data.save_response; + return input; +}; + +// Shared GraphQL field selections. Defined once so the standalone queries and +// the combined (multi-resource) queries below always request the same shape — +// avoiding drift between, say, `functions.get` and `functions.getWithNextRun`. +const PAGE_INFO = `total limit offset`; +const VERSION_FULL_FIELDS = + `id functionId version code createdAt createdBy isActive`; +const VERSION_SUMMARY_FIELDS = + `id functionId version createdAt createdBy isActive`; +// Full function detail (settings/detail views): includes active version code and +// the env/KV maps. +const FUNCTION_DETAIL_FIELDS = ` + id name description disabled + retentionDays cronSchedule cronStatus saveResponse createdAt updatedAt + activeVersion { ${VERSION_FULL_FIELDS} } + envVars scopedData globalData +`; +// Lightweight function selection for list rows and detail-page headers: no code, +// env, or KV — just enough to render a name/status/active version number. +const FUNCTION_SUMMARY_FIELDS = + `id name description disabled activeVersion { version }`; +const EXECUTION_FULL_FIELDS = ` + id functionId functionVersionId status durationMs + errorMessage eventJson responseJson trigger createdAt +`; +const EXECUTION_SUMMARY_FIELDS = ` + id functionId functionVersionId status durationMs + errorMessage trigger createdAt +`; +const LOG_FIELDS = `level message createdAt`; +const AI_REQUEST_FIELDS = ` + id executionId provider model endpoint requestJson responseJson + status errorMessage inputTokens outputTokens durationMs createdAt +`; +const EMAIL_REQUEST_FIELDS = ` + id executionId from to subject hasText hasHtml requestJson + responseJson status errorMessage emailId durationMs createdAt +`; +const NEXT_RUN_FIELDS = + `hasSchedule cronSchedule cronStatus isPaused nextRun nextRunHuman`; +const TOKEN_FIELDS = `id name createdAt lastUsed revoked`; +const DIFF_FIELDS = + `oldVersion newVersion lines { lineType oldLine newLine content }`; + /** * API client for the lunar Dashboard. * @namespace @@ -117,10 +345,13 @@ export const API = { }, tokens: { - list: () => apiRequest({ method: "GET", url: "/api/tokens" }), + list: () => + gqlRequest( + `query { apiTokens { ${TOKEN_FIELDS} } }`, + ).then((data) => ({ tokens: data.apiTokens.map(mapToken) })), revoke: (id) => - apiRequest({ method: "POST", url: `/api/tokens/${id}/revoke` }), + gqlRequest(`mutation ($id: ID!) { revokeApiToken(id: $id) }`, { id }), }, /** @@ -135,17 +366,97 @@ export const API = { * @returns {Promise} Paginated list of functions */ list: (limit = 20, offset = 0) => - apiRequest({ - method: "GET", - url: `/api/functions?limit=${limit}&offset=${offset}`, - }), + gqlRequest( + `query ($limit: Int!, $offset: Int!) { + functions(limit: $limit, offset: $offset) { + nodes { ${FUNCTION_SUMMARY_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { limit, offset }, + ).then((data) => ({ + functions: data.functions.nodes.map(mapFunction), + pagination: data.functions.pageInfo, + })), /** * Gets a single function by ID. * @param {string} id - Function ID * @returns {Promise} The function */ - get: (id) => apiRequest({ method: "GET", url: `/api/functions/${id}` }), + get: (id) => + gqlRequest( + `query ($id: ID!) { + function(id: $id) { ${FUNCTION_DETAIL_FIELDS} } + }`, + { id }, + ).then((data) => mapFunction(data.function)), + + /** + * Gets a function together with its next scheduled run in one round-trip. + * Used by the settings view, which needs both on load. + * @param {string} id - Function ID + * @returns {Promise<{func: LunarFunction, nextRun: Object}>} + */ + getWithNextRun: (id) => + gqlRequest( + `query ($id: ID!) { + function(id: $id) { ${FUNCTION_DETAIL_FIELDS} } + nextRun(functionId: $id) { ${NEXT_RUN_FIELDS} } + }`, + { id }, + ).then((data) => ({ + func: mapFunction(data.function), + nextRun: mapNextRun(data.nextRun), + })), + + /** + * Gets a function (header fields) together with a page of its versions in + * one round-trip. Used by the versions view on load. + * @param {string} id - Function ID + * @param {number} [limit=20] + * @param {number} [offset=0] + * @returns {Promise<{func: LunarFunction, versions: FunctionVersion[], pagination: Object}>} + */ + getWithVersions: (id, limit = 20, offset = 0) => + gqlRequest( + `query ($id: ID!, $limit: Int!, $offset: Int!) { + function(id: $id) { ${FUNCTION_SUMMARY_FIELDS} } + versions(functionId: $id, limit: $limit, offset: $offset) { + nodes { ${VERSION_SUMMARY_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { id, limit, offset }, + ).then((data) => ({ + func: mapFunction(data.function), + versions: data.versions.nodes.map(mapVersion), + pagination: data.versions.pageInfo, + })), + + /** + * Gets a function (header fields) together with a page of its executions in + * one round-trip. Used by the executions view on load. + * @param {string} id - Function ID + * @param {number} [limit=20] + * @param {number} [offset=0] + * @returns {Promise<{func: LunarFunction, executions: Execution[], pagination: Object}>} + */ + getWithExecutions: (id, limit = 20, offset = 0) => + gqlRequest( + `query ($id: ID!, $limit: Int!, $offset: Int!) { + function(id: $id) { ${FUNCTION_SUMMARY_FIELDS} } + executions(functionId: $id, limit: $limit, offset: $offset) { + nodes { ${EXECUTION_SUMMARY_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { id, limit, offset }, + ).then((data) => ({ + func: mapFunction(data.function), + executions: data.executions.nodes.map(mapExecution), + pagination: data.executions.pageInfo, + })), /** * Creates a new function. @@ -156,7 +467,18 @@ export const API = { * @returns {Promise} The created function */ create: (data) => - apiRequest({ method: "POST", url: "/api/functions", body: data }), + gqlRequest( + `mutation ($input: CreateFunctionInput!) { + createFunction(input: $input) { id } + }`, + { + input: { + name: data.name, + description: data.description, + code: data.code, + }, + }, + ).then((d) => mapFunction(d.createFunction)), /** * Updates an existing function. @@ -169,7 +491,12 @@ export const API = { * @returns {Promise} The updated function */ update: (id, data) => - apiRequest({ method: "PUT", url: `/api/functions/${id}`, body: data }), + gqlRequest( + `mutation ($id: ID!, $input: UpdateFunctionInput!) { + updateFunction(id: $id, input: $input) { id } + }`, + { id, input: toUpdateFunctionInput(data) }, + ).then((d) => mapFunction(d.updateFunction)), /** * Deletes a function. @@ -177,7 +504,7 @@ export const API = { * @returns {Promise} */ delete: (id) => - apiRequest({ method: "DELETE", url: `/api/functions/${id}` }), + gqlRequest(`mutation ($id: ID!) { deleteFunction(id: $id) }`, { id }), /** * Updates environment variables for a function. @@ -186,11 +513,12 @@ export const API = { * @returns {Promise} The updated function */ updateEnv: (id, env_vars) => - apiRequest({ - method: "PUT", - url: `/api/functions/${id}/env`, - body: { env_vars }, - }), + gqlRequest( + `mutation ($id: ID!, $env: Map!) { + setFunctionEnv(id: $id, env: $env) { id } + }`, + { id, env: env_vars }, + ), /** * Updates kv store entries for a function. @@ -200,20 +528,18 @@ export const API = { * @param {Array<{key: string, value: string}>} updateData.kvEntries - KV entries to update * @returns {Promise} The updated function */ - updateKvStore: (id, updateData) => - apiRequest({ - method: "POST", - url: `/api/functions/${id}/kv`, - body: updateData, - }), - - /** - * Gets the next scheduled run time for a function. - * @param {string} id - Function ID - * @returns {Promise} Next run information - */ - getNextRun: (id) => - apiRequest({ method: "GET", url: `/api/functions/${id}/next-run` }), + updateKvStore: (id, updateData) => { + const kv = {}; + (updateData.kvEntries || []).forEach((entry) => { + kv[entry.key] = entry.value; + }); + return gqlRequest( + `mutation ($id: ID!, $kv: Map!, $global: Boolean!) { + setFunctionKv(id: $id, kv: $kv, global: $global) { id } + }`, + { id, kv, global: !!updateData.global }, + ); + }, }, /** @@ -229,11 +555,18 @@ export const API = { * @returns {Promise} Paginated list of versions */ list: (functionId, limit = 20, offset = 0) => - apiRequest({ - method: "GET", - url: - `/api/functions/${functionId}/versions?limit=${limit}&offset=${offset}`, - }), + gqlRequest( + `query ($id: ID!, $limit: Int!, $offset: Int!) { + versions(functionId: $id, limit: $limit, offset: $offset) { + nodes { ${VERSION_SUMMARY_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { id: functionId, limit, offset }, + ).then((data) => ({ + versions: data.versions.nodes.map(mapVersion), + pagination: data.versions.pageInfo, + })), /** * Gets a specific version. @@ -242,10 +575,12 @@ export const API = { * @returns {Promise} The version */ get: (functionId, version) => - apiRequest({ - method: "GET", - url: `/api/functions/${functionId}/versions/${version}`, - }), + gqlRequest( + `query ($id: ID!, $version: Int!) { + version(functionId: $id, version: $version) { ${VERSION_FULL_FIELDS} } + }`, + { id: functionId, version }, + ).then((data) => mapVersion(data.version)), /** * Activates a specific version. @@ -254,23 +589,34 @@ export const API = { * @returns {Promise} */ activate: (functionId, versionId) => - apiRequest({ - method: "POST", - url: `/api/functions/${functionId}/versions/${versionId}/activate`, - }), + gqlRequest( + `mutation ($id: ID!, $versionId: ID!) { + activateVersion(functionId: $id, versionId: $versionId) { id } + }`, + { id: functionId, versionId }, + ), /** - * Gets a diff between two versions. + * Gets a function (header fields) together with a version diff in one + * round-trip. Used by the version-diff view on load. * @param {string} functionId - Function ID * @param {number} v1 - First version number * @param {number} v2 - Second version number - * @returns {Promise} The diff result + * @returns {Promise<{func: LunarFunction, diff: DiffResponse}>} */ - diff: (functionId, v1, v2) => - apiRequest({ - method: "GET", - url: `/api/functions/${functionId}/diff/${v1}/${v2}`, - }), + diffWithFunction: (functionId, v1, v2) => + gqlRequest( + `query ($id: ID!, $v1: Int!, $v2: Int!) { + function(id: $id) { ${FUNCTION_SUMMARY_FIELDS} } + versionDiff(functionId: $id, oldVersion: $v1, newVersion: $v2) { + ${DIFF_FIELDS} + } + }`, + { id: functionId, v1, v2 }, + ).then((data) => ({ + func: mapFunction(data.function), + diff: mapDiff(data.versionDiff), + })), /** * Deletes a specific version. @@ -279,10 +625,12 @@ export const API = { * @returns {Promise} */ delete: (functionId, versionId) => - apiRequest({ - method: "DELETE", - url: `/api/functions/${functionId}/versions/${versionId}`, - }), + gqlRequest( + `mutation ($id: ID!, $versionId: ID!) { + deleteVersion(functionId: $id, versionId: $versionId) + }`, + { id: functionId, versionId }, + ), }, /** @@ -298,19 +646,83 @@ export const API = { * @returns {Promise} Paginated list of executions */ list: (functionId, limit = 20, offset = 0) => - apiRequest({ - method: "GET", - url: - `/api/functions/${functionId}/executions?limit=${limit}&offset=${offset}`, - }), + gqlRequest( + `query ($id: ID!, $limit: Int!, $offset: Int!) { + executions(functionId: $id, limit: $limit, offset: $offset) { + nodes { ${EXECUTION_SUMMARY_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { id: functionId, limit, offset }, + ).then((data) => ({ + executions: data.executions.nodes.map(mapExecution), + pagination: data.executions.pageInfo, + })), /** - * Gets a specific execution. - * @param {string} executionId - Execution ID - * @returns {Promise} The execution + * Gets an execution together with its parent function, logs, AI requests, + * and email requests in a single round-trip — used by the execution-detail + * view, which previously fired five separate requests on load. Pagination of + * the individual sub-lists still uses the dedicated methods below. + * @param {string} id - Execution ID + * @param {Object} [opts] - Initial pagination for each sub-list + * @returns {Promise} { execution, func, logs, logsTotal, aiRequests, + * aiRequestsTotal, emailRequests, emailRequestsTotal } */ - get: (executionId) => - apiRequest({ method: "GET", url: `/api/executions/${executionId}` }), + getDetail: (id, opts = {}) => { + const { + logsLimit = 20, + logsOffset = 0, + aiLimit = 20, + aiOffset = 0, + emailLimit = 20, + emailOffset = 0, + } = opts; + return gqlRequest( + `query ( + $id: ID!, $logsLimit: Int!, $logsOffset: Int!, + $aiLimit: Int!, $aiOffset: Int!, $emailLimit: Int!, $emailOffset: Int! + ) { + execution(id: $id) { + ${EXECUTION_FULL_FIELDS} + function { ${FUNCTION_SUMMARY_FIELDS} } + } + executionLogs(executionId: $id, limit: $logsLimit, offset: $logsOffset) { + nodes { ${LOG_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + executionAiRequests(executionId: $id, limit: $aiLimit, offset: $aiOffset) { + nodes { ${AI_REQUEST_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + executionEmailRequests(executionId: $id, limit: $emailLimit, offset: $emailOffset) { + nodes { ${EMAIL_REQUEST_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { + id, + logsLimit, + logsOffset, + aiLimit, + aiOffset, + emailLimit, + emailOffset, + }, + ).then((data) => { + const exec = data.execution; + return { + execution: mapExecution(exec), + func: exec ? mapFunction(exec.function) : null, + logs: data.executionLogs.nodes.map(mapLog), + logsTotal: data.executionLogs.pageInfo?.total || 0, + aiRequests: data.executionAiRequests.nodes.map(mapAIRequest), + aiRequestsTotal: data.executionAiRequests.pageInfo?.total || 0, + emailRequests: data.executionEmailRequests.nodes.map(mapEmailRequest), + emailRequestsTotal: data.executionEmailRequests.pageInfo?.total || 0, + }; + }); + }, /** * Gets logs for an execution. @@ -320,11 +732,18 @@ export const API = { * @returns {Promise} Paginated list of logs */ getLogs: (executionId, limit = 20, offset = 0) => - apiRequest({ - method: "GET", - url: - `/api/executions/${executionId}/logs?limit=${limit}&offset=${offset}`, - }), + gqlRequest( + `query ($id: ID!, $limit: Int!, $offset: Int!) { + executionLogs(executionId: $id, limit: $limit, offset: $offset) { + nodes { ${LOG_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { id: executionId, limit, offset }, + ).then((data) => ({ + logs: data.executionLogs.nodes.map(mapLog), + pagination: data.executionLogs.pageInfo, + })), /** * Gets AI requests for an execution. @@ -334,11 +753,18 @@ export const API = { * @returns {Promise} Paginated list of AI requests */ getAIRequests: (executionId, limit = 20, offset = 0) => - apiRequest({ - method: "GET", - url: - `/api/executions/${executionId}/ai-requests?limit=${limit}&offset=${offset}`, - }), + gqlRequest( + `query ($id: ID!, $limit: Int!, $offset: Int!) { + executionAiRequests(executionId: $id, limit: $limit, offset: $offset) { + nodes { ${AI_REQUEST_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { id: executionId, limit, offset }, + ).then((data) => ({ + ai_requests: data.executionAiRequests.nodes.map(mapAIRequest), + pagination: data.executionAiRequests.pageInfo, + })), /** * Gets email requests for an execution. @@ -348,11 +774,18 @@ export const API = { * @returns {Promise} Paginated list of email requests */ getEmailRequests: (executionId, limit = 20, offset = 0) => - apiRequest({ - method: "GET", - url: - `/api/executions/${executionId}/email-requests?limit=${limit}&offset=${offset}`, - }), + gqlRequest( + `query ($id: ID!, $limit: Int!, $offset: Int!) { + executionEmailRequests(executionId: $id, limit: $limit, offset: $offset) { + nodes { ${EMAIL_REQUEST_FIELDS} } + pageInfo { ${PAGE_INFO} } + } + }`, + { id: executionId, limit, offset }, + ).then((data) => ({ + email_requests: data.executionEmailRequests.nodes.map(mapEmailRequest), + pagination: data.executionEmailRequests.pageInfo, + })), }, /** diff --git a/frontend/js/views/execution-detail.js b/frontend/js/views/execution-detail.js index f08b980..2c2e093 100644 --- a/frontend/js/views/execution-detail.js +++ b/frontend/js/views/execution-detail.js @@ -148,36 +148,24 @@ export const ExecutionDetail = { loadExecution: async (id) => { ExecutionDetail.loading = true; try { - const [execution, logsData, aiRequestsData, emailRequestsData] = - await Promise.all([ - API.executions.get(id), - API.executions.getLogs( - id, - ExecutionDetail.logsLimit, - ExecutionDetail.logsOffset, - ), - API.executions.getAIRequests( - id, - ExecutionDetail.aiRequestsLimit, - ExecutionDetail.aiRequestsOffset, - ), - API.executions.getEmailRequests( - id, - ExecutionDetail.emailRequestsLimit, - ExecutionDetail.emailRequestsOffset, - ), - ]); - ExecutionDetail.execution = execution; - ExecutionDetail.logs = logsData.logs || []; - ExecutionDetail.logsTotal = logsData.pagination?.total || 0; - ExecutionDetail.aiRequests = aiRequestsData.ai_requests || []; - ExecutionDetail.aiRequestsTotal = aiRequestsData.pagination?.total || 0; - ExecutionDetail.emailRequests = emailRequestsData.email_requests || []; - ExecutionDetail.emailRequestsTotal = - emailRequestsData.pagination?.total || 0; - - // Load function details - ExecutionDetail.func = await API.functions.get(execution.function_id); + // One round-trip fetches the execution, its parent function, logs, and + // AI/email requests together (see API.executions.getDetail). + const data = await API.executions.getDetail(id, { + logsLimit: ExecutionDetail.logsLimit, + logsOffset: ExecutionDetail.logsOffset, + aiLimit: ExecutionDetail.aiRequestsLimit, + aiOffset: ExecutionDetail.aiRequestsOffset, + emailLimit: ExecutionDetail.emailRequestsLimit, + emailOffset: ExecutionDetail.emailRequestsOffset, + }); + ExecutionDetail.execution = data.execution; + ExecutionDetail.func = data.func; + ExecutionDetail.logs = data.logs; + ExecutionDetail.logsTotal = data.logsTotal; + ExecutionDetail.aiRequests = data.aiRequests; + ExecutionDetail.aiRequestsTotal = data.aiRequestsTotal; + ExecutionDetail.emailRequests = data.emailRequests; + ExecutionDetail.emailRequestsTotal = data.emailRequestsTotal; } catch (e) { console.error("Failed to load execution:", e); } finally { diff --git a/frontend/js/views/function-executions.js b/frontend/js/views/function-executions.js index f5382c5..351757e 100644 --- a/frontend/js/views/function-executions.js +++ b/frontend/js/views/function-executions.js @@ -92,17 +92,15 @@ export const FunctionExecutions = { loadData: async (id) => { FunctionExecutions.loading = true; try { - const [func, executions] = await Promise.all([ - API.functions.get(id), - API.executions.list( + const { func, executions, pagination } = await API.functions + .getWithExecutions( id, FunctionExecutions.executionsLimit, FunctionExecutions.executionsOffset, - ), - ]); + ); FunctionExecutions.func = func; - FunctionExecutions.executions = executions.executions || []; - FunctionExecutions.executionsTotal = executions.pagination?.total || 0; + FunctionExecutions.executions = executions || []; + FunctionExecutions.executionsTotal = pagination?.total || 0; } catch (e) { console.error("Failed to load function:", e); } finally { diff --git a/frontend/js/views/function-settings.js b/frontend/js/views/function-settings.js index 0903a9a..8c8fa68 100644 --- a/frontend/js/views/function-settings.js +++ b/frontend/js/views/function-settings.js @@ -161,12 +161,9 @@ export const FunctionSettings = { loadFunction: async (id) => { FunctionSettings.loading = true; try { - const [func, nextRunInfo] = await Promise.all([ - API.functions.get(id), - API.functions.getNextRun(id), - ]); + const { func, nextRun } = await API.functions.getWithNextRun(id); FunctionSettings.func = func; - FunctionSettings.nextRunInfo = nextRunInfo; + FunctionSettings.nextRunInfo = nextRun; FunctionSettings.editedName = null; FunctionSettings.editedDescription = null; FunctionSettings.editedDisabled = null; diff --git a/frontend/js/views/function-versions.js b/frontend/js/views/function-versions.js index 8eb795c..a076478 100644 --- a/frontend/js/views/function-versions.js +++ b/frontend/js/views/function-versions.js @@ -109,17 +109,15 @@ export const FunctionVersions = { loadData: async (id) => { FunctionVersions.loading = true; try { - const [func, versions] = await Promise.all([ - API.functions.get(id), - API.versions.list( + const { func, versions, pagination } = await API.functions + .getWithVersions( id, FunctionVersions.versionsLimit, FunctionVersions.versionsOffset, - ), - ]); + ); FunctionVersions.func = func; - FunctionVersions.versions = versions.versions || []; - FunctionVersions.versionsTotal = versions.pagination?.total || 0; + FunctionVersions.versions = versions || []; + FunctionVersions.versionsTotal = pagination?.total || 0; } catch (e) { console.error("Failed to load function:", e); } finally { diff --git a/frontend/js/views/version-diff.js b/frontend/js/views/version-diff.js index 6037788..72cfa78 100644 --- a/frontend/js/views/version-diff.js +++ b/frontend/js/views/version-diff.js @@ -72,12 +72,13 @@ export const VersionDiff = { loadData: async (functionId, v1, v2) => { VersionDiff.loading = true; try { - const [func, diffData] = await Promise.all([ - API.functions.get(functionId), - API.versions.diff(functionId, v1, v2), - ]); + const { func, diff } = await API.versions.diffWithFunction( + functionId, + v1, + v2, + ); VersionDiff.func = func; - VersionDiff.diffData = diffData; + VersionDiff.diffData = diff; } catch (e) { console.error("Failed to load diff:", e); } finally { diff --git a/go.mod b/go.mod index 7e7d4f8..6dddd87 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/dimiro1/lunar go 1.26.0 require ( + github.com/99designs/gqlgen v0.17.90 github.com/caarlos0/env/v11 v11.4.1 github.com/chromedp/chromedp v0.14.2 github.com/golang-migrate/migrate/v4 v4.19.1 @@ -11,28 +12,42 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/rs/xid v1.6.0 github.com/sergi/go-diff v1.4.0 + github.com/vektah/gqlparser/v2 v2.5.33 github.com/yuin/gopher-lua v1.1.1 go.uber.org/fx v1.24.0 modernc.org/sqlite v1.45.0 ) require ( + github.com/agnivade/levenshtein v1.2.1 // indirect github.com/chromedp/cdproto v0.0.0-20250724212937-08a3db8b4327 // indirect github.com/chromedp/sysutil v1.1.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/ws v1.4.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/goccy/go-yaml v1.19.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/mattn/go-isatty v0.0.21 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/sosodev/duration v1.4.0 // indirect + github.com/urfave/cli/v3 v3.8.0 // indirect go.uber.org/dig v1.19.0 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a // indirect - golang.org/x/sys v0.41.0 // indirect + golang.org/x/mod v0.33.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.35.0 // indirect + golang.org/x/tools v0.42.0 // indirect modernc.org/libc v1.67.7 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect ) + +tool github.com/99designs/gqlgen diff --git a/go.sum b/go.sum index 89dee66..573be85 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,15 @@ +github.com/99designs/gqlgen v0.17.90 h1:wSv6blm/PoplU6QoNw83EcQpNtC0HX3/+44vITJOzpk= +github.com/99designs/gqlgen v0.17.90/go.mod h1:GqYrEwYsqCG8VaOsq2kJUCUKwAE1T+u2i+Nj7NtXiVI= +github.com/PuerkitoBio/goquery v1.12.0 h1:pAcL4g3WRXekcB9AU/y1mbKez2dbY2AajVhtkO8RIBo= +github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YFofScC4q/hIpQ= +github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= +github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= +github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/caarlos0/env/v11 v11.4.1 h1:fYwH0sWEsBSMPG7t4e/PEfTFzrWrpjyygXyUnWiSwEw= github.com/caarlos0/env/v11 v11.4.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U= github.com/chromedp/cdproto v0.0.0-20250724212937-08a3db8b4327 h1:UQ4AU+BGti3Sy/aLU8KVseYKNALcX9UXY6DfpwQ6J8E= @@ -10,22 +22,32 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2 h1:iizUGZ9pEquQS5jTGkh4AqeeHCMbfbjeb0zMt0aEFzs= github.com/go-json-experiment/json v0.0.0-20250725192818-e39067aee2d2/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs= github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA= github.com/golang-migrate/migrate/v4 v4.19.1/go.mod h1:CTcgfjxhaUtsLipnLoQRWCrjYXycRz/g5+RWDuYgPrE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -35,8 +57,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= +github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= @@ -54,10 +76,16 @@ github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sosodev/duration v1.4.0 h1:35ed0KiVFriGHHzZZJaZLgmTEEICIyt8Sx0RQfj9IjE= +github.com/sosodev/duration v1.4.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/urfave/cli/v3 v3.8.0 h1:XqKPrm0q4P0q5JpoclYoCAv0/MIvH/jZ2umzuf8pNTI= +github.com/urfave/cli/v3 v3.8.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= +github.com/vektah/gqlparser/v2 v2.5.33 h1:lRp8aIeNUNbimf/axZd7ETg24q06hBtPaas+TcvI/7E= +github.com/vektah/gqlparser/v2 v2.5.33/go.mod h1:c1I28gSOVNzlfc4WuDlqU7voQnsqI6OG2amkBAFmgts= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4= @@ -74,11 +102,15 @@ golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a h1:ovFr6Z0MNmU7nH8VaX5xqw+05 golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA= golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/gqlgen.yml b/gqlgen.yml new file mode 100644 index 0000000..559b1d2 --- /dev/null +++ b/gqlgen.yml @@ -0,0 +1,115 @@ +# gqlgen configuration for the Lunar GraphQL API. +# +# The GraphQL schema (internal/graph/schema/*.graphqls) is the source of truth. +# Running `mise run generate-graphql` (go tool gqlgen generate) regenerates the +# executable schema, models, and resolver stubs. Because resolvers are generated +# as Go interfaces, the compiler refuses to build until every schema field has an +# implementation — so the API can never silently drift from the schema. +schema: + - internal/graph/schema/*.graphqls + +# Where the generated executable schema (the runtime) is written. +exec: + filename: internal/graph/generated.go + package: graph + +# Where models that have no hand-written/bound Go type are generated. Types bound +# in the `models:` section below (or owned elsewhere in the codebase) are NOT +# regenerated here. +model: + filename: internal/graph/model/models_gen.go + package: model + +# Resolvers are generated one file per schema file (follow-schema). The root +# Resolver struct lives in internal/graph/resolver.go (hand-written, holds deps). +resolver: + layout: follow-schema + dir: internal/graph + package: graph + filename_template: "{name}.resolvers.go" + +# Generate value slices ([]T) instead of pointer slices ([]*T) for list fields, +# which matches how the store package returns value-type slices. +omit_slice_element_pointers: true + +# Bind GraphQL types to the existing domain types in internal/store so resolvers +# return store values directly instead of mapping to duplicate DTOs. +models: + ID: + model: + - github.com/99designs/gqlgen/graphql.ID + - github.com/99designs/gqlgen/graphql.Int + Int: + model: + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + Map: + model: github.com/dimiro1/lunar/internal/graph/model.StringMap + Function: + model: github.com/dimiro1/lunar/internal/store.FunctionWithActiveVersion + fields: + # Relation/derived fields resolved lazily from the store, so only queries + # that select them do the work (env/KV are the original overfetch fix; + # versions/executions/nextRun are graph-traversal edges). + versions: + resolver: true + executions: + resolver: true + nextRun: + resolver: true + envVars: + resolver: true + scopedData: + resolver: true + globalData: + resolver: true + # The store carries cron_status as *string; a field resolver coerces it to + # the CronStatus enum (mapping an empty/absent value to null). + cronStatus: + resolver: true + FunctionVersion: + model: github.com/dimiro1/lunar/internal/store.FunctionVersion + fields: + # Reverse edge back to the owning function. + function: + resolver: true + PageInfo: + model: github.com/dimiro1/lunar/internal/store.PaginationInfo + Execution: + model: github.com/dimiro1/lunar/internal/store.Execution + fields: + # Relation edges resolved from the execution's foreign keys / id, all lazy. + function: + resolver: true + version: + resolver: true + logs: + resolver: true + aiRequests: + resolver: true + emailRequests: + resolver: true + AIRequest: + model: github.com/dimiro1/lunar/internal/store.AIRequest + fields: + execution: + resolver: true + EmailRequest: + model: github.com/dimiro1/lunar/internal/store.EmailRequest + fields: + execution: + resolver: true + APIToken: + model: github.com/dimiro1/lunar/internal/store.APIToken + # Enums bound to the existing store string types, so resolvers return store + # values directly. The GraphQL enum values match the store constant strings. + CronStatus: + model: github.com/dimiro1/lunar/internal/store.CronStatus + ExecutionStatus: + model: github.com/dimiro1/lunar/internal/store.ExecutionStatus + ExecutionTrigger: + model: github.com/dimiro1/lunar/internal/store.ExecutionTrigger + AIRequestStatus: + model: github.com/dimiro1/lunar/internal/store.AIRequestStatus + EmailRequestStatus: + model: github.com/dimiro1/lunar/internal/store.EmailRequestStatus diff --git a/internal/api/device_auth_handlers.go b/internal/api/device_auth_handlers.go index 6acca6f..32ec758 100644 --- a/internal/api/device_auth_handlers.go +++ b/internal/api/device_auth_handlers.go @@ -285,43 +285,3 @@ func HandleDeviceToken(deviceStore *DeviceAuthStore) http.HandlerFunc { } } } - -// HandleListAPITokens handles GET /api/tokens -func HandleListAPITokens(db store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - tokens, err := db.ListAPITokens(r.Context()) - if err != nil { - writeError(w, http.StatusInternalServerError, "Failed to list tokens") - return - } - - if tokens == nil { - tokens = []store.APIToken{} - } - - writeJSON(w, http.StatusOK, map[string][]store.APIToken{"tokens": tokens}) - } -} - -// HandleRevokeAPIToken handles POST /api/tokens/{id}/revoke -func HandleRevokeAPIToken(db store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - if id == "" { - writeError(w, http.StatusBadRequest, "Missing token ID") - return - } - - err := db.RevokeAPIToken(r.Context(), id) - if err != nil { - if err == store.ErrAPITokenNotFound { - writeError(w, http.StatusNotFound, "Token not found") - return - } - writeError(w, http.StatusInternalServerError, "Failed to revoke token") - return - } - - writeJSON(w, http.StatusOK, map[string]bool{"success": true}) - } -} diff --git a/internal/api/device_auth_handlers_test.go b/internal/api/device_auth_handlers_test.go index 93c0cf5..2e45368 100644 --- a/internal/api/device_auth_handlers_test.go +++ b/internal/api/device_auth_handlers_test.go @@ -258,8 +258,8 @@ func TestHandleDeviceApproveFlow(t *testing.T) { t.Error("expected token to be set") } - // Step 5: Verify the token works for authentication - reqAuth := httptest.NewRequest(http.MethodGet, "/api/functions", nil) + // Step 5: Verify the token works for authentication against /graphql + reqAuth := newGraphQLProbe() reqAuth.Header.Set("Authorization", "Bearer "+tokenResp.Token) wAuth := httptest.NewRecorder() server.Handler().ServeHTTP(wAuth, reqAuth) @@ -366,110 +366,6 @@ func TestHandleDeviceApprove_InvalidAction(t *testing.T) { } } -func TestHandleListAPITokens(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // List should be empty initially - req := makeAuthRequest(http.MethodGet, "/api/tokens", nil) - w := httptest.NewRecorder() - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Fatalf("expected status 200, got %d: %s", w.Code, w.Body.String()) - } - - var resp map[string][]store.APIToken - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } - - if len(resp["tokens"]) != 0 { - t.Errorf("expected 0 tokens, got %d", len(resp["tokens"])) - } -} - -func TestHandleRevokeAPIToken(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a token via the device flow - reqCreate := httptest.NewRequest(http.MethodPost, "/api/auth/device-request", nil) - wCreate := httptest.NewRecorder() - server.Handler().ServeHTTP(wCreate, reqCreate) - - var createResp DeviceRequestResponse - if err := json.NewDecoder(wCreate.Body).Decode(&createResp); err != nil { - t.Fatalf("failed to decode create response: %v", err) - } - - // Approve - approveBody, _ := json.Marshal(DeviceApproveRequest{ - DeviceCode: createResp.DeviceCode, - Action: "allow", - }) - reqApprove := makeAuthRequest(http.MethodPost, "/api/auth/device-approve", approveBody) - wApprove := httptest.NewRecorder() - server.Handler().ServeHTTP(wApprove, reqApprove) - - // Get the token from poll - reqToken := httptest.NewRequest(http.MethodGet, "/api/auth/device-token?code="+createResp.DeviceCode, nil) - wToken := httptest.NewRecorder() - server.Handler().ServeHTTP(wToken, reqToken) - - var tokenResp DeviceTokenResponse - if err := json.NewDecoder(wToken.Body).Decode(&tokenResp); err != nil { - t.Fatalf("failed to decode token response: %v", err) - } - - // List tokens to get the ID - reqList := makeAuthRequest(http.MethodGet, "/api/tokens", nil) - wList := httptest.NewRecorder() - server.Handler().ServeHTTP(wList, reqList) - - var listResp map[string][]store.APIToken - if err := json.NewDecoder(wList.Body).Decode(&listResp); err != nil { - t.Fatalf("failed to decode list response: %v", err) - } - - if len(listResp["tokens"]) != 1 { - t.Fatalf("expected 1 token, got %d", len(listResp["tokens"])) - } - - tokenID := listResp["tokens"][0].ID - - // Revoke the token - reqRevoke := makeAuthRequest(http.MethodPost, "/api/tokens/"+tokenID+"/revoke", nil) - wRevoke := httptest.NewRecorder() - server.Handler().ServeHTTP(wRevoke, reqRevoke) - - if wRevoke.Code != http.StatusOK { - t.Fatalf("expected status 200 for revoke, got %d: %s", wRevoke.Code, wRevoke.Body.String()) - } - - // Verify the token no longer works for auth - reqAuth := httptest.NewRequest(http.MethodGet, "/api/functions", nil) - reqAuth.Header.Set("Authorization", "Bearer "+tokenResp.Token) - wAuth := httptest.NewRecorder() - server.Handler().ServeHTTP(wAuth, reqAuth) - - if wAuth.Code != http.StatusUnauthorized { - t.Errorf("expected status 401 after revocation, got %d", wAuth.Code) - } -} - -func TestHandleRevokeAPIToken_NotFound(t *testing.T) { - server := createTestServer(store.NewMemoryDB()) - - req := makeAuthRequest(http.MethodPost, "/api/tokens/nonexistent/revoke", nil) - w := httptest.NewRecorder() - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusNotFound { - t.Errorf("expected status 404, got %d", w.Code) - } -} - func TestAuthMiddleware_WithAPIToken(t *testing.T) { database := store.NewMemoryDB() server := createTestServer(database) @@ -488,7 +384,7 @@ func TestAuthMiddleware_WithAPIToken(t *testing.T) { } // Use the raw token for auth - req := httptest.NewRequest(http.MethodGet, "/api/functions", nil) + req := newGraphQLProbe() req.Header.Set("Authorization", "Bearer "+rawToken) w := httptest.NewRecorder() server.Handler().ServeHTTP(w, req) @@ -501,7 +397,7 @@ func TestAuthMiddleware_WithAPIToken(t *testing.T) { func TestAuthMiddleware_InvalidToken(t *testing.T) { server := createTestServer(store.NewMemoryDB()) - req := httptest.NewRequest(http.MethodGet, "/api/functions", nil) + req := newGraphQLProbe() req.Header.Set("Authorization", "Bearer invalid-token") w := httptest.NewRecorder() server.Handler().ServeHTTP(w, req) @@ -515,7 +411,8 @@ func TestAuthMiddleware_AdminKeyStillWorks(t *testing.T) { server := createTestServer(store.NewMemoryDB()) // Admin API key should still work - req := makeAuthRequest(http.MethodGet, "/api/functions", nil) + req := newGraphQLProbe() + req.Header.Set("Authorization", "Bearer test-api-key") w := httptest.NewRecorder() server.Handler().ServeHTTP(w, req) @@ -527,7 +424,7 @@ func TestAuthMiddleware_AdminKeyStillWorks(t *testing.T) { func TestAuthMiddleware_CookieStillWorks(t *testing.T) { server := createTestServer(store.NewMemoryDB()) - req := httptest.NewRequest(http.MethodGet, "/api/functions", nil) + req := newGraphQLProbe() req.AddCookie(&http.Cookie{ Name: "auth_token", Value: "test-api-key", diff --git a/internal/api/doc.go b/internal/api/doc.go index fbcb377..04a73ab 100644 --- a/internal/api/doc.go +++ b/internal/api/doc.go @@ -1,11 +1,13 @@ // Package api provides the HTTP API server for the lunar platform. // -// The API implements the OpenAPI specification defined in docs/openapi.yaml and provides -// endpoints for managing functions, versions, executions, and runtime execution. +// The management API (functions, versions, executions, tokens) is served over +// GraphQL at /graphql; its schema in internal/graph is the source of truth. The +// REST surface this package still owns is intentionally small: // -// Main endpoint groups: -// - /api/functions - Function management (CRUD) -// - /api/functions/{id}/versions - Version management -// - /api/executions - Execution history and logs -// - /fn/{function_id} - Runtime function execution +// - /graphql - GraphQL management API (POST) + GraphiQL playground (GET) +// - /api/auth/* - login/logout and the CLI device-authorization flow +// - /fn/{function_id} - public runtime function execution (passthrough) +// +// The REST endpoints are documented in docs/rest-endpoints.md; the GraphQL +// surface is described by its schema in internal/graph/schema. package api diff --git a/internal/api/docs/index.html b/internal/api/docs/index.html deleted file mode 100644 index 6c1e285..0000000 --- a/internal/api/docs/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - API Reference - Lunar - - - - - - - diff --git a/internal/api/docs/openapi.yaml b/internal/api/docs/openapi.yaml deleted file mode 100644 index 323c0d7..0000000 --- a/internal/api/docs/openapi.yaml +++ /dev/null @@ -1,2489 +0,0 @@ -openapi: 3.1.1 -info: - title: Lunar Application API - description: | - API for managing and executing serverless functions. This API allows you to create, manage, - and execute functions written in Lua, with support for versioning, environment variables, - and execution logging. - version: 1.0.0 - contact: - name: Lunar API Support - -servers: - - url: / - description: Production server - - url: http://localhost:3000 - description: Local development server - -tags: - - name: Authentication - description: Authentication operations - - name: Functions - description: Function management operations - - name: Versions - description: Function version management - - name: Executions - description: Function execution history and logs - - name: Runtime - description: Function execution endpoints - - name: Device Authorization - description: OAuth 2.0-style device authorization flow for CLI authentication - - name: API Tokens - description: API token management for connected clients - -security: - - CookieAuth: [] - - BearerAuth: [] - -paths: - /api/auth/login: - post: - tags: - - Authentication - summary: Authenticate with API key - description: Validates the API key and issues an HttpOnly cookie for subsequent requests. - operationId: login - security: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/LoginRequest" - examples: - validLogin: - summary: Valid API key - value: - apiKey: example-secret - responses: - "200": - description: Authentication successful - headers: - Set-Cookie: - description: HttpOnly authentication cookie containing the API key. - schema: - type: string - content: - application/json: - schema: - $ref: "#/components/schemas/LoginResponse" - examples: - success: - summary: Successful login - value: - success: true - "400": - description: Invalid request body - content: - application/json: - schema: - $ref: "#/components/schemas/LoginResponse" - examples: - invalidBody: - summary: Malformed JSON - value: - success: false - error: Invalid request body - "401": - description: Invalid API key - content: - application/json: - schema: - $ref: "#/components/schemas/LoginResponse" - examples: - invalidAPIKey: - summary: Wrong key - value: - success: false - error: Invalid API key - - /api/auth/logout: - post: - tags: - - Authentication - summary: Log out current session - description: Clears the authentication cookie. - operationId: logout - security: [] - responses: - "200": - description: Logout successful - headers: - Set-Cookie: - description: Expired authentication cookie clearing the session. - schema: - type: string - content: - application/json: - schema: - $ref: "#/components/schemas/LoginResponse" - examples: - success: - summary: Successful logout - value: - success: true - - /api/functions: - post: - tags: - - Functions - summary: Create a new function - description: Creates a new function with the provided code and metadata. The first version is automatically created and activated. - operationId: createFunction - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/CreateFunctionRequest" - examples: - simpleFunction: - summary: Simple HTTP function - value: - name: hello-world - description: A simple hello world function - code: | - function handler(ctx, event) - return { - statusCode = 200, - body = "Hello, World!", - headers = {} - } - end - responses: - "200": - description: Function created successfully - content: - application/json: - schema: - $ref: "#/components/schemas/FunctionWithActiveVersion" - "400": - description: Validation error (invalid request body or field constraints violated) - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - nameEmpty: - summary: Empty name - value: - error: "name: name cannot be empty" - nameTooLong: - summary: Name too long - value: - error: "name: name cannot be longer than 100 characters" - codeEmpty: - summary: Empty code - value: - error: "code: code cannot be empty" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - get: - tags: - - Functions - summary: List all functions - description: Returns a paginated list of all functions with their active versions - operationId: listFunctions - parameters: - - name: limit - in: query - description: Maximum number of items to return (default 20, max 100) - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - example: 20 - - name: offset - in: query - description: Number of items to skip - required: false - schema: - type: integer - minimum: 0 - default: 0 - example: 0 - responses: - "200": - description: List of functions retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/ListFunctionsResponse" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - example: "abc123xyz" - - get: - tags: - - Functions - summary: Get a specific function - description: Returns detailed information about a function including its active version - operationId: getFunction - responses: - "200": - description: Function retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/FunctionWithActiveVersion" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Function not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - put: - tags: - - Functions - summary: Update a function - description: | - Updates function metadata and/or code. If code is provided, a new version is created. - All fields are optional. - operationId: updateFunction - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateFunctionRequest" - examples: - updateMetadata: - summary: Update only metadata - value: - name: new-function-name - description: Updated description - updateCode: - summary: Update code (creates new version) - value: - code: | - function handler(ctx, event) - return {statusCode = 200, body = "Updated!", headers = {}} - end - disableFunction: - summary: Disable function - value: - disabled: true - enableFunction: - summary: Enable function - value: - disabled: false - enableCronSchedule: - summary: Enable cron schedule - value: - cron_schedule: "*/5 * * * *" - cron_status: "active" - pauseCronSchedule: - summary: Pause cron schedule - value: - cron_status: "paused" - clearCronSchedule: - summary: Clear cron schedule - value: - cron_schedule: "" - cron_status: "paused" - responses: - "200": - description: Function updated successfully - "400": - description: Validation error (invalid request body or field constraints violated) - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - noFields: - summary: No fields provided - value: - error: "request: at least one field must be provided for update" - nameEmpty: - summary: Empty name - value: - error: "name: name cannot be empty" - invalidCronSchedule: - summary: Invalid cron expression - value: - error: "cron_schedule: invalid cron expression" - invalidCronStatus: - summary: Invalid cron status - value: - error: "cron_status: must be one of: active, paused" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - delete: - tags: - - Functions - summary: Delete a function - description: Permanently deletes a function and all its versions - operationId: deleteFunction - responses: - "204": - description: Function deleted successfully - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Function not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/versions: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - - get: - tags: - - Versions - summary: List all versions of a function - description: Returns a paginated list of all versions of a function in descending order (newest first) - operationId: listVersions - parameters: - - name: limit - in: query - description: Maximum number of items to return (default 20, max 100) - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - example: 20 - - name: offset - in: query - description: Number of items to skip - required: false - schema: - type: integer - minimum: 0 - default: 0 - example: 0 - responses: - "200": - description: Versions retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/ListVersionsResponse" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/versions/{version}: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - - name: version - in: path - required: true - description: Version number - schema: - type: integer - minimum: 1 - example: 1 - - get: - tags: - - Versions - summary: Get a specific version - description: Returns detailed information about a specific version of a function - operationId: getVersion - responses: - "200": - description: Version retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/FunctionVersion" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Version not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/versions/{versionId}/activate: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - - name: versionId - in: path - required: true - description: Unique identifier of the version (primary key) - schema: - type: string - example: "ver_abc123_v1" - - post: - tags: - - Versions - summary: Activate a version - description: Sets the specified version as the active version for the function - operationId: activateVersion - responses: - "200": - description: Version activated successfully - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Version not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/versions/{versionId}: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - - name: versionId - in: path - required: true - description: Unique identifier of the version (primary key) - schema: - type: string - example: "ver_abc123_v1" - - delete: - tags: - - Versions - summary: Delete a version - description: | - Permanently deletes a specific version of a function. - The active version cannot be deleted - you must activate a different version first. - Deleting a version will also delete all executions associated with that version. - operationId: deleteVersion - responses: - "204": - description: Version deleted successfully - "400": - description: Cannot delete active version - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - activeVersion: - summary: Attempting to delete active version - value: - error: "Cannot delete active version" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Version not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/diff/{v1}/{v2}: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - - name: v1 - in: path - required: true - description: First version number - schema: - type: integer - minimum: 1 - - name: v2 - in: path - required: true - description: Second version number - schema: - type: integer - minimum: 1 - - get: - tags: - - Versions - summary: Get diff between two versions - description: Returns a line-by-line diff between two versions of a function - operationId: getVersionDiff - responses: - "200": - description: Diff retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/VersionDiffResponse" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/env: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - - put: - tags: - - Functions - summary: Update environment variables - description: Updates the environment variables for a function. Does not create a new version. - operationId: updateEnvVars - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateEnvVarsRequest" - examples: - setEnvVars: - summary: Set environment variables - value: - env_vars: - API_KEY: "secret-key-123" - DATABASE_URL: "postgresql://localhost/db" - DEBUG: "true" - responses: - "200": - description: Environment variables updated successfully - content: - application/json: - schema: - $ref: "#/components/schemas/FunctionVersion" - "400": - description: Validation error (invalid request body or field constraints violated) - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - invalidKey: - summary: Invalid environment variable key - value: - error: "env_var_key: environment variable key can only contain letters, numbers, and underscores" - tooManyVars: - summary: Too many environment variables - value: - error: "env_vars: cannot have more than 100 environment variables" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/next-run: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - - get: - tags: - - Functions - summary: Get next scheduled run time - description: | - Returns the next scheduled execution time for a function with an active cron schedule. - If the function has no active schedule, returns null values. - operationId: getNextRun - responses: - "200": - description: Next run information retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/NextRunResponse" - examples: - activeSchedule: - summary: Function with active schedule - value: - next_run: 1702345678 - next_run_human: "in 2 hours" - noSchedule: - summary: Function without active schedule - value: - next_run: null - next_run_human: null - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Function not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/executions: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - - get: - tags: - - Executions - summary: List executions of a function - description: Returns a paginated list of execution history for a function - operationId: listExecutions - parameters: - - name: limit - in: query - description: Maximum number of items to return (default 20, max 100) - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - example: 20 - - name: offset - in: query - description: Number of items to skip - required: false - schema: - type: integer - minimum: 0 - default: 0 - example: 0 - responses: - "200": - description: Executions retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/ListExecutionsResponse" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/functions/{id}/kv: - parameters: - - name: id - in: path - required: true - description: Unique identifier of the function - schema: - type: string - post: - tags: - - Functions - summary: Update key-value store - description: Updates the key-value store for a function or global store. - operationId: updateKV - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/UpdateKVRequest" - examples: - setKV: - summary: Set key-value pairs - value: - kv: - counter: 1 - visitor_email: "fakeuser@fake.com" - responses: - "200": - description: Key-value pairs updated successfully - content: - application/json: - schema: - $ref: "#/components/schemas/FunctionVersion" - "400": - description: Validation error (invalid request body or field constraints violated) - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - invalidKey: - summary: Invalid key - value: - error: "key: key can only contain letters, numbers, and underscores" - tooManyVars: - summary: Too many key-value pairs - value: - error: "kv: cannot have more than 100 key-value pairs" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/executions/{id}: - parameters: - - name: id - in: path - required: true - description: Unique execution identifier - schema: - type: string - example: "exec_abc123" - - get: - tags: - - Executions - summary: Get execution details - description: Returns detailed information about a specific execution - operationId: getExecution - responses: - "200": - description: Execution retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/Execution" - "404": - description: Execution not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/executions/{id}/logs: - parameters: - - name: id - in: path - required: true - description: Unique execution identifier - schema: - type: string - - get: - tags: - - Executions - summary: Get execution logs - description: Returns the execution details along with paginated logs generated during execution - operationId: getExecutionLogs - parameters: - - name: limit - in: query - description: Maximum number of log entries to return (default 20, max 100) - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - example: 20 - - name: offset - in: query - description: Number of log entries to skip - required: false - schema: - type: integer - minimum: 0 - default: 0 - example: 0 - responses: - "200": - description: Execution logs retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/ExecutionWithLogs" - "404": - description: Execution not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/executions/{id}/ai-requests: - parameters: - - name: id - in: path - required: true - description: Unique execution identifier - schema: - type: string - - get: - tags: - - Executions - summary: Get AI requests for an execution - description: Returns paginated AI API requests made during function execution (OpenAI, Anthropic, etc.) - operationId: getExecutionAIRequests - parameters: - - name: limit - in: query - description: Maximum number of AI requests to return (default 20, max 100) - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - example: 20 - - name: offset - in: query - description: Number of AI requests to skip - required: false - schema: - type: integer - minimum: 0 - default: 0 - example: 0 - responses: - "200": - description: AI requests retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/ListAIRequestsResponse" - "404": - description: Execution not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/executions/{id}/email-requests: - parameters: - - name: id - in: path - required: true - description: Unique execution identifier - schema: - type: string - - get: - tags: - - Executions - summary: Get email requests for an execution - description: Returns paginated email requests made during function execution (via Resend API) - operationId: getExecutionEmailRequests - parameters: - - name: limit - in: query - description: Maximum number of email requests to return (default 20, max 100) - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - example: 20 - - name: offset - in: query - description: Number of email requests to skip - required: false - schema: - type: integer - minimum: 0 - default: 0 - example: 0 - responses: - "200": - description: Email requests retrieved successfully - content: - application/json: - schema: - $ref: "#/components/schemas/ListEmailRequestsResponse" - "404": - description: Execution not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/auth/device-request: - post: - tags: - - Device Authorization - summary: Initiate device authorization flow - description: | - Starts the device authorization flow. Returns a device code and user code. - The CLI opens a browser to the approval URL where the user can authorize the device. - This endpoint does not require authentication. - operationId: deviceRequest - security: [] - responses: - "200": - description: Device authorization request created - content: - application/json: - schema: - $ref: "#/components/schemas/DeviceRequestResponse" - examples: - success: - summary: Successful device request - value: - device_code: "crs1abc2def3ghi4" - user_code: "ABCD-EFGH" - approval_url: "http://localhost:3000/#!/device-approve/crs1abc2def3ghi4" - expires_in: 300 - interval: 5 - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/auth/device-approve: - get: - tags: - - Device Authorization - summary: Get device authorization request status - description: | - Returns the status of a pending device authorization request. - Used by the SPA to display the approval page with the user code. - operationId: deviceApproveStatus - parameters: - - name: code - in: query - required: true - description: The device code from the authorization request - schema: - type: string - example: "crs1abc2def3ghi4" - responses: - "200": - description: Device authorization status retrieved - content: - application/json: - schema: - $ref: "#/components/schemas/DeviceApproveStatusResponse" - examples: - pending: - summary: Pending approval - value: - device_code: "crs1abc2def3ghi4" - user_code: "ABCD-EFGH" - status: "pending" - expires_at: 1672531500 - "404": - description: Device authorization request not found or expired - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - notFound: - summary: Request not found - value: - error: "device auth request not found" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - post: - tags: - - Device Authorization - summary: Approve or deny a device authorization request - description: | - Allows the authenticated user to approve or deny a pending device authorization request. - On approval, generates an API token and stores its hash in the database. - The raw token is returned to the polling CLI via the device-token endpoint. - operationId: deviceApprove - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/DeviceApproveRequest" - examples: - allow: - summary: Approve device - value: - device_code: "crs1abc2def3ghi4" - action: "allow" - deny: - summary: Deny device - value: - device_code: "crs1abc2def3ghi4" - action: "deny" - responses: - "200": - description: Device authorization action processed - content: - application/json: - schema: - type: object - properties: - status: - type: string - enum: - - approved - - denied - example: "approved" - "400": - description: Invalid request (bad action or request already processed) - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - invalidAction: - summary: Invalid action - value: - error: "invalid action, must be 'allow' or 'deny'" - alreadyProcessed: - summary: Already processed - value: - error: "device auth request already processed" - "404": - description: Device authorization request not found or expired - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/auth/device-token: - get: - tags: - - Device Authorization - summary: Poll for device authorization token - description: | - Polled by the CLI to check if the user has approved the device authorization request. - Returns the token when approved, or the current status if still pending or denied. - This endpoint does not require authentication. - operationId: deviceToken - security: [] - parameters: - - name: code - in: query - required: true - description: The device code from the authorization request - schema: - type: string - example: "crs1abc2def3ghi4" - responses: - "200": - description: Device token status - content: - application/json: - schema: - $ref: "#/components/schemas/DeviceTokenResponse" - examples: - pending: - summary: Still waiting for user approval - value: - status: "pending" - approved: - summary: Approved - token returned - value: - status: "approved" - token: "a1b2c3d4e5f6..." - denied: - summary: User denied the request - value: - status: "denied" - "400": - description: Missing device code parameter - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - missingCode: - summary: Missing code - value: - error: "missing code parameter" - "404": - description: Device authorization request not found or expired - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - notFound: - summary: Not found - value: - error: "device auth request not found" - - /api/tokens: - get: - tags: - - API Tokens - summary: List all API tokens - description: Returns a list of all API tokens (connected clients) with their metadata. Token hashes are never returned. - operationId: listTokens - responses: - "200": - description: List of API tokens - content: - application/json: - schema: - $ref: "#/components/schemas/ListAPITokensResponse" - examples: - success: - summary: Tokens list - value: - tokens: - - id: "crs1abc2def3ghi4" - name: "CLI Device crs1abc2" - created_at: 1672531200 - last_used: 1672617600 - revoked: false - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /api/tokens/{id}/revoke: - post: - tags: - - API Tokens - summary: Revoke an API token - description: Revokes an API token, preventing it from being used for future authentication. This action cannot be undone. - operationId: revokeToken - parameters: - - name: id - in: path - required: true - description: The unique identifier of the API token to revoke - schema: - type: string - example: "crs1abc2def3ghi4" - responses: - "200": - description: Token revoked successfully - content: - application/json: - schema: - type: object - properties: - status: - type: string - example: "revoked" - "404": - description: Token not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - notFound: - summary: Token not found - value: - error: "token not found" - "401": - description: Authentication required - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "500": - description: Internal server error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /fn/{function_id}: - parameters: - - name: function_id - in: path - required: true - description: Unique identifier of the function to execute - schema: - type: string - example: "abc123xyz" - - get: - tags: - - Runtime - summary: Execute function with GET method - description: | - Executes the active version of a function with an HTTP GET request. - Returns custom response headers: - - X-Function-Id: The function's unique ID - - X-Function-Version-Id: The version ID that was executed - - X-Execution-Id: Unique ID for this execution - - X-Execution-Duration-Ms: Execution time in milliseconds - operationId: executeFunctionGet - security: [] - parameters: - - in: query - name: query parameters - description: Any query parameters are passed to the function - schema: - type: object - additionalProperties: - type: string - responses: - "200": - description: Function executed successfully (status code may vary based on function response) - headers: - X-Function-Id: - description: The function's unique ID - schema: - type: string - X-Function-Version-Id: - description: The version ID that was executed - schema: - type: string - X-Execution-Id: - description: Unique ID for this execution - schema: - type: string - X-Execution-Duration-Ms: - description: Execution time in milliseconds - schema: - type: integer - content: - "*/*": - schema: - type: string - description: Response body from the function - "403": - description: Function is disabled - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - examples: - disabled: - summary: Function disabled - value: - error: "Function is disabled" - "404": - description: Function not found - "500": - description: Function execution failed - - post: - tags: - - Runtime - summary: Execute function with POST method - description: | - Executes the active version of a function with an HTTP POST request. - Returns custom response headers: - - X-Function-Id: The function's unique ID - - X-Function-Version-Id: The version ID that was executed - - X-Execution-Id: Unique ID for this execution - - X-Execution-Duration-Ms: Execution time in milliseconds - operationId: executeFunctionPost - security: [] - parameters: - - in: query - name: query parameters - description: Any query parameters are passed to the function - schema: - type: object - additionalProperties: - type: string - requestBody: - description: Request body passed to the function - content: - "*/*": - schema: - type: string - responses: - "200": - description: Function executed successfully (status code may vary based on function response) - headers: - X-Function-Id: - schema: - type: string - X-Function-Version-Id: - schema: - type: string - X-Execution-Id: - schema: - type: string - X-Execution-Duration-Ms: - schema: - type: integer - content: - "*/*": - schema: - type: string - "403": - description: Function is disabled - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Function not found - "500": - description: Function execution failed - - put: - tags: - - Runtime - summary: Execute function with PUT method - description: | - Executes the active version of a function with an HTTP PUT request. - Returns custom response headers similar to GET and POST. - operationId: executeFunctionPut - security: [] - parameters: - - in: query - name: query parameters - schema: - type: object - additionalProperties: - type: string - requestBody: - content: - "*/*": - schema: - type: string - responses: - "200": - description: Function executed successfully - headers: - X-Function-Id: - schema: - type: string - X-Function-Version-Id: - schema: - type: string - X-Execution-Id: - schema: - type: string - X-Execution-Duration-Ms: - schema: - type: integer - content: - "*/*": - schema: - type: string - "403": - description: Function is disabled - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Function not found - "500": - description: Function execution failed - - delete: - tags: - - Runtime - summary: Execute function with DELETE method - description: | - Executes the active version of a function with an HTTP DELETE request. - Returns custom response headers similar to GET and POST. - operationId: executeFunctionDelete - security: [] - parameters: - - in: query - name: query parameters - schema: - type: object - additionalProperties: - type: string - responses: - "200": - description: Function executed successfully - headers: - X-Function-Id: - schema: - type: string - X-Function-Version-Id: - schema: - type: string - X-Execution-Id: - schema: - type: string - X-Execution-Duration-Ms: - schema: - type: integer - content: - "*/*": - schema: - type: string - "403": - description: Function is disabled - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Function not found - "500": - description: Function execution failed - -components: - securitySchemes: - CookieAuth: - type: apiKey - in: cookie - name: auth_token - description: HttpOnly authentication cookie issued after a successful login. - BearerAuth: - type: http - scheme: bearer - bearerFormat: APIKey - description: Provide the API key as a bearer token in the Authorization header. - - schemas: - LoginRequest: - type: object - required: - - apiKey - properties: - apiKey: - type: string - description: API key used to authenticate requests. - example: example-secret - minLength: 1 - - LoginResponse: - type: object - required: - - success - properties: - success: - type: boolean - description: Indicates whether the authentication action succeeded. - example: true - error: - type: string - description: Error message when the operation fails. - example: Invalid API key - - Function: - type: object - required: - - id - - name - - env_vars - - disabled - - created_at - - updated_at - properties: - id: - type: string - description: Unique identifier for the function - example: "abc123xyz" - name: - type: string - description: Human-readable name for the function - example: "hello-world" - description: - type: string - nullable: true - description: Optional description of what the function does - example: "A simple hello world function" - env_vars: - type: object - additionalProperties: - type: string - description: Environment variables available to the function - example: - API_KEY: "secret-123" - DEBUG: "true" - disabled: - type: boolean - description: Whether the function is disabled and cannot be executed - example: false - default: false - retention_days: - type: integer - nullable: true - description: Number of days to retain execution logs (default is 7 days) - enum: [7, 15, 30, 365] - example: 7 - cron_schedule: - type: string - nullable: true - description: Cron expression for scheduled execution (standard 5-field format) - example: "*/5 * * * *" - cron_status: - type: string - nullable: true - description: Status of the cron schedule - enum: - - active - - paused - example: "paused" - save_response: - type: boolean - description: Whether to save HTTP responses with executions for debugging - example: false - default: false - created_at: - type: integer - format: int64 - description: Unix timestamp when the function was created - example: 1672531200 - updated_at: - type: integer - format: int64 - description: Unix timestamp when the function was last updated - example: 1672617600 - - FunctionVersion: - type: object - required: - - id - - function_id - - version - - code - - created_at - - is_active - properties: - id: - type: string - description: Unique identifier for this version - example: "ver_abc123" - function_id: - type: string - description: ID of the parent function - example: "abc123xyz" - version: - type: integer - description: Version number (incremental) - example: 1 - minimum: 1 - code: - type: string - description: Lua code for this version - example: | - function handler(ctx, event) - return {statusCode = 200, body = "Hello", headers = {}} - end - created_at: - type: integer - format: int64 - description: Unix timestamp when this version was created - example: 1672531200 - created_by: - type: string - nullable: true - description: User who created this version (if applicable) - example: "user@example.com" - is_active: - type: boolean - description: Whether this is the currently active version - example: true - - Execution: - type: object - required: - - id - - function_id - - function_version_id - - execution_id - - status - - created_at - properties: - id: - type: string - description: Internal database ID - example: "1" - function_id: - type: string - description: ID of the function that was executed - example: "abc123xyz" - function_version_id: - type: string - description: ID of the version that was executed - example: "ver_abc123" - execution_id: - type: string - description: Unique execution identifier - example: "exec_xyz789" - status: - type: string - enum: - - pending - - success - - error - description: Status of the execution - example: "success" - duration_ms: - type: integer - format: int64 - nullable: true - description: Execution duration in milliseconds - example: 125 - error_message: - type: string - nullable: true - description: Error message if execution failed - example: "Runtime error: attempt to call nil value" - trigger: - type: string - description: What triggered this execution - enum: - - http - - cron - example: "http" - default: "http" - response_json: - type: string - nullable: true - description: JSON-encoded HTTP response (only present if save_response is enabled on the function). Contains statusCode, headers, body, and isBase64Encoded. Body is truncated to 1MB if larger. - example: '{"statusCode":200,"headers":{"Content-Type":"application/json"},"body":"{\"success\":true}","isBase64Encoded":false}' - created_at: - type: integer - format: int64 - description: Unix timestamp when execution started - example: 1672531200 - - ExecutionWithLogCount: - allOf: - - $ref: "#/components/schemas/Execution" - - type: object - required: - - log_count - properties: - log_count: - type: integer - format: int64 - description: Number of log entries for this execution - example: 5 - - LogEntry: - type: object - required: - - id - - execution_id - - level - - message - - created_at - properties: - id: - type: string - description: Unique identifier for the log entry - example: "log_123" - execution_id: - type: string - description: ID of the execution this log belongs to - example: "exec_xyz789" - level: - type: string - description: Log level - enum: - - debug - - info - - warn - - error - example: "info" - message: - type: string - description: Log message content - example: "Processing request for user 123" - created_at: - type: integer - format: int64 - description: Unix timestamp when log was created - example: 1672531200 - - DiffLine: - type: object - required: - - line_type - - content - properties: - line_type: - type: string - enum: - - unchanged - - added - - removed - description: Type of change for this line - example: "unchanged" - old_line: - type: integer - nullable: true - description: Line number in old version (null for added lines) - example: 5 - new_line: - type: integer - nullable: true - description: Line number in new version (null for removed lines) - example: 5 - content: - type: string - description: Content of the line - example: " return {statusCode = 200}" - - CreateFunctionRequest: - type: object - required: - - name - - code - properties: - name: - type: string - description: Name for the function (must be non-empty after trimming whitespace) - example: "hello-world" - minLength: 1 - maxLength: 100 - description: - type: string - nullable: true - description: Optional description - example: "A simple hello world function" - maxLength: 500 - code: - type: string - description: Lua code for the function (must be non-empty after trimming whitespace) - example: | - function handler(ctx, event) - return {statusCode = 200, body = "Hello", headers = {}} - end - minLength: 1 - maxLength: 1048576 - - UpdateFunctionRequest: - type: object - description: At least one field must be provided - properties: - name: - type: string - nullable: true - description: New name for the function (must be non-empty after trimming whitespace) - example: "updated-name" - minLength: 1 - maxLength: 100 - description: - type: string - nullable: true - description: New description - example: "Updated description" - maxLength: 500 - code: - type: string - nullable: true - description: New code (creates a new version, must be non-empty after trimming whitespace) - example: | - function handler(ctx, event) - return {statusCode = 200, body = "Updated!", headers = {}} - end - minLength: 1 - maxLength: 1048576 - disabled: - type: boolean - nullable: true - description: Set to true to disable the function (preventing execution), false to enable it - example: false - retention_days: - type: integer - nullable: true - description: Number of days to retain execution logs - enum: [7, 15, 30, 365] - example: 30 - cron_schedule: - type: string - nullable: true - description: | - Cron expression for scheduled execution (standard 5-field format: minute hour day month weekday). - Examples: "*/5 * * * *" (every 5 minutes), "0 9 * * 1-5" (weekdays at 9am). - Set to empty string to clear the schedule. - example: "0 */2 * * *" - maxLength: 100 - cron_status: - type: string - nullable: true - description: Status of the cron schedule. Set to "active" to enable scheduled execution. - enum: - - active - - paused - example: "active" - save_response: - type: boolean - nullable: true - description: Whether to save HTTP responses with executions for debugging - example: true - - UpdateEnvVarsRequest: - type: object - required: - - env_vars - properties: - env_vars: - type: object - additionalProperties: - type: string - maxLength: 10000 - description: | - Environment variables to set (max 100 variables). - Keys must contain only letters, numbers, and underscores (max 100 chars). - Values can be up to 10,000 characters. - example: - API_KEY: "new-secret" - DATABASE_URL: "postgresql://localhost/db" - maxProperties: 100 - - UpdateKVRequest: - type: object - required: - - global - - kv - properties: - global: - type: boolean - description: Whether the KV pairs are global or function-scoped - example: true - kv: - type: object - additionalProperties: - type: string - maxLength: 10000 - description: | - Key-value pairs to set in the function's KV store (max 100 pairs). - Keys must contain only letters, numbers, and underscores (max 100 chars). - Values can be up to 10,000 characters. - example: - counter: "42" - visitor_email: "fakeuser@fake.com" - maxProperties: 100 - - FunctionWithActiveVersion: - allOf: - - $ref: "#/components/schemas/Function" - - type: object - required: - - active_version - properties: - active_version: - $ref: "#/components/schemas/FunctionVersion" - - ListFunctionsResponse: - type: object - required: - - functions - - pagination - properties: - functions: - type: array - items: - $ref: "#/components/schemas/FunctionWithActiveVersion" - pagination: - $ref: "#/components/schemas/PaginationInfo" - - ListVersionsResponse: - type: object - required: - - versions - - pagination - properties: - versions: - type: array - items: - $ref: "#/components/schemas/FunctionVersion" - pagination: - $ref: "#/components/schemas/PaginationInfo" - - ListExecutionsResponse: - type: object - required: - - executions - - pagination - properties: - executions: - type: array - items: - $ref: "#/components/schemas/ExecutionWithLogCount" - pagination: - $ref: "#/components/schemas/PaginationInfo" - - ExecutionWithLogs: - allOf: - - $ref: "#/components/schemas/Execution" - - type: object - required: - - logs - - pagination - properties: - logs: - type: array - items: - $ref: "#/components/schemas/LogEntry" - pagination: - $ref: "#/components/schemas/PaginationInfo" - - AIRequest: - type: object - required: - - id - - execution_id - - provider - - model - - endpoint - - request_json - - status - - duration_ms - - created_at - properties: - id: - type: string - description: Unique identifier for the AI request - example: "aireq_abc123" - execution_id: - type: string - description: ID of the execution this request belongs to - example: "exec_xyz789" - provider: - type: string - description: AI provider name - enum: - - openai - - anthropic - example: "openai" - model: - type: string - description: Model name used for the request - example: "gpt-4" - endpoint: - type: string - description: API endpoint called - example: "/v1/chat/completions" - request_json: - type: string - description: JSON-encoded request payload (sensitive data masked) - example: '{"model":"gpt-4","messages":[...]}' - response_json: - type: string - nullable: true - description: JSON-encoded response payload (sensitive data masked) - example: '{"id":"chatcmpl-...","choices":[...]}' - status: - type: string - enum: - - success - - error - description: Status of the AI request - example: "success" - error_message: - type: string - nullable: true - description: Error message if the request failed - example: "Rate limit exceeded" - input_tokens: - type: integer - nullable: true - description: Number of input tokens used - example: 150 - output_tokens: - type: integer - nullable: true - description: Number of output tokens generated - example: 75 - duration_ms: - type: integer - format: int64 - description: Request duration in milliseconds - example: 1250 - created_at: - type: integer - format: int64 - description: Unix timestamp when the request was made - example: 1672531200 - - ListAIRequestsResponse: - type: object - required: - - ai_requests - - pagination - properties: - ai_requests: - type: array - items: - $ref: "#/components/schemas/AIRequest" - pagination: - $ref: "#/components/schemas/PaginationInfo" - - EmailRequest: - type: object - required: - - id - - execution_id - - from - - to - - subject - - has_text - - has_html - - request_json - - status - - duration_ms - - created_at - properties: - id: - type: string - description: Unique identifier for the email request - example: "emailreq_abc123" - execution_id: - type: string - description: ID of the execution this request belongs to - example: "exec_xyz789" - from: - type: string - description: Sender email address - example: "noreply@example.com" - to: - type: array - items: - type: string - description: List of recipient email addresses - example: ["user@example.com"] - subject: - type: string - description: Email subject line - example: "Welcome to our platform!" - has_text: - type: boolean - description: Whether the email contains plain text content - example: true - has_html: - type: boolean - description: Whether the email contains HTML content - example: true - request_json: - type: string - description: JSON-encoded request payload (sensitive data masked) - example: '{"from":"noreply@example.com","to":["user@example.com"],"subject":"Welcome!"}' - response_json: - type: string - nullable: true - description: JSON-encoded response payload - example: '{"id":"email_abc123"}' - status: - type: string - enum: - - success - - error - description: Status of the email request - example: "success" - error_message: - type: string - nullable: true - description: Error message if the request failed - example: "Invalid API key" - email_id: - type: string - nullable: true - description: ID returned by the email provider (Resend) - example: "email_abc123def456" - duration_ms: - type: integer - format: int64 - description: Request duration in milliseconds - example: 234 - created_at: - type: integer - format: int64 - description: Unix timestamp when the request was made - example: 1672531200 - - ListEmailRequestsResponse: - type: object - required: - - email_requests - - pagination - properties: - email_requests: - type: array - items: - $ref: "#/components/schemas/EmailRequest" - pagination: - $ref: "#/components/schemas/PaginationInfo" - - VersionDiffResponse: - type: object - required: - - old_version - - new_version - - diff - properties: - old_version: - type: integer - description: First version number - example: 1 - new_version: - type: integer - description: Second version number - example: 2 - diff: - type: array - items: - $ref: "#/components/schemas/DiffLine" - description: Line-by-line diff - - NextRunResponse: - type: object - properties: - next_run: - type: integer - format: int64 - nullable: true - description: Unix timestamp of the next scheduled execution (null if no active schedule) - example: 1702345678 - next_run_human: - type: string - nullable: true - description: Human-readable description of when the next run will occur (e.g., "in 2 hours") - example: "in 2 hours" - - ErrorResponse: - type: object - required: - - error - properties: - error: - type: string - description: Error message - example: "Function not found" - - PaginationInfo: - type: object - required: - - total - - limit - - offset - properties: - total: - type: integer - format: int64 - description: Total number of items available - example: 42 - limit: - type: integer - description: Number of items per page - example: 20 - offset: - type: integer - description: Number of items skipped - example: 0 - - DeviceRequestResponse: - type: object - required: - - device_code - - user_code - - approval_url - - expires_in - - interval - properties: - device_code: - type: string - description: Unique device code used to identify this authorization request - example: "crs1abc2def3ghi4" - user_code: - type: string - description: Short alphanumeric code displayed to the user for verification - example: "ABCD-EFGH" - approval_url: - type: string - description: URL where the user should approve the device authorization - example: "http://localhost:3000/#!/device-approve/crs1abc2def3ghi4" - expires_in: - type: integer - description: Number of seconds until this authorization request expires - example: 300 - interval: - type: integer - description: Recommended polling interval in seconds for the device-token endpoint - example: 5 - - DeviceApproveRequest: - type: object - required: - - device_code - - action - properties: - device_code: - type: string - description: The device code from the authorization request - example: "crs1abc2def3ghi4" - action: - type: string - description: The action to take on the authorization request - enum: - - allow - - deny - example: "allow" - - DeviceApproveStatusResponse: - type: object - required: - - device_code - - user_code - - status - - expires_at - properties: - device_code: - type: string - description: The device code for this authorization request - example: "crs1abc2def3ghi4" - user_code: - type: string - description: The user verification code - example: "ABCD-EFGH" - status: - type: string - description: Current status of the authorization request - enum: - - pending - - approved - - denied - example: "pending" - expires_at: - type: integer - format: int64 - description: Unix timestamp when this authorization request expires - example: 1672531500 - - DeviceTokenResponse: - type: object - required: - - status - properties: - status: - type: string - description: Current status of the authorization request - enum: - - pending - - approved - - denied - example: "pending" - token: - type: string - description: The API token (only present when status is "approved"). This is the only time the raw token is returned. - example: "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" - - APIToken: - type: object - required: - - id - - name - - created_at - - revoked - properties: - id: - type: string - description: Unique identifier for the API token - example: "crs1abc2def3ghi4" - name: - type: string - description: Human-readable name for the token - example: "CLI Device crs1abc2" - created_at: - type: integer - format: int64 - description: Unix timestamp when the token was created - example: 1672531200 - last_used: - type: integer - format: int64 - nullable: true - description: Unix timestamp when the token was last used (null if never used) - example: 1672617600 - revoked: - type: boolean - description: Whether the token has been revoked - example: false - - ListAPITokensResponse: - type: object - required: - - tokens - properties: - tokens: - type: array - items: - $ref: "#/components/schemas/APIToken" - description: List of API tokens diff --git a/internal/api/docs_handlers.go b/internal/api/docs_handlers.go deleted file mode 100644 index d5d7823..0000000 --- a/internal/api/docs_handlers.go +++ /dev/null @@ -1,35 +0,0 @@ -package api - -import ( - "net/http" - - _ "embed" -) - -var ( - //go:embed docs/index.html - docsHTML []byte - - //go:embed docs/openapi.yaml - openAPISpec []byte -) - -// docsPageHandler serves the interactive API reference page. -func docsPageHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.Header().Set("Cache-Control", "no-store") - w.WriteHeader(http.StatusOK) - if r.Method != http.MethodHead { - _, _ = w.Write(docsHTML) - } -} - -// openAPISpecHandler returns the OpenAPI specification consumed by the docs UI. -func openAPISpecHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/yaml") - w.Header().Set("Cache-Control", "no-store") - w.WriteHeader(http.StatusOK) - if r.Method != http.MethodHead { - _, _ = w.Write(openAPISpec) - } -} diff --git a/internal/api/handlers.go b/internal/api/handlers.go index 5918d06..ead8c8f 100644 --- a/internal/api/handlers.go +++ b/internal/api/handlers.go @@ -9,17 +9,9 @@ import ( "strconv" "strings" - internalcron "github.com/dimiro1/lunar/internal/cron" - "github.com/dimiro1/lunar/internal/diff" "github.com/dimiro1/lunar/internal/engine" "github.com/dimiro1/lunar/internal/events" - "github.com/dimiro1/lunar/internal/services/ai" - "github.com/dimiro1/lunar/internal/services/email" - "github.com/dimiro1/lunar/internal/services/env" - "github.com/dimiro1/lunar/internal/services/kv" - "github.com/dimiro1/lunar/internal/services/logger" "github.com/dimiro1/lunar/internal/store" - "github.com/rs/xid" ) // ExecuteFunctionDeps holds dependencies for executing functions @@ -42,696 +34,10 @@ func writeError(w http.ResponseWriter, status int, message string) { writeJSON(w, status, map[string]string{"error": message}) } -func parsePaginationParams(r *http.Request) store.PaginationParams { - params := store.PaginationParams{ - Limit: 20, // Default - Offset: 0, // Default - } - - if limitStr := r.URL.Query().Get("limit"); limitStr != "" { - if limit, err := strconv.Atoi(limitStr); err == nil && limit > 0 { - // Enforce maximum page size - params.Limit = min(limit, MaxPageSize) - } - } - - if offsetStr := r.URL.Query().Get("offset"); offsetStr != "" { - if offset, err := strconv.Atoi(offsetStr); err == nil && offset >= 0 { - params.Offset = offset - } - } - - return params -} - -func generateID() string { - return xid.New().String() -} - -func generateDiff(oldCode, newCode string, oldVersion, newVersion int) VersionDiffResponse { - // Use the diff package to generate the diff - result := diff.Compare(oldCode, newCode) - - // Convert from diff.Line to DiffLine (API type) - apiDiffLines := make([]DiffLine, len(result.Lines)) - for i, line := range result.Lines { - apiDiffLines[i] = DiffLine{ - LineType: DiffLineType(line.Type), - OldLine: line.OldLine, - NewLine: line.NewLine, - Content: line.Content, - } - } - - return VersionDiffResponse{ - OldVersion: oldVersion, - NewVersion: newVersion, - Diff: apiDiffLines, - } -} - -// CreateFunctionHandler returns a handler for creating functions -func CreateFunctionHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var req CreateFunctionRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - writeError(w, http.StatusBadRequest, "Invalid request body") - return - } - - // Validate request - if err := ValidateCreateFunctionRequest(&req); err != nil { - writeError(w, http.StatusBadRequest, err.Error()) - return - } - - // Generate unique ID for the function - functionID := generateID() - - // Create the function - fn := store.Function{ - ID: functionID, - Name: req.Name, - Description: req.Description, - EnvVars: make(map[string]string), - } - - createdFn, err := database.CreateFunction(r.Context(), fn) - if err != nil { - slog.Error("Failed to create function", "error", err) - writeError(w, http.StatusInternalServerError, "Failed to create function") - return - } - - // Create the first version - version, err := database.CreateVersion(r.Context(), createdFn.ID, req.Code, nil) - if err != nil { - slog.Error("Failed to create initial version", "error", err, "function_id", createdFn.ID) - writeError(w, http.StatusInternalServerError, "Failed to create initial version") - return - } - - // Return function with the active version - resp := store.FunctionWithActiveVersion{ - Function: createdFn, - ActiveVersion: version, - } - - writeJSON(w, http.StatusOK, resp) - } -} - -// ListFunctionsHandler returns a handler for listing functions -func ListFunctionsHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - params := parsePaginationParams(r) - - functions, total, err := database.ListFunctions(r.Context(), params) - if err != nil { - slog.Error("Failed to list functions", "error", err) - writeError(w, http.StatusInternalServerError, "Failed to list functions") - return - } - - params = params.Normalize() - resp := PaginatedFunctionsResponse{ - Functions: functions, - Pagination: store.PaginationInfo{ - Total: total, - Limit: params.Limit, - Offset: params.Offset, - }, - } - - writeJSON(w, http.StatusOK, resp) - } -} - -// GetFunctionHandler returns a handler for getting a specific function -func GetFunctionHandler(database store.DB, envStore env.Store, kvStore kv.Store) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - - fn, err := database.GetFunction(r.Context(), id) - if err != nil { - writeError(w, http.StatusNotFound, "Function not found") - return - } - - activeVersion, err := database.GetActiveVersion(r.Context(), id) - if err != nil { - slog.Error("Failed to get active version", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "No active version found") - return - } - - // Get env vars from the env store - envVars, err := envStore.All(id) - if err != nil { - slog.Error("Failed to get env vars", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to get env vars") - return - } - fn.EnvVars = envVars - - // Get current kv entries from kv store - scopedKvEntries, err := kvStore.All(id) - if err != nil { - slog.Error("Failed to get function-scoped kv entries", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to get current function-scoped kv entries") - return - } - - // Get current global kv entries from kv store - globalKvEntries, err := kvStore.AllGlobal() - if err != nil { - slog.Error("Failed to get global kv entries", "error", err) - writeError(w, http.StatusInternalServerError, "Failed to get current global kv entries") - return - } - - fn.ScopedData = scopedKvEntries - fn.GlobalData = globalKvEntries - - resp := store.FunctionWithActiveVersion{ - Function: fn, - ActiveVersion: activeVersion, - } - - writeJSON(w, http.StatusOK, resp) - } -} - -// UpdateFunctionHandler returns a handler for updating functions -func UpdateFunctionHandler(database store.DB, scheduler *internalcron.FunctionScheduler) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - - var req store.UpdateFunctionRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - writeError(w, http.StatusBadRequest, "Invalid request body") - return - } - - // Validate request - if err := ValidateUpdateFunctionRequest(&req); err != nil { - writeError(w, http.StatusBadRequest, err.Error()) - return - } - - // If code is provided, create a new version - if req.Code != nil { - _, err := database.CreateVersion(r.Context(), id, *req.Code, nil) - if err != nil { - slog.Error("Failed to create new version", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to create new version") - return - } - } - - // Track if cron settings changed - cronChanged := req.CronSchedule != nil || req.CronStatus != nil - - // If metadata is provided, update the function - if req.Name != nil || req.Description != nil || req.Disabled != nil || req.RetentionDays != nil || req.CronSchedule != nil || req.CronStatus != nil || req.SaveResponse != nil { - err := database.UpdateFunction(r.Context(), id, req) - if err != nil { - slog.Error("Failed to update function", "error", err, "function_id", id) - writeError(w, http.StatusNotFound, "Function not found") - return - } - } - - // If cron settings changed, refresh the scheduler - if cronChanged && scheduler != nil { - if err := scheduler.RefreshFunction(id); err != nil { - slog.Error("Failed to refresh cron schedule for function", - "function_id", id, - "error", err) - // Don't fail the request, just log the error - } - } - - w.WriteHeader(http.StatusOK) - } -} - -// DeleteFunctionHandler returns a handler for deleting functions -func DeleteFunctionHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - - if err := database.DeleteFunction(r.Context(), id); err != nil { - slog.Error("Failed to delete function", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to delete function") - return - } - - w.WriteHeader(http.StatusNoContent) - } -} - -// UpdateEnvVarsHandler returns a handler for updating environment variables -func UpdateEnvVarsHandler(database store.DB, envStore env.Store) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - - var req UpdateEnvVarsRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - writeError(w, http.StatusBadRequest, "Invalid request body") - return - } - - // Validate request - if err := ValidateUpdateEnvVarsRequest(&req); err != nil { - writeError(w, http.StatusBadRequest, err.Error()) - return - } - - // Verify function exists - _, err := database.GetFunction(r.Context(), id) - if err != nil { - writeError(w, http.StatusNotFound, "Function not found") - return - } - - // Get current env vars from env store - currentEnvVars, err := envStore.All(id) - if err != nil { - slog.Error("Failed to get current env vars", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to get current env vars") - return - } - - // Delete removed env vars - for key := range currentEnvVars { - if _, exists := req.EnvVars[key]; !exists { - if err := envStore.Delete(id, key); err != nil { - slog.Error("Failed to delete env var", "error", err, "function_id", id, "key", key) - writeError(w, http.StatusInternalServerError, "Failed to delete env var") - return - } - } - } - - // Set new/updated env vars - for key, value := range req.EnvVars { - if err := envStore.Set(id, key, value); err != nil { - slog.Error("Failed to set env var", "error", err, "function_id", id, "key", key) - writeError(w, http.StatusInternalServerError, "Failed to set env var") - return - } - } - - // Get the active version to return - activeVersion, err := database.GetActiveVersion(r.Context(), id) - if err != nil { - slog.Error("Failed to get active version after env update", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to get active version") - return - } - - writeJSON(w, http.StatusOK, activeVersion) - } -} - -// UpdateKvStoreHandler returns a handler for updating key-value store entries -func UpdateKvStoreHandler(database store.DB, kvStore kv.Store) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - - var req UpdateKvStoreRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - writeError(w, http.StatusBadRequest, "Invalid request body") - return - } - - // Validate request - if err := ValidateUpdateKvStoreRequest(&req); err != nil { - writeError(w, http.StatusBadRequest, err.Error()) - return - } - - // Verify function exists - _, err := database.GetFunction(r.Context(), id) - if err != nil { - writeError(w, http.StatusNotFound, "Function not found") - return - } - - // This function handles both function-scoped and global kv entries. - // If req.Global is true, we use an empty string as the functionID in the kv store - // to represent global entries. Otherwise, we use the function ID for function-scoped - // entries. - useStore := id - if req.Global { - useStore = "" - } - - // Get current kv entries from kv store - currentKvEntries, err := kvStore.All(useStore) - if err != nil { - slog.Error("Failed to get current kv entries", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to get current kv entries") - return - } - - // Delete removed kv entries - for key := range currentKvEntries { - if _, ok := req.Kv[key]; !ok { - if err := kvStore.Delete(useStore, key); err != nil { - slog.Error("Failed to delete kv entry", "error", err, "function_id", id, "key", key) - writeError(w, http.StatusInternalServerError, "Failed to delete kv entry") - return - } - } - } - - // Set new/updated kv entries - for key, value := range req.Kv { - if err := kvStore.Set(useStore, key, value); err != nil { - slog.Error("Failed to set kv entry", "error", err, "function_id", id, "key", key) - writeError(w, http.StatusInternalServerError, "Failed to set kv entry") - return - } - } - - // Get the active version to return - activeVersion, err := database.GetActiveVersion(r.Context(), id) - if err != nil { - slog.Error("Failed to get active version after kv update", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to get active version") - return - } - - writeJSON(w, http.StatusOK, activeVersion) - } -} - -// ListVersionsHandler returns a handler for listing function versions -func ListVersionsHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - params := parsePaginationParams(r) - - // Verify function exists - if _, err := database.GetFunction(r.Context(), id); err != nil { - writeError(w, http.StatusNotFound, "Function not found") - return - } - - versions, total, err := database.ListVersions(r.Context(), id, params) - if err != nil { - slog.Error("Failed to list versions", "error", err, "function_id", id) - writeError(w, http.StatusInternalServerError, "Failed to list versions") - return - } - - params = params.Normalize() - resp := PaginatedVersionsResponse{ - Versions: versions, - Pagination: store.PaginationInfo{ - Total: total, - Limit: params.Limit, - Offset: params.Offset, - }, - } - - writeJSON(w, http.StatusOK, resp) - } -} - -// GetVersionHandler returns a handler for getting a specific version -func GetVersionHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - versionStr := r.PathValue("version") - - // Parse version number - versionNum, err := strconv.Atoi(versionStr) - if err != nil { - writeError(w, http.StatusBadRequest, "Invalid version number") - return - } - - version, err := database.GetVersion(r.Context(), id, versionNum) - if err != nil { - writeError(w, http.StatusNotFound, "Version not found") - return - } - - writeJSON(w, http.StatusOK, version) - } -} - -// ActivateVersionHandler returns a handler for activating a version -func ActivateVersionHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - versionID := r.PathValue("versionId") - - // Activate the version - if err := database.ActivateVersion(r.Context(), versionID); err != nil { - if err == store.ErrVersionNotFound { - writeError(w, http.StatusNotFound, "Version not found") - return - } - slog.Error("Failed to activate version", "error", err, "version_id", versionID) - writeError(w, http.StatusInternalServerError, "Failed to activate version") - return - } - - w.WriteHeader(http.StatusOK) - } -} - -// DeleteVersionHandler returns a handler for deleting a version -func DeleteVersionHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - versionID := r.PathValue("versionId") - - // Delete the version - if err := database.DeleteVersion(r.Context(), versionID); err != nil { - if err == store.ErrVersionNotFound { - writeError(w, http.StatusNotFound, "Version not found") - return - } - if err == store.ErrCannotDeleteActiveVersion { - writeError(w, http.StatusBadRequest, "Cannot delete active version") - return - } - slog.Error("Failed to delete version", "error", err, "version_id", versionID) - writeError(w, http.StatusInternalServerError, "Failed to delete version") - return - } - - w.WriteHeader(http.StatusNoContent) - } -} - -// GetVersionDiffHandler returns a handler for getting diff between versions -func GetVersionDiffHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - v1Str := r.PathValue("v1") - v2Str := r.PathValue("v2") - - // Parse version numbers - v1, err := strconv.Atoi(v1Str) - if err != nil { - writeError(w, http.StatusBadRequest, "Invalid version number v1") - return - } - - v2, err := strconv.Atoi(v2Str) - if err != nil { - writeError(w, http.StatusBadRequest, "Invalid version number v2") - return - } - - // Get both versions from the database - version1, err := database.GetVersion(r.Context(), id, v1) - if err != nil { - writeError(w, http.StatusNotFound, "Version v1 not found") - return - } - - version2, err := database.GetVersion(r.Context(), id, v2) - if err != nil { - writeError(w, http.StatusNotFound, "Version v2 not found") - return - } - - // Generate the diff using our utility function - diffResult := generateDiff(version1.Code, version2.Code, v1, v2) - - writeJSON(w, http.StatusOK, diffResult) - } -} - -// ListExecutionsHandler returns a handler for listing executions -func ListExecutionsHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - params := parsePaginationParams(r) - - // Verify function exists - if _, err := database.GetFunction(r.Context(), id); err != nil { - writeError(w, http.StatusNotFound, "Function not found") - return - } - - executions, total, err := database.ListExecutions(r.Context(), id, params) - if err != nil { - writeError(w, http.StatusInternalServerError, "Failed to list executions") - return - } - - params = params.Normalize() - resp := PaginatedExecutionsResponse{ - Executions: executions, - Pagination: store.PaginationInfo{ - Total: total, - Limit: params.Limit, - Offset: params.Offset, - }, - } - - writeJSON(w, http.StatusOK, resp) - } -} - -// GetExecutionHandler returns a handler for getting a specific execution -func GetExecutionHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - - execution, err := database.GetExecution(r.Context(), id) - if err != nil { - writeError(w, http.StatusNotFound, "Execution not found") - return - } - - writeJSON(w, http.StatusOK, execution) - } -} - -// GetExecutionLogsHandler returns a handler for getting execution logs -func GetExecutionLogsHandler(database store.DB, appLogger logger.Logger) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - params := parsePaginationParams(r) - - // Get the execution - execution, err := database.GetExecution(r.Context(), id) - if err != nil { - writeError(w, http.StatusNotFound, "Execution not found") - return - } - - // Get the logs for this execution from the logger - params = params.Normalize() - logEntries, total := appLogger.EntriesPaginated(id, params.Limit, params.Offset) - - // Convert logger.LogEntry to API LogEntry format - apiLogs := make([]LogEntry, len(logEntries)) - for i, entry := range logEntries { - // Map logger.LogLevel (int) to API LogLevel (string) - var level LogLevel - switch entry.Level { - case logger.Debug: - level = LogLevelDebug - case logger.Info: - level = LogLevelInfo - case logger.Warn: - level = LogLevelWarn - case logger.Error: - level = LogLevelError - default: - level = LogLevelInfo - } - - apiLogs[i] = LogEntry{ - Level: level, - Message: entry.Message, - CreatedAt: entry.Timestamp, - } - } - - resp := PaginatedExecutionWithLogs{ - Execution: execution, - Logs: apiLogs, - Pagination: store.PaginationInfo{ - Total: total, - Limit: params.Limit, - Offset: params.Offset, - }, - } - - writeJSON(w, http.StatusOK, resp) - } -} - -// GetExecutionAIRequestsHandler returns a handler for getting AI requests for an execution -func GetExecutionAIRequestsHandler(database store.DB, aiTracker ai.Tracker) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - params := parsePaginationParams(r) - - // Verify execution exists - _, err := database.GetExecution(r.Context(), id) - if err != nil { - writeError(w, http.StatusNotFound, "Execution not found") - return - } - - // Get AI requests for this execution - params = params.Normalize() - aiRequests, total := aiTracker.RequestsPaginated(id, params.Limit, params.Offset) - - resp := PaginatedAIRequestsResponse{ - AIRequests: aiRequests, - Pagination: store.PaginationInfo{ - Total: total, - Limit: params.Limit, - Offset: params.Offset, - }, - } - - writeJSON(w, http.StatusOK, resp) - } -} - -// GetExecutionEmailRequestsHandler returns a handler for getting email requests for an execution -func GetExecutionEmailRequestsHandler(database store.DB, emailTracker email.Tracker) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - params := parsePaginationParams(r) - - // Verify execution exists - _, err := database.GetExecution(r.Context(), id) - if err != nil { - writeError(w, http.StatusNotFound, "Execution not found") - return - } - - // Get email requests for this execution - params = params.Normalize() - emailRequests, total := emailTracker.RequestsPaginated(id, params.Limit, params.Offset) - - resp := PaginatedEmailRequestsResponse{ - EmailRequests: emailRequests, - Pagination: store.PaginationInfo{ - Total: total, - Limit: params.Limit, - Offset: params.Offset, - }, - } - - writeJSON(w, http.StatusOK, resp) - } -} - -// ExecuteFunctionHandler returns a handler for executing functions +// ExecuteFunctionHandler returns the handler for the public /fn/* execution +// passthrough. Unlike the management API (now served over GraphQL), this stays +// REST: it forwards an arbitrary HTTP request to a function and relays the +// function's status code, headers, and body back to the caller verbatim. func ExecuteFunctionHandler(deps ExecuteFunctionDeps) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { functionID := r.PathValue("function_id") @@ -868,60 +174,3 @@ func writeExecutionResponse(w http.ResponseWriter, result *engine.ExecutionResul w.WriteHeader(statusCode) _, _ = w.Write([]byte(result.Response.Body)) } - -// GetNextRunHandler returns a handler for getting the next scheduled run time -func GetNextRunHandler(database store.DB) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - - // Get the function - fn, err := database.GetFunction(r.Context(), id) - if err != nil { - writeError(w, http.StatusNotFound, "Function not found") - return - } - - // Check if the function has an active cron schedule - if fn.CronSchedule == nil || *fn.CronSchedule == "" { - writeJSON(w, http.StatusOK, NextRunResponse{ - HasSchedule: false, - }) - return - } - - if fn.CronStatus == nil || *fn.CronStatus != string(store.CronStatusActive) { - writeJSON(w, http.StatusOK, NextRunResponse{ - HasSchedule: true, - CronSchedule: fn.CronSchedule, - CronStatus: fn.CronStatus, - IsPaused: true, - }) - return - } - - // Calculate next run time - nextRun, err := internalcron.GetNextRunFromSchedule(*fn.CronSchedule) - if err != nil { - writeError(w, http.StatusBadRequest, "Invalid cron schedule") - return - } - - var nextRunUnix *int64 - var nextRunHuman *string - if nextRun != nil { - unix := nextRun.Unix() - nextRunUnix = &unix - human := internalcron.FormatNextRun(*nextRun) - nextRunHuman = &human - } - - writeJSON(w, http.StatusOK, NextRunResponse{ - HasSchedule: true, - CronSchedule: fn.CronSchedule, - CronStatus: fn.CronStatus, - IsPaused: false, - NextRun: nextRunUnix, - NextRunHuman: nextRunHuman, - }) - } -} diff --git a/internal/api/module.go b/internal/api/module.go index d05c45b..44d6fec 100644 --- a/internal/api/module.go +++ b/internal/api/module.go @@ -5,14 +5,9 @@ import ( "log/slog" "net/http" + "github.com/99designs/gqlgen/graphql/handler" "github.com/dimiro1/lunar/internal/config" - internalcron "github.com/dimiro1/lunar/internal/cron" "github.com/dimiro1/lunar/internal/engine" - "github.com/dimiro1/lunar/internal/services/ai" - "github.com/dimiro1/lunar/internal/services/email" - "github.com/dimiro1/lunar/internal/services/env" - "github.com/dimiro1/lunar/internal/services/kv" - "github.com/dimiro1/lunar/internal/services/logger" "github.com/dimiro1/lunar/internal/store" "go.uber.org/fx" ) @@ -25,36 +20,26 @@ var Module = fx.Module("api", ) // serverParams gathers everything the API server needs via dependency -// injection. The engine.Engine is injected as a fully-built graph node rather -// than assembled inside the server. +// injection. The engine.Engine and the GraphQL handler are injected as +// fully-built graph nodes rather than assembled inside the server. type serverParams struct { fx.In - DB store.DB - Engine engine.Engine - Logger logger.Logger - KVStore kv.Store - EnvStore env.Store - AITracker ai.Tracker - EmailTracker email.Tracker - Scheduler *internalcron.FunctionScheduler - Frontend http.Handler - Config config.Config + DB store.DB + Engine engine.Engine + Frontend http.Handler + GraphQL *handler.Server + Config config.Config } func provideServer(p serverParams) *Server { return newServer(serverDeps{ DB: p.DB, Engine: p.Engine, - Logger: p.Logger, - KVStore: p.KVStore, - EnvStore: p.EnvStore, - AITracker: p.AITracker, - EmailTracker: p.EmailTracker, - Scheduler: p.Scheduler, FrontendHandler: p.Frontend, APIKey: p.Config.APIKey, BaseURL: p.Config.BaseURL, + GraphQL: p.GraphQL, }) } diff --git a/internal/api/server.go b/internal/api/server.go index bfd1ad2..3e72694 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -5,8 +5,11 @@ import ( "net/http" "time" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/playground" internalcron "github.com/dimiro1/lunar/internal/cron" "github.com/dimiro1/lunar/internal/engine" + "github.com/dimiro1/lunar/internal/graph" "github.com/dimiro1/lunar/internal/runner" "github.com/dimiro1/lunar/internal/services/ai" "github.com/dimiro1/lunar/internal/services/email" @@ -18,22 +21,20 @@ import ( "github.com/rs/xid" ) -// Server represents the API server +// Server represents the API server. With the management API now served over +// GraphQL, the REST surface is limited to auth (login/device flow), the public +// /fn/* execution passthrough, and the frontend — so the server only holds the +// collaborators those routes and the GraphQL handler need. type Server struct { mux *http.ServeMux db store.DB execDeps *ExecuteFunctionDeps - envStore env.Store - logger logger.Logger - aiTracker ai.Tracker - emailTracker email.Tracker - scheduler *internalcron.FunctionScheduler frontendHandler http.Handler apiKey string httpServer *http.Server - kvStore kv.Store deviceAuth *DeviceAuthStore baseURL string + graphQL *handler.Server } // ServerConfig holds configuration for creating a Server @@ -96,34 +97,32 @@ func NewServer(config ServerConfig) *Server { return newServer(serverDeps{ DB: config.DB, Engine: eng, - Logger: config.Logger, - KVStore: config.KVStore, - EnvStore: config.EnvStore, - AITracker: config.AITracker, - EmailTracker: config.EmailTracker, - Scheduler: config.Scheduler, FrontendHandler: config.FrontendHandler, APIKey: config.APIKey, BaseURL: config.BaseURL, + GraphQL: graph.NewServer(&graph.Resolver{ + DB: config.DB, + EnvStore: config.EnvStore, + KVStore: config.KVStore, + Scheduler: config.Scheduler, + Logger: config.Logger, + AITracker: config.AITracker, + EmailTracker: config.EmailTracker, + }), }) } // serverDeps are the fully-constructed collaborators a Server needs. Unlike -// ServerConfig — which carries the raw ingredients used to build the engine — -// serverDeps takes the engine.Engine already assembled. This is the seam the fx -// graph injects through. +// ServerConfig — which carries the raw ingredients used to build the engine and +// the GraphQL resolver — serverDeps takes the engine.Engine and GraphQL handler +// already assembled. This is the seam the fx graph injects through. type serverDeps struct { DB store.DB Engine engine.Engine - Logger logger.Logger - KVStore kv.Store - EnvStore env.Store - AITracker ai.Tracker - EmailTracker email.Tracker - Scheduler *internalcron.FunctionScheduler FrontendHandler http.Handler APIKey string BaseURL string + GraphQL *handler.Server } // newServer assembles a Server from its constructed dependencies and registers @@ -133,16 +132,11 @@ func newServer(d serverDeps) *Server { mux: http.NewServeMux(), db: d.DB, execDeps: &ExecuteFunctionDeps{Engine: d.Engine, BaseURL: d.BaseURL}, - envStore: d.EnvStore, - logger: d.Logger, - aiTracker: d.AITracker, - emailTracker: d.EmailTracker, - scheduler: d.Scheduler, frontendHandler: d.FrontendHandler, apiKey: d.APIKey, - kvStore: d.KVStore, deviceAuth: NewDeviceAuthStore(), baseURL: d.BaseURL, + graphQL: d.GraphQL, } s.setupRoutes() @@ -159,46 +153,21 @@ func (s *Server) setupRoutes() { s.mux.HandleFunc("POST /api/auth/device-request", HandleDeviceRequest(s.deviceAuth, s.baseURL)) s.mux.HandleFunc("GET /api/auth/device-token", HandleDeviceToken(s.deviceAuth)) - // API documentation (no authentication required) - s.mux.HandleFunc("GET /docs", docsPageHandler) - s.mux.HandleFunc("HEAD /docs", docsPageHandler) - s.mux.HandleFunc("GET /docs/openapi.yaml", openAPISpecHandler) - s.mux.HandleFunc("HEAD /docs/openapi.yaml", openAPISpecHandler) - - // Protected API routes - wrap with auth middleware + // Protected routes - wrap with auth middleware authMiddleware := AuthMiddleware(s.apiKey, s.db) - // Function Management - only need DB - s.mux.Handle("POST /api/functions", authMiddleware(http.HandlerFunc(CreateFunctionHandler(s.db)))) - s.mux.Handle("GET /api/functions", authMiddleware(http.HandlerFunc(ListFunctionsHandler(s.db)))) - s.mux.Handle("GET /api/functions/{id}", authMiddleware(http.HandlerFunc(GetFunctionHandler(s.db, s.envStore, s.kvStore)))) - s.mux.Handle("PUT /api/functions/{id}", authMiddleware(http.HandlerFunc(UpdateFunctionHandler(s.db, s.scheduler)))) - s.mux.Handle("DELETE /api/functions/{id}", authMiddleware(http.HandlerFunc(DeleteFunctionHandler(s.db)))) - s.mux.Handle("PUT /api/functions/{id}/env", authMiddleware(http.HandlerFunc(UpdateEnvVarsHandler(s.db, s.envStore)))) - s.mux.Handle("GET /api/functions/{id}/next-run", authMiddleware(http.HandlerFunc(GetNextRunHandler(s.db)))) - s.mux.Handle("POST /api/functions/{id}/kv", authMiddleware(http.HandlerFunc(UpdateKvStoreHandler(s.db, s.kvStore)))) - - // Version Management - only need DB - s.mux.Handle("GET /api/functions/{id}/versions", authMiddleware(http.HandlerFunc(ListVersionsHandler(s.db)))) - s.mux.Handle("GET /api/functions/{id}/versions/{version}", authMiddleware(http.HandlerFunc(GetVersionHandler(s.db)))) - s.mux.Handle("POST /api/functions/{id}/versions/{versionId}/activate", authMiddleware(http.HandlerFunc(ActivateVersionHandler(s.db)))) - s.mux.Handle("DELETE /api/functions/{id}/versions/{versionId}", authMiddleware(http.HandlerFunc(DeleteVersionHandler(s.db)))) - s.mux.Handle("GET /api/functions/{id}/diff/{v1}/{v2}", authMiddleware(http.HandlerFunc(GetVersionDiffHandler(s.db)))) - - // Execution History - only need DB - s.mux.Handle("GET /api/functions/{id}/executions", authMiddleware(http.HandlerFunc(ListExecutionsHandler(s.db)))) - s.mux.Handle("GET /api/executions/{id}", authMiddleware(http.HandlerFunc(GetExecutionHandler(s.db)))) - s.mux.Handle("GET /api/executions/{id}/logs", authMiddleware(http.HandlerFunc(GetExecutionLogsHandler(s.db, s.logger)))) - s.mux.Handle("GET /api/executions/{id}/ai-requests", authMiddleware(http.HandlerFunc(GetExecutionAIRequestsHandler(s.db, s.aiTracker)))) - s.mux.Handle("GET /api/executions/{id}/email-requests", authMiddleware(http.HandlerFunc(GetExecutionEmailRequestsHandler(s.db, s.emailTracker)))) - - // Device approval (auth required - user must be logged in) + // Device approval (auth required - user must be logged in via the SPA) s.mux.Handle("GET /api/auth/device-approve", authMiddleware(http.HandlerFunc(HandleDeviceApproveStatus(s.deviceAuth)))) s.mux.Handle("POST /api/auth/device-approve", authMiddleware(http.HandlerFunc(HandleDeviceApprove(s.deviceAuth, s.db)))) - // API token management (auth required) - s.mux.Handle("GET /api/tokens", authMiddleware(http.HandlerFunc(HandleListAPITokens(s.db)))) - s.mux.Handle("POST /api/tokens/{id}/revoke", authMiddleware(http.HandlerFunc(HandleRevokeAPIToken(s.db)))) + // GraphQL API — the entire management surface (functions, versions, + // executions, tokens). Query execution (POST) is auth-protected; the + // GraphiQL playground UI (GET) is served publicly and posts back to + // /graphql, which still enforces authentication. + if s.graphQL != nil { + s.mux.Handle("POST /graphql", authMiddleware(s.graphQL)) + s.mux.HandleFunc("GET /graphql", playground.Handler("Lunar GraphQL", "/graphql")) + } // Runtime Execution - needs all dependencies (NO AUTH - public endpoint) // Register both exact match and wildcard patterns for routing support diff --git a/internal/api/server_test.go b/internal/api/server_test.go index bdc8e33..5feae67 100644 --- a/internal/api/server_test.go +++ b/internal/api/server_test.go @@ -40,32 +40,6 @@ func createTestFunction(t *testing.T, database store.DB) store.Function { return created } -// Helper function to create a test version -func createTestVersion(t *testing.T, database store.DB, functionID string, code string) store.FunctionVersion { - t.Helper() - version, err := database.CreateVersion(context.Background(), functionID, code, nil) - if err != nil { - t.Fatalf("failed to create test version: %v", err) - } - return version -} - -// Helper function to create a test execution -func createTestExecution(t *testing.T, database store.DB, functionID, versionID string) store.Execution { - t.Helper() - exec := store.Execution{ - ID: "exec_test_123", - FunctionID: functionID, - FunctionVersionID: versionID, - Status: store.ExecutionStatusSuccess, - } - created, err := database.CreateExecution(context.Background(), exec) - if err != nil { - t.Fatalf("failed to create test execution: %v", err) - } - return created -} - // Helper function to create a test server with full configuration func createTestServer(database store.DB) *Server { return NewServer(ServerConfig{ @@ -92,390 +66,15 @@ func makeAuthRequest(method, path string, body []byte) *http.Request { return req } -func TestDocsPage(t *testing.T) { - server := createTestServer(store.NewMemoryDB()) - - req := httptest.NewRequest(http.MethodGet, "/docs", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Fatalf("expected status 200, got %d", w.Code) - } - - if ct := w.Header().Get("Content-Type"); ct != "text/html; charset=utf-8" { - t.Fatalf("expected Content-Type text/html; charset=utf-8, got %q", ct) - } - - if w.Body.Len() == 0 { - t.Fatal("expected non-empty response body") - } -} - -func TestOpenAPISpecEndpoint(t *testing.T) { - server := createTestServer(store.NewMemoryDB()) - - req := httptest.NewRequest(http.MethodGet, "/docs/openapi.yaml", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Fatalf("expected status 200, got %d", w.Code) - } - - if ct := w.Header().Get("Content-Type"); ct != "application/yaml" { - t.Fatalf("expected Content-Type application/yaml, got %q", ct) - } - - if !bytes.Equal(w.Body.Bytes(), openAPISpec) { - t.Fatal("expected response body to match embedded OpenAPI spec") - } -} - -func TestCreateFunction(t *testing.T) { - server := createTestServer(store.NewMemoryDB()) - - reqBody := CreateFunctionRequest{ - Name: "test-function", - Code: "function handler(ctx, event)\n return {statusCode = 200}\nend", - } - - body, _ := json.Marshal(reqBody) - req := makeAuthRequest(http.MethodPost, "/api/functions", body) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp store.FunctionWithActiveVersion - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } - - if resp.Name != reqBody.Name { - t.Errorf("expected name %q, got %q", reqBody.Name, resp.Name) - } - - if resp.ActiveVersion.Version != 1 { - t.Errorf("expected version 1, got %d", resp.ActiveVersion.Version) - } -} - -func TestListFunctions(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function first - createTestFunction(t, database) - - req := makeAuthRequest(http.MethodGet, "/api/functions", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp PaginatedFunctionsResponse - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } - - if len(resp.Functions) == 0 { - t.Error("expected at least one function") - } -} - -func TestGetFunction(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function first - fn := createTestFunction(t, database) - - req := makeAuthRequest(http.MethodGet, "/api/functions/"+fn.ID, nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp store.FunctionWithActiveVersion - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } - - if resp.ID != fn.ID { - t.Errorf("expected ID %s, got %q", fn.ID, resp.ID) - } -} - -func TestUpdateFunction(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function first - fn := createTestFunction(t, database) - - name := "updated-name" - reqBody := store.UpdateFunctionRequest{ - Name: &name, - } - - body, _ := json.Marshal(reqBody) - req := makeAuthRequest(http.MethodPut, "/api/functions/"+fn.ID, body) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } -} - -func TestDeleteFunction(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function first - fn := createTestFunction(t, database) - - req := makeAuthRequest(http.MethodDelete, "/api/functions/"+fn.ID, nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusNoContent { - t.Errorf("expected status 204, got %d", w.Code) - } -} - -func TestListVersions(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function and version - fn := createTestFunction(t, database) - createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 200}\nend") - - req := makeAuthRequest(http.MethodGet, "/api/functions/"+fn.ID+"/versions", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp PaginatedVersionsResponse - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } - - if len(resp.Versions) == 0 { - t.Error("expected at least one version") - } -} - -func TestGetVersion(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function (which creates version 1) and another version (version 2) - fn := createTestFunction(t, database) - ver := createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 201}\nend") - - // Request version 2 which we just created - req := makeAuthRequest(http.MethodGet, "/api/functions/"+fn.ID+"/versions/2", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp store.FunctionVersion - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } - - if resp.ID != ver.ID { - t.Errorf("expected version ID %s, got %s", ver.ID, resp.ID) - } - - if resp.Version != 2 { - t.Errorf("expected version number 2, got %d", resp.Version) - } -} - -func TestActivateVersion(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function and two versions - fn := createTestFunction(t, database) - v1 := createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 200}\nend") - createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 201}\nend") - - // Use version ID (primary key) instead of version number - req := makeAuthRequest(http.MethodPost, "/api/functions/"+fn.ID+"/versions/"+v1.ID+"/activate", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } -} - -func TestGetVersionDiff(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function and two versions with different code - fn := createTestFunction(t, database) - createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 200}\nend") - createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 201}\nend") - - req := makeAuthRequest(http.MethodGet, "/api/functions/"+fn.ID+"/diff/1/2", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp VersionDiffResponse - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } - - if len(resp.Diff) == 0 { - t.Error("expected at least one diff line") - } -} - -func TestUpdateEnvVars(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function first - fn := createTestFunction(t, database) - - reqBody := UpdateEnvVarsRequest{ - EnvVars: map[string]string{ - "API_KEY": "secret-123", - "DEBUG": "true", - }, - } - - body, _ := json.Marshal(reqBody) - req := makeAuthRequest(http.MethodPut, "/api/functions/"+fn.ID+"/env", body) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } -} - -func TestListExecutions(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function and execution - fn := createTestFunction(t, database) - ver := createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 200}\nend") - createTestExecution(t, database, fn.ID, ver.ID) - - req := makeAuthRequest(http.MethodGet, "/api/functions/"+fn.ID+"/executions", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp PaginatedExecutionsResponse - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } -} - -func TestGetExecution(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function, version and execution - fn := createTestFunction(t, database) - ver := createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 200}\nend") - exec := createTestExecution(t, database, fn.ID, ver.ID) - - req := makeAuthRequest(http.MethodGet, "/api/executions/"+exec.ID, nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp store.Execution - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } -} - -func TestGetExecutionLogs(t *testing.T) { - database := store.NewMemoryDB() - memLogger := logger.NewMemoryLogger() - - server := NewServer(ServerConfig{ - DB: database, - Logger: memLogger, - KVStore: kv.NewMemoryStore(), - EnvStore: env.NewMemoryStore(), - HTTPClient: internalhttp.NewDefaultClient(), - APIKey: "test-api-key", - }) - - // Create a test function, version, execution - fn := createTestFunction(t, database) - ver := createTestVersion(t, database, fn.ID, "function handler(ctx, event)\n return {statusCode = 200}\nend") - exec := createTestExecution(t, database, fn.ID, ver.ID) - - // Create a log entry for the execution using the logger - memLogger.Info(exec.ID, "Test log message") - - req := makeAuthRequest(http.MethodGet, "/api/executions/"+exec.ID+"/logs", nil) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - var resp PaginatedExecutionWithLogs - if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { - t.Fatalf("failed to decode response: %v", err) - } - - if len(resp.Logs) == 0 { - t.Error("expected at least one log entry") - } +// newGraphQLProbe builds an unauthenticated POST /graphql request running a +// trivial query. It is used by the auth-middleware tests to assert that a +// caller is (or isn't) allowed through to a protected route — /graphql being +// the canonical auth-protected endpoint now that the REST management API is +// gone. Callers add the credential (bearer token or cookie) under test. +func newGraphQLProbe() *http.Request { + req := httptest.NewRequest(http.MethodPost, "/graphql", bytes.NewReader([]byte(`{"query":"{ __typename }"}`))) + req.Header.Set("Content-Type", "application/json") + return req } func TestExecuteFunction(t *testing.T) { @@ -898,104 +497,6 @@ end }) } -func TestUpdateFunction_ToggleDisabled(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function first - fn := createTestFunction(t, database) - - // Disable the function - disabled := true - reqBody := store.UpdateFunctionRequest{ - Disabled: &disabled, - } - - body, _ := json.Marshal(reqBody) - req := makeAuthRequest(http.MethodPut, "/api/functions/"+fn.ID, body) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - // Verify the function is disabled - updated, err := database.GetFunction(context.Background(), fn.ID) - if err != nil { - t.Fatalf("failed to get updated function: %v", err) - } - - if !updated.Disabled { - t.Error("expected function to be disabled") - } - - // Enable the function again - enabled := false - reqBody2 := store.UpdateFunctionRequest{ - Disabled: &enabled, - } - - body2, _ := json.Marshal(reqBody2) - req2 := makeAuthRequest(http.MethodPut, "/api/functions/"+fn.ID, body2) - w2 := httptest.NewRecorder() - - server.Handler().ServeHTTP(w2, req2) - - if w2.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w2.Code) - } - - // Verify the function is enabled - reenabled, err := database.GetFunction(context.Background(), fn.ID) - if err != nil { - t.Fatalf("failed to get re-enabled function: %v", err) - } - - if reenabled.Disabled { - t.Error("expected function to be enabled") - } -} - -func TestUpdateFunction_RetentionDays(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function first - fn := createTestFunction(t, database) - - // Update retention days to 30 - retentionDays := 30 - reqBody := store.UpdateFunctionRequest{ - RetentionDays: &retentionDays, - } - - body, _ := json.Marshal(reqBody) - req := makeAuthRequest(http.MethodPut, "/api/functions/"+fn.ID, body) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - // Verify the retention days was updated - updated, err := database.GetFunction(context.Background(), fn.ID) - if err != nil { - t.Fatalf("failed to get updated function: %v", err) - } - - if updated.RetentionDays == nil { - t.Fatal("expected retention_days to be set") - } - - if *updated.RetentionDays != 30 { - t.Errorf("expected retention_days to be 30, got %d", *updated.RetentionDays) - } -} - func TestExecuteFunction_DisabledFunction(t *testing.T) { database := store.NewMemoryDB() server := NewServer(ServerConfig{ @@ -1054,7 +555,7 @@ end func TestCORSMiddleware(t *testing.T) { server := createTestServer(store.NewMemoryDB()) - req := makeAuthRequest(http.MethodOptions, "/api/functions", nil) + req := makeAuthRequest(http.MethodOptions, "/graphql", nil) w := httptest.NewRecorder() server.Handler().ServeHTTP(w, req) @@ -1375,66 +876,6 @@ end } } -func TestUpdateFunction_SaveResponse(t *testing.T) { - database := store.NewMemoryDB() - server := createTestServer(database) - - // Create a test function first - fn := createTestFunction(t, database) - - // Enable save_response - saveResponse := true - reqBody := store.UpdateFunctionRequest{ - SaveResponse: &saveResponse, - } - - body, _ := json.Marshal(reqBody) - req := makeAuthRequest(http.MethodPut, "/api/functions/"+fn.ID, body) - w := httptest.NewRecorder() - - server.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w.Code) - } - - // Verify the save_response was updated - updated, err := database.GetFunction(context.Background(), fn.ID) - if err != nil { - t.Fatalf("failed to get updated function: %v", err) - } - - if !updated.SaveResponse { - t.Error("expected save_response to be true") - } - - // Disable save_response - saveResponseFalse := false - reqBody2 := store.UpdateFunctionRequest{ - SaveResponse: &saveResponseFalse, - } - - body2, _ := json.Marshal(reqBody2) - req2 := makeAuthRequest(http.MethodPut, "/api/functions/"+fn.ID, body2) - w2 := httptest.NewRecorder() - - server.Handler().ServeHTTP(w2, req2) - - if w2.Code != http.StatusOK { - t.Errorf("expected status 200, got %d", w2.Code) - } - - // Verify the save_response was updated - updated2, err := database.GetFunction(context.Background(), fn.ID) - if err != nil { - t.Fatalf("failed to get updated function: %v", err) - } - - if updated2.SaveResponse { - t.Error("expected save_response to be false") - } -} - func TestExecuteFunction_SaveResponse(t *testing.T) { t.Run("saves response when enabled", func(t *testing.T) { database := store.NewMemoryDB() diff --git a/internal/api/types.go b/internal/api/types.go index 5e72b56..7b12604 100644 --- a/internal/api/types.go +++ b/internal/api/types.go @@ -1,137 +1,5 @@ package api -import "github.com/dimiro1/lunar/internal/store" - -// LogLevel represents the severity level of a log entry -type LogLevel string - -const ( - LogLevelDebug LogLevel = "debug" - LogLevelInfo LogLevel = "info" - LogLevelWarn LogLevel = "warn" - LogLevelError LogLevel = "error" -) - -// DiffLineType represents the type of change in a diff line -type DiffLineType string - -const ( - DiffLineUnchanged DiffLineType = "unchanged" - DiffLineAdded DiffLineType = "added" - DiffLineRemoved DiffLineType = "removed" -) - -// LogEntry represents a log entry from function execution -type LogEntry struct { - Level LogLevel `json:"level"` - Message string `json:"message"` - CreatedAt int64 `json:"created_at"` -} - -// DiffLine represents a line in a version diff -type DiffLine struct { - LineType DiffLineType `json:"line_type"` - OldLine *int `json:"old_line,omitempty"` - NewLine *int `json:"new_line,omitempty"` - Content string `json:"content"` -} - -// CreateFunctionRequest is the request body for creating a function -type CreateFunctionRequest struct { - Name string `json:"name"` - Description *string `json:"description,omitempty"` - Code string `json:"code"` -} - -// UpdateEnvVarsRequest is the request body for updating environment variables -type UpdateEnvVarsRequest struct { - EnvVars map[string]string `json:"env_vars"` -} - -// UpdateKvStoreRequest is the request body for updating the KV store -type UpdateKvStoreRequest struct { - Global bool `json:"global"` - Kv map[string]string `json:"kv"` -} - -// ListFunctionsResponse is the response for listing functions -type ListFunctionsResponse struct { - Functions []store.FunctionWithActiveVersion `json:"functions"` -} - -// ListVersionsResponse is the response for listing versions -type ListVersionsResponse struct { - Versions []store.FunctionVersion `json:"versions"` -} - -// ListExecutionsResponse is the response for listing executions -type ListExecutionsResponse struct { - Executions []store.Execution `json:"executions"` -} - -// ExecutionWithLogs includes execution details and logs -type ExecutionWithLogs struct { - store.Execution - Logs []LogEntry `json:"logs"` -} - -// VersionDiffResponse is the response for version diff -type VersionDiffResponse struct { - OldVersion int `json:"old_version"` - NewVersion int `json:"new_version"` - Diff []DiffLine `json:"diff"` -} - -// ErrorResponse is the standard error response -type ErrorResponse struct { - Error string `json:"error"` -} - -// Pagination types moved to internal/db package - re-exported in store.go for compatibility - -// PaginatedFunctionsResponse is the paginated response for listing functions -type PaginatedFunctionsResponse struct { - Functions []store.FunctionWithActiveVersion `json:"functions"` - Pagination store.PaginationInfo `json:"pagination"` -} - -// PaginatedVersionsResponse is the paginated response for listing versions -type PaginatedVersionsResponse struct { - Versions []store.FunctionVersion `json:"versions"` - Pagination store.PaginationInfo `json:"pagination"` -} - -// PaginatedExecutionsResponse is the paginated response for listing executions -type PaginatedExecutionsResponse struct { - Executions []store.Execution `json:"executions"` - Pagination store.PaginationInfo `json:"pagination"` -} - -// PaginatedLogsResponse is the paginated response for listing logs -type PaginatedLogsResponse struct { - Logs []LogEntry `json:"logs"` - Pagination store.PaginationInfo `json:"pagination"` -} - -// PaginatedExecutionWithLogs includes execution details with paginated logs -type PaginatedExecutionWithLogs struct { - store.Execution - Logs []LogEntry `json:"logs"` - Pagination store.PaginationInfo `json:"pagination"` -} - -// PaginatedAIRequestsResponse is the paginated response for AI requests -type PaginatedAIRequestsResponse struct { - AIRequests []store.AIRequest `json:"ai_requests"` - Pagination store.PaginationInfo `json:"pagination"` -} - -// PaginatedEmailRequestsResponse is the paginated response for email requests -type PaginatedEmailRequestsResponse struct { - EmailRequests []store.EmailRequest `json:"email_requests"` - Pagination store.PaginationInfo `json:"pagination"` -} - // DeviceRequestResponse is the response for POST /api/auth/device-request type DeviceRequestResponse struct { DeviceCode string `json:"device_code"` @@ -160,13 +28,3 @@ type DeviceTokenResponse struct { Status string `json:"status"` Token string `json:"token,omitempty"` } - -// NextRunResponse is the response for getting the next scheduled run time -type NextRunResponse struct { - HasSchedule bool `json:"has_schedule"` - CronSchedule *string `json:"cron_schedule,omitempty"` - CronStatus *string `json:"cron_status,omitempty"` - IsPaused bool `json:"is_paused,omitempty"` - NextRun *int64 `json:"next_run,omitempty"` - NextRunHuman *string `json:"next_run_human,omitempty"` -} diff --git a/internal/api/validation.go b/internal/api/validation.go deleted file mode 100644 index 9894737..0000000 --- a/internal/api/validation.go +++ /dev/null @@ -1,340 +0,0 @@ -package api - -import ( - "fmt" - "slices" - "strings" - - "github.com/dimiro1/lunar/internal/store" - "github.com/robfig/cron/v3" -) - -const ( - // MaxPageSize is the maximum allowed page size for pagination - MaxPageSize = 100 - // MaxFunctionNameLength is the maximum length for function names - MaxFunctionNameLength = 100 - // MaxDescriptionLength is the maximum length for function descriptions - MaxDescriptionLength = 500 - // MaxCodeLength is the maximum length for function code - MaxCodeLength = 1024 * 1024 // 1MB - // MaxEnvVarKeyLength is the maximum length for environment variable keys - MaxEnvVarKeyLength = 100 - // MaxEnvVarValueLength is the maximum length for environment variable values - MaxEnvVarValueLength = 10000 - // MaxEnvVars is the maximum number of environment variables per function - MaxEnvVars = 100 - // MaxStoreKeyLength is the maximum length for store keys - MaxStoreKeyLength = 100 - // MaxStoreValueLength is the maximum length for store values - MaxStoreValueLength = 10000 -) - -var AllowedRetentionDays = []int{7, 15, 30, 365} -var AllowedCronStatuses = []string{string(store.CronStatusActive), string(store.CronStatusPaused)} - -// ValidationError represents a validation error -type ValidationError struct { - Field string - Message string -} - -func (e *ValidationError) Error() string { - return fmt.Sprintf("%s: %s", e.Field, e.Message) -} - -// ValidateCreateFunctionRequest validates a CreateFunctionRequest -func ValidateCreateFunctionRequest(req *CreateFunctionRequest) error { - if req == nil { - return &ValidationError{Field: "request", Message: "request cannot be nil"} - } - - // Validate name - if err := validateFunctionName(req.Name); err != nil { - return err - } - - // Validate description if provided - if req.Description != nil { - if err := validateDescription(*req.Description); err != nil { - return err - } - } - - // Validate code - if err := validateCode(req.Code); err != nil { - return err - } - - return nil -} - -// ValidateUpdateFunctionRequest validates an UpdateFunctionRequest -func ValidateUpdateFunctionRequest(req *store.UpdateFunctionRequest) error { - if req == nil { - return &ValidationError{Field: "request", Message: "request cannot be nil"} - } - - // At least one field must be provided - if req.Name == nil && req.Description == nil && req.Code == nil && req.Disabled == nil && req.RetentionDays == nil && req.CronSchedule == nil && req.CronStatus == nil && req.SaveResponse == nil { - return &ValidationError{Field: "request", Message: "at least one field must be provided for update"} - } - - // Validate name if provided - if req.Name != nil { - if err := validateFunctionName(*req.Name); err != nil { - return err - } - } - - // Validate description if provided - if req.Description != nil { - if err := validateDescription(*req.Description); err != nil { - return err - } - } - - // Validate code if provided - if req.Code != nil { - if err := validateCode(*req.Code); err != nil { - return err - } - } - - // Validate retention_days if provided - if req.RetentionDays != nil { - if err := validateRetentionDays(*req.RetentionDays); err != nil { - return err - } - } - - // Validate cron_schedule if provided - if req.CronSchedule != nil { - if err := validateCronSchedule(*req.CronSchedule); err != nil { - return err - } - } - - // Validate cron_status if provided - if req.CronStatus != nil { - if err := validateCronStatus(*req.CronStatus); err != nil { - return err - } - } - - return nil -} - -// ValidateUpdateEnvVarsRequest validates an UpdateEnvVarsRequest -func ValidateUpdateEnvVarsRequest(req *UpdateEnvVarsRequest) error { - if req == nil { - return &ValidationError{Field: "request", Message: "request cannot be nil"} - } - - if req.EnvVars == nil { - return &ValidationError{Field: "env_vars", Message: "env_vars cannot be nil"} - } - - if len(req.EnvVars) > MaxEnvVars { - return &ValidationError{ - Field: "env_vars", - Message: fmt.Sprintf("cannot have more than %d environment variables", MaxEnvVars), - } - } - - for key, value := range req.EnvVars { - if err := validateEnvVarKey(key); err != nil { - return err - } - if err := validateEnvVarValue(value); err != nil { - return err - } - } - - return nil -} - -// validateFunctionName validates a function name -func validateFunctionName(name string) error { - trimmed := strings.TrimSpace(name) - if trimmed == "" { - return &ValidationError{Field: "name", Message: "name cannot be empty"} - } - if len(trimmed) > MaxFunctionNameLength { - return &ValidationError{ - Field: "name", - Message: fmt.Sprintf("name cannot be longer than %d characters", MaxFunctionNameLength), - } - } - return nil -} - -// validateDescription validates a function description -func validateDescription(description string) error { - if len(description) > MaxDescriptionLength { - return &ValidationError{ - Field: "description", - Message: fmt.Sprintf("description cannot be longer than %d characters", MaxDescriptionLength), - } - } - return nil -} - -// validateCode validates function code -func validateCode(code string) error { - trimmed := strings.TrimSpace(code) - if trimmed == "" { - return &ValidationError{Field: "code", Message: "code cannot be empty"} - } - if len(code) > MaxCodeLength { - return &ValidationError{ - Field: "code", - Message: fmt.Sprintf("code cannot be longer than %d bytes", MaxCodeLength), - } - } - return nil -} - -// validateEnvVarKey validates an environment variable key -func validateEnvVarKey(key string) error { - trimmed := strings.TrimSpace(key) - if trimmed == "" { - return &ValidationError{Field: "env_var_key", Message: "environment variable key cannot be empty"} - } - if len(key) > MaxEnvVarKeyLength { - return &ValidationError{ - Field: "env_var_key", - Message: fmt.Sprintf("environment variable key cannot be longer than %d characters", MaxEnvVarKeyLength), - } - } - // Additional validation: keys should only contain alphanumeric and underscores - if !isValidEnvVarKey(key) { - return &ValidationError{ - Field: "env_var_key", - Message: "environment variable key can only contain letters, numbers, and underscores", - } - } - return nil -} - -// validateEnvVarValue validates an environment variable value -func validateEnvVarValue(value string) error { - trimmed := strings.TrimSpace(value) - if trimmed == "" { - return &ValidationError{Field: "env_var_value", Message: "environment variable value cannot be empty"} - } - if len(value) > MaxEnvVarValueLength { - return &ValidationError{ - Field: "env_var_value", - Message: fmt.Sprintf("environment variable value cannot be longer than %d characters", MaxEnvVarValueLength), - } - } - return nil -} - -// isValidEnvVarKey checks if a string is a valid environment variable key -func isValidEnvVarKey(key string) bool { - if key == "" { - return false - } - for _, char := range key { - if (char < 'a' || char > 'z') && (char < 'A' || char > 'Z') && (char < '0' || char > '9') && char != '_' { - return false - } - } - return true -} - -// validateRetentionDays validates retention days value -func validateRetentionDays(days int) error { - // Check if the value is in the allowed list - if slices.Contains(AllowedRetentionDays, days) { - return nil - } - return &ValidationError{ - Field: "retention_days", - Message: fmt.Sprintf("retention_days must be one of: %v", AllowedRetentionDays), - } -} - -// validateCronSchedule validates a cron expression -func validateCronSchedule(schedule string) error { - // Empty schedule is allowed (to clear the schedule) - if schedule == "" { - return nil - } - - // Parse the cron expression using the robfig/cron parser - parser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow) - _, err := parser.Parse(schedule) - if err != nil { - return &ValidationError{ - Field: "cron_schedule", - Message: fmt.Sprintf("invalid cron expression: %v", err), - } - } - return nil -} - -// validateCronStatus validates a cron status value -func validateCronStatus(status string) error { - if slices.Contains(AllowedCronStatuses, status) { - return nil - } - return &ValidationError{ - Field: "cron_status", - Message: fmt.Sprintf("cron_status must be one of: %v", AllowedCronStatuses), - } -} - -// validateStoreKey validates a store key -func validateStoreKey(key string) error { - trimmed := strings.TrimSpace(key) - if trimmed == "" { - return &ValidationError{Field: "key", Message: "key cannot be empty"} - } - if len(key) > MaxStoreKeyLength { - return &ValidationError{ - Field: "key", - Message: fmt.Sprintf("key cannot be longer than %d characters", MaxStoreKeyLength), - } - } - return nil -} - -// validateStoreValue validates a store value -func validateStoreValue(value string) error { - trimmed := strings.TrimSpace(value) - if trimmed == "" { - return &ValidationError{Field: "value", Message: "value cannot be empty"} - } - if len(value) > MaxStoreValueLength { - return &ValidationError{ - Field: "value", - Message: fmt.Sprintf("value cannot be longer than %d characters", MaxStoreValueLength), - } - } - return nil -} - -// ValidateUpdateKvStoreRequest validates an UpdateKvStoreRequest -func ValidateUpdateKvStoreRequest(req *UpdateKvStoreRequest) error { - if req == nil { - return &ValidationError{Field: "request", Message: "request cannot be nil"} - } - - if req.Kv == nil { - return &ValidationError{Field: "kv", Message: "kv cannot be nil"} - } - - for key, value := range req.Kv { - if err := validateStoreKey(key); err != nil { - return err - } - if err := validateStoreValue(value); err != nil { - return err - } - } - - return nil -} diff --git a/internal/api/validation_test.go b/internal/api/validation_test.go deleted file mode 100644 index 32f9444..0000000 --- a/internal/api/validation_test.go +++ /dev/null @@ -1,721 +0,0 @@ -package api - -import ( - "strings" - "testing" - - "github.com/dimiro1/lunar/internal/store" -) - -func TestValidateCreateFunctionRequest(t *testing.T) { - tests := []struct { - name string - req *CreateFunctionRequest - wantErr bool - errMsg string - }{ - { - name: "valid request", - req: &CreateFunctionRequest{ - Name: "test-function", - Code: "function handler() end", - }, - wantErr: false, - }, - { - name: "valid request with description", - req: &CreateFunctionRequest{ - Name: "test-function", - Description: new("A test function"), - Code: "function handler() end", - }, - wantErr: false, - }, - { - name: "nil request", - req: nil, - wantErr: true, - errMsg: "request cannot be nil", - }, - { - name: "empty name", - req: &CreateFunctionRequest{ - Name: "", - Code: "function handler() end", - }, - wantErr: true, - errMsg: "name cannot be empty", - }, - { - name: "whitespace only name", - req: &CreateFunctionRequest{ - Name: " ", - Code: "function handler() end", - }, - wantErr: true, - errMsg: "name cannot be empty", - }, - { - name: "name too long", - req: &CreateFunctionRequest{ - Name: strings.Repeat("a", MaxFunctionNameLength+1), - Code: "function handler() end", - }, - wantErr: true, - errMsg: "name cannot be longer", - }, - { - name: "empty code", - req: &CreateFunctionRequest{ - Name: "test-function", - Code: "", - }, - wantErr: true, - errMsg: "code cannot be empty", - }, - { - name: "whitespace only code", - req: &CreateFunctionRequest{ - Name: "test-function", - Code: " \n \t ", - }, - wantErr: true, - errMsg: "code cannot be empty", - }, - { - name: "code too long", - req: &CreateFunctionRequest{ - Name: "test-function", - Code: strings.Repeat("a", MaxCodeLength+1), - }, - wantErr: true, - errMsg: "code cannot be longer", - }, - { - name: "description too long", - req: &CreateFunctionRequest{ - Name: "test-function", - Description: new(strings.Repeat("a", MaxDescriptionLength+1)), - Code: "function handler() end", - }, - wantErr: true, - errMsg: "description cannot be longer", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateCreateFunctionRequest(tt.req) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateCreateFunctionRequest() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("ValidateCreateFunctionRequest() error = %v, should contain %v", err, tt.errMsg) - } - }) - } -} - -func TestValidateUpdateFunctionRequest(t *testing.T) { - tests := []struct { - name string - req *store.UpdateFunctionRequest - wantErr bool - errMsg string - }{ - { - name: "valid request with name", - req: &store.UpdateFunctionRequest{ - Name: new("new-name"), - }, - wantErr: false, - }, - { - name: "valid request with code", - req: &store.UpdateFunctionRequest{ - Code: new("function handler() end"), - }, - wantErr: false, - }, - { - name: "valid request with all fields", - req: &store.UpdateFunctionRequest{ - Name: new("new-name"), - Description: new("new description"), - Code: new("function handler() end"), - }, - wantErr: false, - }, - { - name: "nil request", - req: nil, - wantErr: true, - errMsg: "request cannot be nil", - }, - { - name: "empty request", - req: &store.UpdateFunctionRequest{}, - wantErr: true, - errMsg: "at least one field must be provided", - }, - { - name: "invalid name", - req: &store.UpdateFunctionRequest{ - Name: new(""), - }, - wantErr: true, - errMsg: "name cannot be empty", - }, - { - name: "invalid code", - req: &store.UpdateFunctionRequest{ - Code: new(""), - }, - wantErr: true, - errMsg: "code cannot be empty", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateUpdateFunctionRequest(tt.req) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, should contain %v", err, tt.errMsg) - } - }) - } -} - -func TestValidateUpdateEnvVarsRequest(t *testing.T) { - tests := []struct { - name string - req *UpdateEnvVarsRequest - wantErr bool - errMsg string - }{ - { - name: "valid request", - req: &UpdateEnvVarsRequest{ - EnvVars: map[string]string{ - "API_KEY": "secret", - "PORT": "3000", - }, - }, - wantErr: false, - }, - { - name: "valid empty env vars", - req: &UpdateEnvVarsRequest{ - EnvVars: map[string]string{}, - }, - wantErr: false, - }, - { - name: "nil request", - req: nil, - wantErr: true, - errMsg: "request cannot be nil", - }, - { - name: "nil env vars", - req: &UpdateEnvVarsRequest{ - EnvVars: nil, - }, - wantErr: true, - errMsg: "env_vars cannot be nil", - }, - { - name: "invalid env var key - empty", - req: &UpdateEnvVarsRequest{ - EnvVars: map[string]string{ - "": "value", - }, - }, - wantErr: true, - errMsg: "key cannot be empty", - }, - { - name: "invalid env var key - special chars", - req: &UpdateEnvVarsRequest{ - EnvVars: map[string]string{ - "API-KEY": "value", - }, - }, - wantErr: true, - errMsg: "can only contain letters, numbers, and underscores", - }, - { - name: "invalid env var key - too long", - req: &UpdateEnvVarsRequest{ - EnvVars: map[string]string{ - strings.Repeat("A", MaxEnvVarKeyLength+1): "value", - }, - }, - wantErr: true, - errMsg: "key cannot be longer", - }, - { - name: "invalid env var value - empty", - req: &UpdateEnvVarsRequest{ - EnvVars: map[string]string{ - "KEY": "", - }, - }, - wantErr: true, - errMsg: "value cannot be empty", - }, - { - name: "invalid env var value - whitespace only", - req: &UpdateEnvVarsRequest{ - EnvVars: map[string]string{ - "KEY": " ", - }, - }, - wantErr: true, - errMsg: "value cannot be empty", - }, - { - name: "invalid env var value - too long", - req: &UpdateEnvVarsRequest{ - EnvVars: map[string]string{ - "KEY": strings.Repeat("a", MaxEnvVarValueLength+1), - }, - }, - wantErr: true, - errMsg: "value cannot be longer", - }, - { - name: "too many env vars", - req: &UpdateEnvVarsRequest{ - EnvVars: func() map[string]string { - m := make(map[string]string) - for i := range MaxEnvVars + 1 { - m[strings.Repeat("A", i%10+1)+string(rune(i))] = "value" - } - return m - }(), - }, - wantErr: true, - errMsg: "cannot have more than", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateUpdateEnvVarsRequest(tt.req) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateUpdateEnvVarsRequest() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("ValidateUpdateEnvVarsRequest() error = %v, should contain %v", err, tt.errMsg) - } - }) - } -} - -func TestIsValidEnvVarKey(t *testing.T) { - tests := []struct { - key string - valid bool - }{ - {"API_KEY", true}, - {"PORT", true}, - {"DB_HOST_1", true}, - {"_PRIVATE", true}, - {"snake_case_key", true}, - {"UPPERCASE_KEY", true}, - {"MixedCase123", true}, - {"", false}, - {"API-KEY", false}, - {"API.KEY", false}, - {"API KEY", false}, - {"API@KEY", false}, - {"123", true}, - {"_123", true}, - } - - for _, tt := range tests { - t.Run(tt.key, func(t *testing.T) { - if got := isValidEnvVarKey(tt.key); got != tt.valid { - t.Errorf("isValidEnvVarKey(%q) = %v, want %v", tt.key, got, tt.valid) - } - }) - } -} - -func TestValidateRetentionDays(t *testing.T) { - tests := []struct { - name string - days int - wantErr bool - errMsg string - }{ - { - name: "valid 7 days", - days: 7, - wantErr: false, - }, - { - name: "valid 15 days", - days: 15, - wantErr: false, - }, - { - name: "valid 30 days", - days: 30, - wantErr: false, - }, - { - name: "valid 365 days (1 year)", - days: 365, - wantErr: false, - }, - { - name: "invalid 1 day", - days: 1, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "invalid 5 days", - days: 5, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "invalid 60 days", - days: 60, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "invalid 500 days", - days: 500, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "invalid 0 days", - days: 0, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "invalid negative days", - days: -1, - wantErr: true, - errMsg: "must be one of", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := validateRetentionDays(tt.days) - if (err != nil) != tt.wantErr { - t.Errorf("validateRetentionDays() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("validateRetentionDays() error = %v, should contain %v", err, tt.errMsg) - } - }) - } -} - -func TestValidateUpdateFunctionRequest_WithRetentionDays(t *testing.T) { - tests := []struct { - name string - req *store.UpdateFunctionRequest - wantErr bool - errMsg string - }{ - { - name: "valid retention days 7", - req: &store.UpdateFunctionRequest{ - RetentionDays: new(7), - }, - wantErr: false, - }, - { - name: "valid retention days 30", - req: &store.UpdateFunctionRequest{ - RetentionDays: new(30), - }, - wantErr: false, - }, - { - name: "invalid retention days 5", - req: &store.UpdateFunctionRequest{ - RetentionDays: new(5), - }, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "invalid retention days 100", - req: &store.UpdateFunctionRequest{ - RetentionDays: new(100), - }, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "combined update with valid retention days", - req: &store.UpdateFunctionRequest{ - Name: new("new-name"), - RetentionDays: new(15), - }, - wantErr: false, - }, - { - name: "combined update with invalid retention days", - req: &store.UpdateFunctionRequest{ - Name: new("new-name"), - RetentionDays: new(20), - }, - wantErr: true, - errMsg: "must be one of", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateUpdateFunctionRequest(tt.req) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, should contain %v", err, tt.errMsg) - } - }) - } -} - -func TestValidateUpdateFunctionRequest_WithCronSchedule(t *testing.T) { - tests := []struct { - name string - req *store.UpdateFunctionRequest - wantErr bool - errMsg string - }{ - { - name: "valid cron schedule - every 5 minutes", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("*/5 * * * *"), - }, - wantErr: false, - }, - { - name: "valid cron schedule - every hour", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("0 * * * *"), - }, - wantErr: false, - }, - { - name: "valid cron schedule - every day at midnight", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("0 0 * * *"), - }, - wantErr: false, - }, - { - name: "valid cron schedule - weekdays at 9am", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("0 9 * * 1-5"), - }, - wantErr: false, - }, - { - name: "valid cron schedule - first day of month", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("0 0 1 * *"), - }, - wantErr: false, - }, - { - name: "valid empty cron schedule (to clear)", - req: &store.UpdateFunctionRequest{ - CronSchedule: new(""), - }, - wantErr: false, - }, - { - name: "invalid cron schedule - too few fields", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("* * *"), - }, - wantErr: true, - errMsg: "invalid cron expression", - }, - { - name: "invalid cron schedule - too many fields", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("* * * * * *"), - }, - wantErr: true, - errMsg: "invalid cron expression", - }, - { - name: "invalid cron schedule - bad minute value", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("60 * * * *"), - }, - wantErr: true, - errMsg: "invalid cron expression", - }, - { - name: "invalid cron schedule - bad hour value", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("* 25 * * *"), - }, - wantErr: true, - errMsg: "invalid cron expression", - }, - { - name: "invalid cron schedule - invalid syntax", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("not a cron"), - }, - wantErr: true, - errMsg: "invalid cron expression", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateUpdateFunctionRequest(tt.req) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, should contain %v", err, tt.errMsg) - } - }) - } -} - -func TestValidateUpdateFunctionRequest_WithSaveResponse(t *testing.T) { - tests := []struct { - name string - req *store.UpdateFunctionRequest - wantErr bool - }{ - { - name: "valid save_response true", - req: &store.UpdateFunctionRequest{ - SaveResponse: new(true), - }, - wantErr: false, - }, - { - name: "valid save_response false", - req: &store.UpdateFunctionRequest{ - SaveResponse: new(false), - }, - wantErr: false, - }, - { - name: "combined update with save_response", - req: &store.UpdateFunctionRequest{ - Name: new("new-name"), - SaveResponse: new(true), - }, - wantErr: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateUpdateFunctionRequest(tt.req) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestValidateUpdateFunctionRequest_WithCronStatus(t *testing.T) { - tests := []struct { - name string - req *store.UpdateFunctionRequest - wantErr bool - errMsg string - }{ - { - name: "valid cron status - active", - req: &store.UpdateFunctionRequest{ - CronStatus: new("active"), - }, - wantErr: false, - }, - { - name: "valid cron status - paused", - req: &store.UpdateFunctionRequest{ - CronStatus: new("paused"), - }, - wantErr: false, - }, - { - name: "invalid cron status - stopped", - req: &store.UpdateFunctionRequest{ - CronStatus: new("stopped"), - }, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "invalid cron status - enabled", - req: &store.UpdateFunctionRequest{ - CronStatus: new("enabled"), - }, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "invalid cron status - empty", - req: &store.UpdateFunctionRequest{ - CronStatus: new(""), - }, - wantErr: true, - errMsg: "must be one of", - }, - { - name: "valid combined cron schedule and status", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("*/5 * * * *"), - CronStatus: new("active"), - }, - wantErr: false, - }, - { - name: "valid cron schedule with paused status", - req: &store.UpdateFunctionRequest{ - CronSchedule: new("0 * * * *"), - CronStatus: new("paused"), - }, - wantErr: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := ValidateUpdateFunctionRequest(tt.req) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil && tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("ValidateUpdateFunctionRequest() error = %v, should contain %v", err, tt.errMsg) - } - }) - } -} diff --git a/internal/graph/domains_test.go b/internal/graph/domains_test.go new file mode 100644 index 0000000..b5cc755 --- /dev/null +++ b/internal/graph/domains_test.go @@ -0,0 +1,217 @@ +package graph_test + +import ( + "context" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/dimiro1/lunar/internal/store" +) + +func TestFunctionMutations(t *testing.T) { + c, db, envStore, _ := newTestClient(t) + ctx := context.Background() + + var created struct { + CreateFunction struct { + ID string + Name string + ActiveVersion struct{ Code string } + } + } + c.MustPost(`mutation { + createFunction(input: {name: "hello", code: "return 1"}) { + id name activeVersion { code } + } + }`, &created) + id := created.CreateFunction.ID + if id == "" || created.CreateFunction.Name != "hello" || created.CreateFunction.ActiveVersion.Code != "return 1" { + t.Fatalf("createFunction = %+v", created.CreateFunction) + } + if _, err := db.GetFunction(ctx, id); err != nil { + t.Fatalf("GetFunction after create: %v", err) + } + + // Update metadata and supply new code → a new active version. + var updated struct { + UpdateFunction struct { + Name string + ActiveVersion struct { + Version int + Code string + } + } + } + c.MustPost(`mutation($id: ID!) { + updateFunction(id: $id, input: {name: "renamed", code: "return 2"}) { + name activeVersion { version code } + } + }`, &updated, client.Var("id", id)) + if updated.UpdateFunction.Name != "renamed" { + t.Errorf("updated name = %q, want renamed", updated.UpdateFunction.Name) + } + if updated.UpdateFunction.ActiveVersion.Version != 2 || updated.UpdateFunction.ActiveVersion.Code != "return 2" { + t.Errorf("updated activeVersion = %+v, want v2 'return 2'", updated.UpdateFunction.ActiveVersion) + } + + // Replace env vars (Map scalar input), then read them back. + var env struct { + SetFunctionEnv struct { + EnvVars map[string]string + } + } + c.MustPost(`mutation($id: ID!, $env: Map!) { + setFunctionEnv(id: $id, env: $env) { envVars } + }`, &env, client.Var("id", id), client.Var("env", map[string]string{"API_KEY": "secret"})) + if env.SetFunctionEnv.EnvVars["API_KEY"] != "secret" { + t.Errorf("setFunctionEnv envVars = %+v", env.SetFunctionEnv.EnvVars) + } + if envStore.vars["API_KEY"] != "secret" { + t.Errorf("env store not updated: %+v", envStore.vars) + } + + // Delete, then confirm it is gone (null). + var deleted struct{ DeleteFunction bool } + c.MustPost(`mutation($id: ID!) { deleteFunction(id: $id) }`, &deleted, client.Var("id", id)) + if !deleted.DeleteFunction { + t.Error("deleteFunction = false, want true") + } + var gone struct { + Function *struct{ ID string } + } + c.MustPost(`query($id: ID!) { function(id: $id) { id } }`, &gone, client.Var("id", id)) + if gone.Function != nil { + t.Errorf("function after delete = %+v, want nil", gone.Function) + } +} + +// TestExecutionEnums verifies the enums bound to the store string types marshal +// to their GraphQL enum values over the wire. +func TestExecutionEnums(t *testing.T) { + c, db, _, _ := newTestClient(t) + ctx := context.Background() + seedFunction(t, db, "fn1", "hello", "return 1") + + dur := int64(42) + if _, err := db.CreateExecution(ctx, store.Execution{ + ID: "exec1", + FunctionID: "fn1", + FunctionVersionID: "v1", + Status: store.ExecutionStatusSuccess, + Trigger: store.ExecutionTriggerHTTP, + DurationMs: &dur, + CreatedAt: 1000, + }); err != nil { + t.Fatalf("CreateExecution: %v", err) + } + + var resp struct { + Execution *struct { + ID string + Status string + Trigger string + DurationMs *int + } + } + c.MustPost(`{ execution(id: "exec1") { id status trigger durationMs } }`, &resp) + if resp.Execution == nil { + t.Fatal("execution(exec1) = nil") + } + if resp.Execution.Status != "success" { + t.Errorf("status = %q, want success", resp.Execution.Status) + } + if resp.Execution.Trigger != "http" { + t.Errorf("trigger = %q, want http", resp.Execution.Trigger) + } + if resp.Execution.DurationMs == nil || *resp.Execution.DurationMs != 42 { + t.Errorf("durationMs = %v, want 42", resp.Execution.DurationMs) + } + + var list struct { + Executions struct { + Nodes []struct{ ID string } + PageInfo struct{ Total int } + } + } + c.MustPost(`{ executions(functionId: "fn1") { nodes { id } pageInfo { total } } }`, &list) + if list.Executions.PageInfo.Total != 1 || len(list.Executions.Nodes) != 1 { + t.Errorf("executions = %+v, want 1", list.Executions) + } +} + +func TestVersionDiff(t *testing.T) { + c, db, _, _ := newTestClient(t) + ctx := context.Background() + if _, err := db.CreateFunction(ctx, store.Function{ID: "fn1", Name: "f"}); err != nil { + t.Fatal(err) + } + if _, err := db.CreateVersion(ctx, "fn1", "line1\nline2", nil); err != nil { + t.Fatal(err) + } + if _, err := db.CreateVersion(ctx, "fn1", "line1\nCHANGED", nil); err != nil { + t.Fatal(err) + } + + var resp struct { + VersionDiff struct { + OldVersion int + NewVersion int + Lines []struct { + LineType string + Content string + } + } + } + c.MustPost(`{ + versionDiff(functionId: "fn1", oldVersion: 1, newVersion: 2) { + oldVersion newVersion lines { lineType content } + } + }`, &resp) + + if resp.VersionDiff.OldVersion != 1 || resp.VersionDiff.NewVersion != 2 { + t.Errorf("versions = %d/%d, want 1/2", resp.VersionDiff.OldVersion, resp.VersionDiff.NewVersion) + } + var added, removed int + for _, l := range resp.VersionDiff.Lines { + switch l.LineType { + case "added": + added++ + case "removed": + removed++ + } + } + if added == 0 || removed == 0 { + t.Errorf("expected added & removed diff lines; got added=%d removed=%d", added, removed) + } +} + +func TestTokens(t *testing.T) { + c, db, _, _ := newTestClient(t) + ctx := context.Background() + if _, err := db.CreateAPIToken(ctx, store.APIToken{ID: "tok1", Name: "cli", TokenHash: "h"}); err != nil { + t.Fatal(err) + } + + var list struct { + APITokens []struct { + ID string + Name string + Revoked bool + } + } + c.MustPost(`{ apiTokens { id name revoked } }`, &list) + if len(list.APITokens) != 1 || list.APITokens[0].ID != "tok1" || list.APITokens[0].Revoked { + t.Fatalf("apiTokens = %+v", list.APITokens) + } + + var revoke struct{ RevokeApiToken bool } + c.MustPost(`mutation { revokeApiToken(id: "tok1") }`, &revoke) + if !revoke.RevokeApiToken { + t.Error("revokeApiToken = false, want true") + } + + c.MustPost(`{ apiTokens { id revoked } }`, &list) + if len(list.APITokens) != 1 || !list.APITokens[0].Revoked { + t.Errorf("after revoke = %+v, want revoked=true", list.APITokens) + } +} diff --git a/internal/graph/executions.resolvers.go b/internal/graph/executions.resolvers.go new file mode 100644 index 0000000..bb97be9 --- /dev/null +++ b/internal/graph/executions.resolvers.go @@ -0,0 +1,126 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver +// implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.90 + +import ( + "context" + "errors" + + "github.com/dimiro1/lunar/internal/graph/model" + "github.com/dimiro1/lunar/internal/store" +) + +// Execution is the resolver for the execution field — the reverse edge from an +// AI request back to the execution it was made during (null if deleted). +func (r *aIRequestResolver) Execution(ctx context.Context, obj *store.AIRequest) (*store.Execution, error) { + return r.loadExecution(ctx, obj.ExecutionID) +} + +// Execution is the resolver for the execution field — the reverse edge from an +// email request back to the execution it was made during (null if deleted). +func (r *emailRequestResolver) Execution(ctx context.Context, obj *store.EmailRequest) (*store.Execution, error) { + return r.loadExecution(ctx, obj.ExecutionID) +} + +// Function is the resolver for the function field. It loads the execution's +// parent function so a single query can fetch both; a deleted function resolves +// to null. +func (r *executionResolver) Function(ctx context.Context, obj *store.Execution) (*store.FunctionWithActiveVersion, error) { + return r.loadFunction(ctx, obj.FunctionID) +} + +// Version is the resolver for the version field — the specific function version +// that produced this execution (null if that version was deleted). +func (r *executionResolver) Version(ctx context.Context, obj *store.Execution) (*store.FunctionVersion, error) { + return r.loadVersionByID(ctx, obj.FunctionVersionID) +} + +// Logs is the resolver for the logs field. obj is already the execution, so no +// existence check is needed before reading its logs. +func (r *executionResolver) Logs(ctx context.Context, obj *store.Execution, limit *int, offset *int) (*model.LogEntryConnection, error) { + return r.logEntryConnection(obj.ID, limit, offset), nil +} + +// AiRequests is the resolver for the aiRequests field. +func (r *executionResolver) AiRequests(ctx context.Context, obj *store.Execution, limit *int, offset *int) (*model.AIRequestConnection, error) { + return r.aiRequestConnection(obj.ID, limit, offset), nil +} + +// EmailRequests is the resolver for the emailRequests field. +func (r *executionResolver) EmailRequests(ctx context.Context, obj *store.Execution, limit *int, offset *int) (*model.EmailRequestConnection, error) { + return r.emailRequestConnection(obj.ID, limit, offset), nil +} + +// Executions is the resolver for the executions field. +func (r *queryResolver) Executions(ctx context.Context, functionID string, limit *int, offset *int) (*model.ExecutionConnection, error) { + params := paginationParams(limit, offset) + executions, total, err := r.DB.ListExecutions(ctx, functionID, params) + if err != nil { + return nil, err + } + return &model.ExecutionConnection{Nodes: executions, PageInfo: pageInfo(total, params)}, nil +} + +// Execution is the resolver for the execution field. +func (r *queryResolver) Execution(ctx context.Context, id string) (*store.Execution, error) { + exec, err := r.DB.GetExecution(ctx, id) + if err != nil { + // A missing execution is a null result in GraphQL, not an error. + if errors.Is(err, store.ErrExecutionNotFound) { + return nil, nil + } + return nil, err + } + return &exec, nil +} + +// ExecutionLogs is the resolver for the executionLogs field. It validates the +// execution exists (a 404 for an unknown id) then returns its logs. +func (r *queryResolver) ExecutionLogs(ctx context.Context, executionID string, limit *int, offset *int) (*model.LogEntryConnection, error) { + if _, err := r.DB.GetExecution(ctx, executionID); err != nil { + return nil, err + } + return r.logEntryConnection(executionID, limit, offset), nil +} + +// ExecutionAiRequests is the resolver for the executionAiRequests field. +func (r *queryResolver) ExecutionAiRequests(ctx context.Context, executionID string, limit *int, offset *int) (*model.AIRequestConnection, error) { + if _, err := r.DB.GetExecution(ctx, executionID); err != nil { + return nil, err + } + return r.aiRequestConnection(executionID, limit, offset), nil +} + +// ExecutionEmailRequests is the resolver for the executionEmailRequests field. +func (r *queryResolver) ExecutionEmailRequests(ctx context.Context, executionID string, limit *int, offset *int) (*model.EmailRequestConnection, error) { + if _, err := r.DB.GetExecution(ctx, executionID); err != nil { + return nil, err + } + return r.emailRequestConnection(executionID, limit, offset), nil +} + +// NextRun is the resolver for the nextRun field. It mirrors the scheduling logic +// of the REST next-run endpoint. +func (r *queryResolver) NextRun(ctx context.Context, functionID string) (*model.NextRun, error) { + fn, err := r.DB.GetFunction(ctx, functionID) + if err != nil { + return nil, err + } + return computeNextRun(fn) +} + +// AIRequest returns AIRequestResolver implementation. +func (r *Resolver) AIRequest() AIRequestResolver { return &aIRequestResolver{r} } + +// EmailRequest returns EmailRequestResolver implementation. +func (r *Resolver) EmailRequest() EmailRequestResolver { return &emailRequestResolver{r} } + +// Execution returns ExecutionResolver implementation. +func (r *Resolver) Execution() ExecutionResolver { return &executionResolver{r} } + +type aIRequestResolver struct{ *Resolver } +type emailRequestResolver struct{ *Resolver } +type executionResolver struct{ *Resolver } diff --git a/internal/graph/functions.resolvers.go b/internal/graph/functions.resolvers.go new file mode 100644 index 0000000..9661c88 --- /dev/null +++ b/internal/graph/functions.resolvers.go @@ -0,0 +1,243 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver +// implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.90 + +import ( + "context" + "log/slog" + + "github.com/dimiro1/lunar/internal/graph/model" + "github.com/dimiro1/lunar/internal/store" + "github.com/dimiro1/lunar/internal/validation" + "github.com/rs/xid" +) + +// CronStatus is the resolver for the cronStatus field. It coerces the store's +// *string cron status into the CronStatus enum (empty/absent → null). +func (r *functionResolver) CronStatus(ctx context.Context, obj *store.FunctionWithActiveVersion) (*store.CronStatus, error) { + return cronStatusEnum(obj.CronStatus), nil +} + +// Versions is the resolver for the versions field. It lazily lists the +// function's versions, mirroring the top-level versions query, so only queries +// that select this field read the version store. +func (r *functionResolver) Versions(ctx context.Context, obj *store.FunctionWithActiveVersion, limit *int, offset *int) (*model.FunctionVersionConnection, error) { + params := paginationParams(limit, offset) + versions, total, err := r.DB.ListVersions(ctx, obj.ID, params) + if err != nil { + return nil, err + } + return &model.FunctionVersionConnection{Nodes: versions, PageInfo: pageInfo(total, params)}, nil +} + +// Executions is the resolver for the executions field. It lazily lists the +// function's executions, mirroring the top-level executions query. +func (r *functionResolver) Executions(ctx context.Context, obj *store.FunctionWithActiveVersion, limit *int, offset *int) (*model.ExecutionConnection, error) { + return r.executionConnection(ctx, obj.ID, limit, offset) +} + +// NextRun is the resolver for the nextRun field. It derives the next run from +// the function's own cron settings (no extra fetch — obj already has them). +func (r *functionResolver) NextRun(ctx context.Context, obj *store.FunctionWithActiveVersion) (*model.NextRun, error) { + return computeNextRun(obj.Function) +} + +// EnvVars is the resolver for the envVars field. It reads the env store lazily, +// so only queries that select envVars incur the lookup. +func (r *functionResolver) EnvVars(ctx context.Context, obj *store.FunctionWithActiveVersion) (model.StringMap, error) { + vars, err := r.EnvStore.All(obj.ID) + if err != nil { + return nil, err + } + return model.StringMap(vars), nil +} + +// ScopedData is the resolver for the scopedData field. Function-scoped KV entries +// are read lazily from the KV store. +func (r *functionResolver) ScopedData(ctx context.Context, obj *store.FunctionWithActiveVersion) (model.StringMap, error) { + data, err := r.KVStore.All(obj.ID) + if err != nil { + return nil, err + } + return model.StringMap(data), nil +} + +// GlobalData is the resolver for the globalData field. Global KV entries are read +// lazily from the KV store. +func (r *functionResolver) GlobalData(ctx context.Context, obj *store.FunctionWithActiveVersion) (model.StringMap, error) { + data, err := r.KVStore.AllGlobal() + if err != nil { + return nil, err + } + return model.StringMap(data), nil +} + +// CreateFunction is the resolver for the createFunction field. +func (r *mutationResolver) CreateFunction(ctx context.Context, input model.CreateFunctionInput) (*store.FunctionWithActiveVersion, error) { + if err := validation.CreateFunction(input.Name, input.Description, input.Code); err != nil { + return nil, err + } + + created, err := r.DB.CreateFunction(ctx, store.Function{ + ID: xid.New().String(), + Name: input.Name, + Description: input.Description, + EnvVars: map[string]string{}, + }) + if err != nil { + return nil, err + } + + if _, err := r.DB.CreateVersion(ctx, created.ID, input.Code, nil); err != nil { + return nil, err + } + + return r.reloadFunction(ctx, created.ID) +} + +// UpdateFunction is the resolver for the updateFunction field. Providing code +// creates a new active version; changing cron settings reschedules the function. +func (r *mutationResolver) UpdateFunction(ctx context.Context, id string, input model.UpdateFunctionInput) (*store.FunctionWithActiveVersion, error) { + req := store.UpdateFunctionRequest{ + Name: input.Name, + Description: input.Description, + Code: input.Code, + Disabled: input.Disabled, + RetentionDays: input.RetentionDays, + CronSchedule: input.CronSchedule, + CronStatus: cronStatusString(input.CronStatus), + SaveResponse: input.SaveResponse, + } + if err := validation.UpdateFunctionRequest(&req); err != nil { + return nil, err + } + + // Providing code creates a new (active) version. + if req.Code != nil { + if _, err := r.DB.CreateVersion(ctx, id, *req.Code, nil); err != nil { + return nil, err + } + } + + // Apply metadata changes (code is versioned separately, above). + cronChanged := req.CronSchedule != nil || req.CronStatus != nil + if req.Name != nil || req.Description != nil || req.Disabled != nil || req.RetentionDays != nil || req.CronSchedule != nil || req.CronStatus != nil || req.SaveResponse != nil { + if err := r.DB.UpdateFunction(ctx, id, req); err != nil { + return nil, err + } + } + + // Reschedule on cron changes; a refresh failure is logged, not fatal. + if cronChanged && r.Scheduler != nil { + if err := r.Scheduler.RefreshFunction(id); err != nil { + slog.Error("Failed to refresh cron schedule", "function_id", id, "error", err) + } + } + + return r.reloadFunction(ctx, id) +} + +// DeleteFunction is the resolver for the deleteFunction field. +func (r *mutationResolver) DeleteFunction(ctx context.Context, id string) (bool, error) { + if err := r.DB.DeleteFunction(ctx, id); err != nil { + return false, err + } + return true, nil +} + +// SetFunctionEnv is the resolver for the setFunctionEnv field. It replaces the +// function's environment variables with the supplied set. +func (r *mutationResolver) SetFunctionEnv(ctx context.Context, id string, env model.StringMap) (*store.FunctionWithActiveVersion, error) { + if err := validation.EnvVars(env); err != nil { + return nil, err + } + if _, err := r.DB.GetFunction(ctx, id); err != nil { + return nil, err + } + + current, err := r.EnvStore.All(id) + if err != nil { + return nil, err + } + for key := range current { + if _, ok := env[key]; !ok { + if err := r.EnvStore.Delete(id, key); err != nil { + return nil, err + } + } + } + for key, value := range env { + if err := r.EnvStore.Set(id, key, value); err != nil { + return nil, err + } + } + + return r.reloadFunction(ctx, id) +} + +// SetFunctionKv is the resolver for the setFunctionKv field. It replaces the +// function-scoped (or global) KV entries with the supplied set. +func (r *mutationResolver) SetFunctionKv(ctx context.Context, id string, kv model.StringMap, global *bool) (*store.FunctionWithActiveVersion, error) { + if err := validation.KVEntries(kv); err != nil { + return nil, err + } + if _, err := r.DB.GetFunction(ctx, id); err != nil { + return nil, err + } + + // Global entries are stored under an empty function scope. + scope := id + if global != nil && *global { + scope = "" + } + + current, err := r.KVStore.All(scope) + if err != nil { + return nil, err + } + for key := range current { + if _, ok := kv[key]; !ok { + if err := r.KVStore.Delete(scope, key); err != nil { + return nil, err + } + } + } + for key, value := range kv { + if err := r.KVStore.Set(scope, key, value); err != nil { + return nil, err + } + } + + return r.reloadFunction(ctx, id) +} + +// Functions is the resolver for the functions field. +func (r *queryResolver) Functions(ctx context.Context, limit *int, offset *int) (*model.FunctionConnection, error) { + params := paginationParams(limit, offset) + functions, total, err := r.DB.ListFunctions(ctx, params) + if err != nil { + return nil, err + } + return &model.FunctionConnection{Nodes: functions, PageInfo: pageInfo(total, params)}, nil +} + +// Function is the resolver for the function field. +func (r *queryResolver) Function(ctx context.Context, id string) (*store.FunctionWithActiveVersion, error) { + return r.loadFunction(ctx, id) +} + +// Function returns FunctionResolver implementation. +func (r *Resolver) Function() FunctionResolver { return &functionResolver{r} } + +// Mutation returns MutationResolver implementation. +func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } + +// Query returns QueryResolver implementation. +func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } + +type functionResolver struct{ *Resolver } +type mutationResolver struct{ *Resolver } +type queryResolver struct{ *Resolver } diff --git a/internal/graph/generated.go b/internal/graph/generated.go new file mode 100644 index 0000000..cbcb0d3 --- /dev/null +++ b/internal/graph/generated.go @@ -0,0 +1,10261 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package graph + +import ( + "bytes" + "context" + "embed" + "errors" + "fmt" + "math" + "strconv" + "sync/atomic" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/introspection" + "github.com/dimiro1/lunar/internal/graph/model" + "github.com/dimiro1/lunar/internal/store" + gqlparser "github.com/vektah/gqlparser/v2" + "github.com/vektah/gqlparser/v2/ast" +) + +// region ************************** generated!.gotpl ************************** + +// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. +func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { + return &executableSchema{SchemaData: cfg.Schema, Resolvers: cfg.Resolvers, Directives: cfg.Directives, ComplexityRoot: cfg.Complexity} +} + +type Config = graphql.Config[ResolverRoot, DirectiveRoot, ComplexityRoot] + +type ResolverRoot interface { + AIRequest() AIRequestResolver + EmailRequest() EmailRequestResolver + Execution() ExecutionResolver + Function() FunctionResolver + FunctionVersion() FunctionVersionResolver + Mutation() MutationResolver + Query() QueryResolver +} + +type DirectiveRoot struct { +} + +type ComplexityRoot struct { + AIRequest struct { + CreatedAt func(childComplexity int) int + DurationMs func(childComplexity int) int + Endpoint func(childComplexity int) int + ErrorMessage func(childComplexity int) int + Execution func(childComplexity int) int + ExecutionID func(childComplexity int) int + ID func(childComplexity int) int + InputTokens func(childComplexity int) int + Model func(childComplexity int) int + OutputTokens func(childComplexity int) int + Provider func(childComplexity int) int + RequestJSON func(childComplexity int) int + ResponseJSON func(childComplexity int) int + Status func(childComplexity int) int + } + + AIRequestConnection struct { + Nodes func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + APIToken struct { + CreatedAt func(childComplexity int) int + ID func(childComplexity int) int + LastUsed func(childComplexity int) int + Name func(childComplexity int) int + Revoked func(childComplexity int) int + } + + DiffLine struct { + Content func(childComplexity int) int + LineType func(childComplexity int) int + NewLine func(childComplexity int) int + OldLine func(childComplexity int) int + } + + EmailRequest struct { + CreatedAt func(childComplexity int) int + DurationMs func(childComplexity int) int + EmailID func(childComplexity int) int + ErrorMessage func(childComplexity int) int + Execution func(childComplexity int) int + ExecutionID func(childComplexity int) int + From func(childComplexity int) int + HasHTML func(childComplexity int) int + HasText func(childComplexity int) int + ID func(childComplexity int) int + RequestJSON func(childComplexity int) int + ResponseJSON func(childComplexity int) int + Status func(childComplexity int) int + Subject func(childComplexity int) int + To func(childComplexity int) int + } + + EmailRequestConnection struct { + Nodes func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + Execution struct { + AiRequests func(childComplexity int, limit *int, offset *int) int + CreatedAt func(childComplexity int) int + DurationMs func(childComplexity int) int + EmailRequests func(childComplexity int, limit *int, offset *int) int + ErrorMessage func(childComplexity int) int + EventJSON func(childComplexity int) int + Function func(childComplexity int) int + FunctionID func(childComplexity int) int + FunctionVersionID func(childComplexity int) int + ID func(childComplexity int) int + Logs func(childComplexity int, limit *int, offset *int) int + ResponseJSON func(childComplexity int) int + Status func(childComplexity int) int + Trigger func(childComplexity int) int + Version func(childComplexity int) int + } + + ExecutionConnection struct { + Nodes func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + Function struct { + ActiveVersion func(childComplexity int) int + CreatedAt func(childComplexity int) int + CronSchedule func(childComplexity int) int + CronStatus func(childComplexity int) int + Description func(childComplexity int) int + Disabled func(childComplexity int) int + EnvVars func(childComplexity int) int + Executions func(childComplexity int, limit *int, offset *int) int + GlobalData func(childComplexity int) int + ID func(childComplexity int) int + Name func(childComplexity int) int + NextRun func(childComplexity int) int + RetentionDays func(childComplexity int) int + SaveResponse func(childComplexity int) int + ScopedData func(childComplexity int) int + UpdatedAt func(childComplexity int) int + Versions func(childComplexity int, limit *int, offset *int) int + } + + FunctionConnection struct { + Nodes func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + FunctionVersion struct { + Code func(childComplexity int) int + CreatedAt func(childComplexity int) int + CreatedBy func(childComplexity int) int + Function func(childComplexity int) int + FunctionID func(childComplexity int) int + ID func(childComplexity int) int + IsActive func(childComplexity int) int + Version func(childComplexity int) int + } + + FunctionVersionConnection struct { + Nodes func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + LogEntry struct { + CreatedAt func(childComplexity int) int + Level func(childComplexity int) int + Message func(childComplexity int) int + } + + LogEntryConnection struct { + Nodes func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + Mutation struct { + ActivateVersion func(childComplexity int, functionID string, versionID string) int + CreateFunction func(childComplexity int, input model.CreateFunctionInput) int + DeleteFunction func(childComplexity int, id string) int + DeleteVersion func(childComplexity int, functionID string, versionID string) int + RevokeAPIToken func(childComplexity int, id string) int + SetFunctionEnv func(childComplexity int, id string, env model.StringMap) int + SetFunctionKv func(childComplexity int, id string, kv model.StringMap, global *bool) int + UpdateFunction func(childComplexity int, id string, input model.UpdateFunctionInput) int + } + + NextRun struct { + CronSchedule func(childComplexity int) int + CronStatus func(childComplexity int) int + HasSchedule func(childComplexity int) int + IsPaused func(childComplexity int) int + NextRun func(childComplexity int) int + NextRunHuman func(childComplexity int) int + } + + PageInfo struct { + Limit func(childComplexity int) int + Offset func(childComplexity int) int + Total func(childComplexity int) int + } + + Query struct { + APITokens func(childComplexity int) int + Execution func(childComplexity int, id string) int + ExecutionAiRequests func(childComplexity int, executionID string, limit *int, offset *int) int + ExecutionEmailRequests func(childComplexity int, executionID string, limit *int, offset *int) int + ExecutionLogs func(childComplexity int, executionID string, limit *int, offset *int) int + Executions func(childComplexity int, functionID string, limit *int, offset *int) int + Function func(childComplexity int, id string) int + Functions func(childComplexity int, limit *int, offset *int) int + NextRun func(childComplexity int, functionID string) int + Version func(childComplexity int, functionID string, version int) int + VersionDiff func(childComplexity int, functionID string, oldVersion int, newVersion int) int + Versions func(childComplexity int, functionID string, limit *int, offset *int) int + } + + VersionDiff struct { + Lines func(childComplexity int) int + NewVersion func(childComplexity int) int + OldVersion func(childComplexity int) int + } +} + +type AIRequestResolver interface { + Execution(ctx context.Context, obj *store.AIRequest) (*store.Execution, error) +} +type EmailRequestResolver interface { + Execution(ctx context.Context, obj *store.EmailRequest) (*store.Execution, error) +} +type ExecutionResolver interface { + Function(ctx context.Context, obj *store.Execution) (*store.FunctionWithActiveVersion, error) + Version(ctx context.Context, obj *store.Execution) (*store.FunctionVersion, error) + Logs(ctx context.Context, obj *store.Execution, limit *int, offset *int) (*model.LogEntryConnection, error) + AiRequests(ctx context.Context, obj *store.Execution, limit *int, offset *int) (*model.AIRequestConnection, error) + EmailRequests(ctx context.Context, obj *store.Execution, limit *int, offset *int) (*model.EmailRequestConnection, error) +} +type FunctionResolver interface { + CronStatus(ctx context.Context, obj *store.FunctionWithActiveVersion) (*store.CronStatus, error) + + Versions(ctx context.Context, obj *store.FunctionWithActiveVersion, limit *int, offset *int) (*model.FunctionVersionConnection, error) + Executions(ctx context.Context, obj *store.FunctionWithActiveVersion, limit *int, offset *int) (*model.ExecutionConnection, error) + NextRun(ctx context.Context, obj *store.FunctionWithActiveVersion) (*model.NextRun, error) + EnvVars(ctx context.Context, obj *store.FunctionWithActiveVersion) (model.StringMap, error) + ScopedData(ctx context.Context, obj *store.FunctionWithActiveVersion) (model.StringMap, error) + GlobalData(ctx context.Context, obj *store.FunctionWithActiveVersion) (model.StringMap, error) +} +type FunctionVersionResolver interface { + Function(ctx context.Context, obj *store.FunctionVersion) (*store.FunctionWithActiveVersion, error) +} +type MutationResolver interface { + CreateFunction(ctx context.Context, input model.CreateFunctionInput) (*store.FunctionWithActiveVersion, error) + UpdateFunction(ctx context.Context, id string, input model.UpdateFunctionInput) (*store.FunctionWithActiveVersion, error) + DeleteFunction(ctx context.Context, id string) (bool, error) + SetFunctionEnv(ctx context.Context, id string, env model.StringMap) (*store.FunctionWithActiveVersion, error) + SetFunctionKv(ctx context.Context, id string, kv model.StringMap, global *bool) (*store.FunctionWithActiveVersion, error) + RevokeAPIToken(ctx context.Context, id string) (bool, error) + ActivateVersion(ctx context.Context, functionID string, versionID string) (*store.FunctionWithActiveVersion, error) + DeleteVersion(ctx context.Context, functionID string, versionID string) (bool, error) +} +type QueryResolver interface { + Functions(ctx context.Context, limit *int, offset *int) (*model.FunctionConnection, error) + Function(ctx context.Context, id string) (*store.FunctionWithActiveVersion, error) + Executions(ctx context.Context, functionID string, limit *int, offset *int) (*model.ExecutionConnection, error) + Execution(ctx context.Context, id string) (*store.Execution, error) + ExecutionLogs(ctx context.Context, executionID string, limit *int, offset *int) (*model.LogEntryConnection, error) + ExecutionAiRequests(ctx context.Context, executionID string, limit *int, offset *int) (*model.AIRequestConnection, error) + ExecutionEmailRequests(ctx context.Context, executionID string, limit *int, offset *int) (*model.EmailRequestConnection, error) + NextRun(ctx context.Context, functionID string) (*model.NextRun, error) + APITokens(ctx context.Context) ([]store.APIToken, error) + Versions(ctx context.Context, functionID string, limit *int, offset *int) (*model.FunctionVersionConnection, error) + Version(ctx context.Context, functionID string, version int) (*store.FunctionVersion, error) + VersionDiff(ctx context.Context, functionID string, oldVersion int, newVersion int) (*model.VersionDiff, error) +} + +type executableSchema graphql.ExecutableSchemaState[ResolverRoot, DirectiveRoot, ComplexityRoot] + +func (e *executableSchema) Schema() *ast.Schema { + if e.SchemaData != nil { + return e.SchemaData + } + return parsedSchema +} + +func (e *executableSchema) Complexity(ctx context.Context, typeName, field string, childComplexity int, rawArgs map[string]any) (int, bool) { + ec := newExecutionContext(nil, e, nil) + _ = ec + switch typeName + "." + field { + + case "AIRequest.createdAt": + if e.ComplexityRoot.AIRequest.CreatedAt == nil { + break + } + + return e.ComplexityRoot.AIRequest.CreatedAt(childComplexity), true + case "AIRequest.durationMs": + if e.ComplexityRoot.AIRequest.DurationMs == nil { + break + } + + return e.ComplexityRoot.AIRequest.DurationMs(childComplexity), true + case "AIRequest.endpoint": + if e.ComplexityRoot.AIRequest.Endpoint == nil { + break + } + + return e.ComplexityRoot.AIRequest.Endpoint(childComplexity), true + case "AIRequest.errorMessage": + if e.ComplexityRoot.AIRequest.ErrorMessage == nil { + break + } + + return e.ComplexityRoot.AIRequest.ErrorMessage(childComplexity), true + case "AIRequest.execution": + if e.ComplexityRoot.AIRequest.Execution == nil { + break + } + + return e.ComplexityRoot.AIRequest.Execution(childComplexity), true + case "AIRequest.executionId": + if e.ComplexityRoot.AIRequest.ExecutionID == nil { + break + } + + return e.ComplexityRoot.AIRequest.ExecutionID(childComplexity), true + case "AIRequest.id": + if e.ComplexityRoot.AIRequest.ID == nil { + break + } + + return e.ComplexityRoot.AIRequest.ID(childComplexity), true + case "AIRequest.inputTokens": + if e.ComplexityRoot.AIRequest.InputTokens == nil { + break + } + + return e.ComplexityRoot.AIRequest.InputTokens(childComplexity), true + case "AIRequest.model": + if e.ComplexityRoot.AIRequest.Model == nil { + break + } + + return e.ComplexityRoot.AIRequest.Model(childComplexity), true + case "AIRequest.outputTokens": + if e.ComplexityRoot.AIRequest.OutputTokens == nil { + break + } + + return e.ComplexityRoot.AIRequest.OutputTokens(childComplexity), true + case "AIRequest.provider": + if e.ComplexityRoot.AIRequest.Provider == nil { + break + } + + return e.ComplexityRoot.AIRequest.Provider(childComplexity), true + case "AIRequest.requestJson": + if e.ComplexityRoot.AIRequest.RequestJSON == nil { + break + } + + return e.ComplexityRoot.AIRequest.RequestJSON(childComplexity), true + case "AIRequest.responseJson": + if e.ComplexityRoot.AIRequest.ResponseJSON == nil { + break + } + + return e.ComplexityRoot.AIRequest.ResponseJSON(childComplexity), true + case "AIRequest.status": + if e.ComplexityRoot.AIRequest.Status == nil { + break + } + + return e.ComplexityRoot.AIRequest.Status(childComplexity), true + + case "AIRequestConnection.nodes": + if e.ComplexityRoot.AIRequestConnection.Nodes == nil { + break + } + + return e.ComplexityRoot.AIRequestConnection.Nodes(childComplexity), true + case "AIRequestConnection.pageInfo": + if e.ComplexityRoot.AIRequestConnection.PageInfo == nil { + break + } + + return e.ComplexityRoot.AIRequestConnection.PageInfo(childComplexity), true + + case "APIToken.createdAt": + if e.ComplexityRoot.APIToken.CreatedAt == nil { + break + } + + return e.ComplexityRoot.APIToken.CreatedAt(childComplexity), true + case "APIToken.id": + if e.ComplexityRoot.APIToken.ID == nil { + break + } + + return e.ComplexityRoot.APIToken.ID(childComplexity), true + case "APIToken.lastUsed": + if e.ComplexityRoot.APIToken.LastUsed == nil { + break + } + + return e.ComplexityRoot.APIToken.LastUsed(childComplexity), true + case "APIToken.name": + if e.ComplexityRoot.APIToken.Name == nil { + break + } + + return e.ComplexityRoot.APIToken.Name(childComplexity), true + case "APIToken.revoked": + if e.ComplexityRoot.APIToken.Revoked == nil { + break + } + + return e.ComplexityRoot.APIToken.Revoked(childComplexity), true + + case "DiffLine.content": + if e.ComplexityRoot.DiffLine.Content == nil { + break + } + + return e.ComplexityRoot.DiffLine.Content(childComplexity), true + case "DiffLine.lineType": + if e.ComplexityRoot.DiffLine.LineType == nil { + break + } + + return e.ComplexityRoot.DiffLine.LineType(childComplexity), true + case "DiffLine.newLine": + if e.ComplexityRoot.DiffLine.NewLine == nil { + break + } + + return e.ComplexityRoot.DiffLine.NewLine(childComplexity), true + case "DiffLine.oldLine": + if e.ComplexityRoot.DiffLine.OldLine == nil { + break + } + + return e.ComplexityRoot.DiffLine.OldLine(childComplexity), true + + case "EmailRequest.createdAt": + if e.ComplexityRoot.EmailRequest.CreatedAt == nil { + break + } + + return e.ComplexityRoot.EmailRequest.CreatedAt(childComplexity), true + case "EmailRequest.durationMs": + if e.ComplexityRoot.EmailRequest.DurationMs == nil { + break + } + + return e.ComplexityRoot.EmailRequest.DurationMs(childComplexity), true + case "EmailRequest.emailId": + if e.ComplexityRoot.EmailRequest.EmailID == nil { + break + } + + return e.ComplexityRoot.EmailRequest.EmailID(childComplexity), true + case "EmailRequest.errorMessage": + if e.ComplexityRoot.EmailRequest.ErrorMessage == nil { + break + } + + return e.ComplexityRoot.EmailRequest.ErrorMessage(childComplexity), true + case "EmailRequest.execution": + if e.ComplexityRoot.EmailRequest.Execution == nil { + break + } + + return e.ComplexityRoot.EmailRequest.Execution(childComplexity), true + case "EmailRequest.executionId": + if e.ComplexityRoot.EmailRequest.ExecutionID == nil { + break + } + + return e.ComplexityRoot.EmailRequest.ExecutionID(childComplexity), true + case "EmailRequest.from": + if e.ComplexityRoot.EmailRequest.From == nil { + break + } + + return e.ComplexityRoot.EmailRequest.From(childComplexity), true + case "EmailRequest.hasHtml": + if e.ComplexityRoot.EmailRequest.HasHTML == nil { + break + } + + return e.ComplexityRoot.EmailRequest.HasHTML(childComplexity), true + case "EmailRequest.hasText": + if e.ComplexityRoot.EmailRequest.HasText == nil { + break + } + + return e.ComplexityRoot.EmailRequest.HasText(childComplexity), true + case "EmailRequest.id": + if e.ComplexityRoot.EmailRequest.ID == nil { + break + } + + return e.ComplexityRoot.EmailRequest.ID(childComplexity), true + case "EmailRequest.requestJson": + if e.ComplexityRoot.EmailRequest.RequestJSON == nil { + break + } + + return e.ComplexityRoot.EmailRequest.RequestJSON(childComplexity), true + case "EmailRequest.responseJson": + if e.ComplexityRoot.EmailRequest.ResponseJSON == nil { + break + } + + return e.ComplexityRoot.EmailRequest.ResponseJSON(childComplexity), true + case "EmailRequest.status": + if e.ComplexityRoot.EmailRequest.Status == nil { + break + } + + return e.ComplexityRoot.EmailRequest.Status(childComplexity), true + case "EmailRequest.subject": + if e.ComplexityRoot.EmailRequest.Subject == nil { + break + } + + return e.ComplexityRoot.EmailRequest.Subject(childComplexity), true + case "EmailRequest.to": + if e.ComplexityRoot.EmailRequest.To == nil { + break + } + + return e.ComplexityRoot.EmailRequest.To(childComplexity), true + + case "EmailRequestConnection.nodes": + if e.ComplexityRoot.EmailRequestConnection.Nodes == nil { + break + } + + return e.ComplexityRoot.EmailRequestConnection.Nodes(childComplexity), true + case "EmailRequestConnection.pageInfo": + if e.ComplexityRoot.EmailRequestConnection.PageInfo == nil { + break + } + + return e.ComplexityRoot.EmailRequestConnection.PageInfo(childComplexity), true + + case "Execution.aiRequests": + if e.ComplexityRoot.Execution.AiRequests == nil { + break + } + + args, err := ec.field_Execution_aiRequests_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Execution.AiRequests(childComplexity, args["limit"].(*int), args["offset"].(*int)), true + case "Execution.createdAt": + if e.ComplexityRoot.Execution.CreatedAt == nil { + break + } + + return e.ComplexityRoot.Execution.CreatedAt(childComplexity), true + case "Execution.durationMs": + if e.ComplexityRoot.Execution.DurationMs == nil { + break + } + + return e.ComplexityRoot.Execution.DurationMs(childComplexity), true + case "Execution.emailRequests": + if e.ComplexityRoot.Execution.EmailRequests == nil { + break + } + + args, err := ec.field_Execution_emailRequests_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Execution.EmailRequests(childComplexity, args["limit"].(*int), args["offset"].(*int)), true + case "Execution.errorMessage": + if e.ComplexityRoot.Execution.ErrorMessage == nil { + break + } + + return e.ComplexityRoot.Execution.ErrorMessage(childComplexity), true + case "Execution.eventJson": + if e.ComplexityRoot.Execution.EventJSON == nil { + break + } + + return e.ComplexityRoot.Execution.EventJSON(childComplexity), true + case "Execution.function": + if e.ComplexityRoot.Execution.Function == nil { + break + } + + return e.ComplexityRoot.Execution.Function(childComplexity), true + case "Execution.functionId": + if e.ComplexityRoot.Execution.FunctionID == nil { + break + } + + return e.ComplexityRoot.Execution.FunctionID(childComplexity), true + case "Execution.functionVersionId": + if e.ComplexityRoot.Execution.FunctionVersionID == nil { + break + } + + return e.ComplexityRoot.Execution.FunctionVersionID(childComplexity), true + case "Execution.id": + if e.ComplexityRoot.Execution.ID == nil { + break + } + + return e.ComplexityRoot.Execution.ID(childComplexity), true + case "Execution.logs": + if e.ComplexityRoot.Execution.Logs == nil { + break + } + + args, err := ec.field_Execution_logs_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Execution.Logs(childComplexity, args["limit"].(*int), args["offset"].(*int)), true + case "Execution.responseJson": + if e.ComplexityRoot.Execution.ResponseJSON == nil { + break + } + + return e.ComplexityRoot.Execution.ResponseJSON(childComplexity), true + case "Execution.status": + if e.ComplexityRoot.Execution.Status == nil { + break + } + + return e.ComplexityRoot.Execution.Status(childComplexity), true + case "Execution.trigger": + if e.ComplexityRoot.Execution.Trigger == nil { + break + } + + return e.ComplexityRoot.Execution.Trigger(childComplexity), true + case "Execution.version": + if e.ComplexityRoot.Execution.Version == nil { + break + } + + return e.ComplexityRoot.Execution.Version(childComplexity), true + + case "ExecutionConnection.nodes": + if e.ComplexityRoot.ExecutionConnection.Nodes == nil { + break + } + + return e.ComplexityRoot.ExecutionConnection.Nodes(childComplexity), true + case "ExecutionConnection.pageInfo": + if e.ComplexityRoot.ExecutionConnection.PageInfo == nil { + break + } + + return e.ComplexityRoot.ExecutionConnection.PageInfo(childComplexity), true + + case "Function.activeVersion": + if e.ComplexityRoot.Function.ActiveVersion == nil { + break + } + + return e.ComplexityRoot.Function.ActiveVersion(childComplexity), true + case "Function.createdAt": + if e.ComplexityRoot.Function.CreatedAt == nil { + break + } + + return e.ComplexityRoot.Function.CreatedAt(childComplexity), true + case "Function.cronSchedule": + if e.ComplexityRoot.Function.CronSchedule == nil { + break + } + + return e.ComplexityRoot.Function.CronSchedule(childComplexity), true + case "Function.cronStatus": + if e.ComplexityRoot.Function.CronStatus == nil { + break + } + + return e.ComplexityRoot.Function.CronStatus(childComplexity), true + case "Function.description": + if e.ComplexityRoot.Function.Description == nil { + break + } + + return e.ComplexityRoot.Function.Description(childComplexity), true + case "Function.disabled": + if e.ComplexityRoot.Function.Disabled == nil { + break + } + + return e.ComplexityRoot.Function.Disabled(childComplexity), true + case "Function.envVars": + if e.ComplexityRoot.Function.EnvVars == nil { + break + } + + return e.ComplexityRoot.Function.EnvVars(childComplexity), true + case "Function.executions": + if e.ComplexityRoot.Function.Executions == nil { + break + } + + args, err := ec.field_Function_executions_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Function.Executions(childComplexity, args["limit"].(*int), args["offset"].(*int)), true + case "Function.globalData": + if e.ComplexityRoot.Function.GlobalData == nil { + break + } + + return e.ComplexityRoot.Function.GlobalData(childComplexity), true + case "Function.id": + if e.ComplexityRoot.Function.ID == nil { + break + } + + return e.ComplexityRoot.Function.ID(childComplexity), true + case "Function.name": + if e.ComplexityRoot.Function.Name == nil { + break + } + + return e.ComplexityRoot.Function.Name(childComplexity), true + case "Function.nextRun": + if e.ComplexityRoot.Function.NextRun == nil { + break + } + + return e.ComplexityRoot.Function.NextRun(childComplexity), true + case "Function.retentionDays": + if e.ComplexityRoot.Function.RetentionDays == nil { + break + } + + return e.ComplexityRoot.Function.RetentionDays(childComplexity), true + case "Function.saveResponse": + if e.ComplexityRoot.Function.SaveResponse == nil { + break + } + + return e.ComplexityRoot.Function.SaveResponse(childComplexity), true + case "Function.scopedData": + if e.ComplexityRoot.Function.ScopedData == nil { + break + } + + return e.ComplexityRoot.Function.ScopedData(childComplexity), true + case "Function.updatedAt": + if e.ComplexityRoot.Function.UpdatedAt == nil { + break + } + + return e.ComplexityRoot.Function.UpdatedAt(childComplexity), true + case "Function.versions": + if e.ComplexityRoot.Function.Versions == nil { + break + } + + args, err := ec.field_Function_versions_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Function.Versions(childComplexity, args["limit"].(*int), args["offset"].(*int)), true + + case "FunctionConnection.nodes": + if e.ComplexityRoot.FunctionConnection.Nodes == nil { + break + } + + return e.ComplexityRoot.FunctionConnection.Nodes(childComplexity), true + case "FunctionConnection.pageInfo": + if e.ComplexityRoot.FunctionConnection.PageInfo == nil { + break + } + + return e.ComplexityRoot.FunctionConnection.PageInfo(childComplexity), true + + case "FunctionVersion.code": + if e.ComplexityRoot.FunctionVersion.Code == nil { + break + } + + return e.ComplexityRoot.FunctionVersion.Code(childComplexity), true + case "FunctionVersion.createdAt": + if e.ComplexityRoot.FunctionVersion.CreatedAt == nil { + break + } + + return e.ComplexityRoot.FunctionVersion.CreatedAt(childComplexity), true + case "FunctionVersion.createdBy": + if e.ComplexityRoot.FunctionVersion.CreatedBy == nil { + break + } + + return e.ComplexityRoot.FunctionVersion.CreatedBy(childComplexity), true + case "FunctionVersion.function": + if e.ComplexityRoot.FunctionVersion.Function == nil { + break + } + + return e.ComplexityRoot.FunctionVersion.Function(childComplexity), true + case "FunctionVersion.functionId": + if e.ComplexityRoot.FunctionVersion.FunctionID == nil { + break + } + + return e.ComplexityRoot.FunctionVersion.FunctionID(childComplexity), true + case "FunctionVersion.id": + if e.ComplexityRoot.FunctionVersion.ID == nil { + break + } + + return e.ComplexityRoot.FunctionVersion.ID(childComplexity), true + case "FunctionVersion.isActive": + if e.ComplexityRoot.FunctionVersion.IsActive == nil { + break + } + + return e.ComplexityRoot.FunctionVersion.IsActive(childComplexity), true + case "FunctionVersion.version": + if e.ComplexityRoot.FunctionVersion.Version == nil { + break + } + + return e.ComplexityRoot.FunctionVersion.Version(childComplexity), true + + case "FunctionVersionConnection.nodes": + if e.ComplexityRoot.FunctionVersionConnection.Nodes == nil { + break + } + + return e.ComplexityRoot.FunctionVersionConnection.Nodes(childComplexity), true + case "FunctionVersionConnection.pageInfo": + if e.ComplexityRoot.FunctionVersionConnection.PageInfo == nil { + break + } + + return e.ComplexityRoot.FunctionVersionConnection.PageInfo(childComplexity), true + + case "LogEntry.createdAt": + if e.ComplexityRoot.LogEntry.CreatedAt == nil { + break + } + + return e.ComplexityRoot.LogEntry.CreatedAt(childComplexity), true + case "LogEntry.level": + if e.ComplexityRoot.LogEntry.Level == nil { + break + } + + return e.ComplexityRoot.LogEntry.Level(childComplexity), true + case "LogEntry.message": + if e.ComplexityRoot.LogEntry.Message == nil { + break + } + + return e.ComplexityRoot.LogEntry.Message(childComplexity), true + + case "LogEntryConnection.nodes": + if e.ComplexityRoot.LogEntryConnection.Nodes == nil { + break + } + + return e.ComplexityRoot.LogEntryConnection.Nodes(childComplexity), true + case "LogEntryConnection.pageInfo": + if e.ComplexityRoot.LogEntryConnection.PageInfo == nil { + break + } + + return e.ComplexityRoot.LogEntryConnection.PageInfo(childComplexity), true + + case "Mutation.activateVersion": + if e.ComplexityRoot.Mutation.ActivateVersion == nil { + break + } + + args, err := ec.field_Mutation_activateVersion_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.ActivateVersion(childComplexity, args["functionId"].(string), args["versionId"].(string)), true + case "Mutation.createFunction": + if e.ComplexityRoot.Mutation.CreateFunction == nil { + break + } + + args, err := ec.field_Mutation_createFunction_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.CreateFunction(childComplexity, args["input"].(model.CreateFunctionInput)), true + case "Mutation.deleteFunction": + if e.ComplexityRoot.Mutation.DeleteFunction == nil { + break + } + + args, err := ec.field_Mutation_deleteFunction_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.DeleteFunction(childComplexity, args["id"].(string)), true + case "Mutation.deleteVersion": + if e.ComplexityRoot.Mutation.DeleteVersion == nil { + break + } + + args, err := ec.field_Mutation_deleteVersion_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.DeleteVersion(childComplexity, args["functionId"].(string), args["versionId"].(string)), true + case "Mutation.revokeApiToken": + if e.ComplexityRoot.Mutation.RevokeAPIToken == nil { + break + } + + args, err := ec.field_Mutation_revokeApiToken_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.RevokeAPIToken(childComplexity, args["id"].(string)), true + case "Mutation.setFunctionEnv": + if e.ComplexityRoot.Mutation.SetFunctionEnv == nil { + break + } + + args, err := ec.field_Mutation_setFunctionEnv_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.SetFunctionEnv(childComplexity, args["id"].(string), args["env"].(model.StringMap)), true + case "Mutation.setFunctionKv": + if e.ComplexityRoot.Mutation.SetFunctionKv == nil { + break + } + + args, err := ec.field_Mutation_setFunctionKv_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.SetFunctionKv(childComplexity, args["id"].(string), args["kv"].(model.StringMap), args["global"].(*bool)), true + case "Mutation.updateFunction": + if e.ComplexityRoot.Mutation.UpdateFunction == nil { + break + } + + args, err := ec.field_Mutation_updateFunction_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Mutation.UpdateFunction(childComplexity, args["id"].(string), args["input"].(model.UpdateFunctionInput)), true + + case "NextRun.cronSchedule": + if e.ComplexityRoot.NextRun.CronSchedule == nil { + break + } + + return e.ComplexityRoot.NextRun.CronSchedule(childComplexity), true + case "NextRun.cronStatus": + if e.ComplexityRoot.NextRun.CronStatus == nil { + break + } + + return e.ComplexityRoot.NextRun.CronStatus(childComplexity), true + case "NextRun.hasSchedule": + if e.ComplexityRoot.NextRun.HasSchedule == nil { + break + } + + return e.ComplexityRoot.NextRun.HasSchedule(childComplexity), true + case "NextRun.isPaused": + if e.ComplexityRoot.NextRun.IsPaused == nil { + break + } + + return e.ComplexityRoot.NextRun.IsPaused(childComplexity), true + case "NextRun.nextRun": + if e.ComplexityRoot.NextRun.NextRun == nil { + break + } + + return e.ComplexityRoot.NextRun.NextRun(childComplexity), true + case "NextRun.nextRunHuman": + if e.ComplexityRoot.NextRun.NextRunHuman == nil { + break + } + + return e.ComplexityRoot.NextRun.NextRunHuman(childComplexity), true + + case "PageInfo.limit": + if e.ComplexityRoot.PageInfo.Limit == nil { + break + } + + return e.ComplexityRoot.PageInfo.Limit(childComplexity), true + case "PageInfo.offset": + if e.ComplexityRoot.PageInfo.Offset == nil { + break + } + + return e.ComplexityRoot.PageInfo.Offset(childComplexity), true + case "PageInfo.total": + if e.ComplexityRoot.PageInfo.Total == nil { + break + } + + return e.ComplexityRoot.PageInfo.Total(childComplexity), true + + case "Query.apiTokens": + if e.ComplexityRoot.Query.APITokens == nil { + break + } + + return e.ComplexityRoot.Query.APITokens(childComplexity), true + case "Query.execution": + if e.ComplexityRoot.Query.Execution == nil { + break + } + + args, err := ec.field_Query_execution_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.Execution(childComplexity, args["id"].(string)), true + case "Query.executionAiRequests": + if e.ComplexityRoot.Query.ExecutionAiRequests == nil { + break + } + + args, err := ec.field_Query_executionAiRequests_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.ExecutionAiRequests(childComplexity, args["executionId"].(string), args["limit"].(*int), args["offset"].(*int)), true + case "Query.executionEmailRequests": + if e.ComplexityRoot.Query.ExecutionEmailRequests == nil { + break + } + + args, err := ec.field_Query_executionEmailRequests_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.ExecutionEmailRequests(childComplexity, args["executionId"].(string), args["limit"].(*int), args["offset"].(*int)), true + case "Query.executionLogs": + if e.ComplexityRoot.Query.ExecutionLogs == nil { + break + } + + args, err := ec.field_Query_executionLogs_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.ExecutionLogs(childComplexity, args["executionId"].(string), args["limit"].(*int), args["offset"].(*int)), true + case "Query.executions": + if e.ComplexityRoot.Query.Executions == nil { + break + } + + args, err := ec.field_Query_executions_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.Executions(childComplexity, args["functionId"].(string), args["limit"].(*int), args["offset"].(*int)), true + case "Query.function": + if e.ComplexityRoot.Query.Function == nil { + break + } + + args, err := ec.field_Query_function_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.Function(childComplexity, args["id"].(string)), true + case "Query.functions": + if e.ComplexityRoot.Query.Functions == nil { + break + } + + args, err := ec.field_Query_functions_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.Functions(childComplexity, args["limit"].(*int), args["offset"].(*int)), true + + case "Query.nextRun": + if e.ComplexityRoot.Query.NextRun == nil { + break + } + + args, err := ec.field_Query_nextRun_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.NextRun(childComplexity, args["functionId"].(string)), true + case "Query.version": + if e.ComplexityRoot.Query.Version == nil { + break + } + + args, err := ec.field_Query_version_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.Version(childComplexity, args["functionId"].(string), args["version"].(int)), true + case "Query.versionDiff": + if e.ComplexityRoot.Query.VersionDiff == nil { + break + } + + args, err := ec.field_Query_versionDiff_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.VersionDiff(childComplexity, args["functionId"].(string), args["oldVersion"].(int), args["newVersion"].(int)), true + case "Query.versions": + if e.ComplexityRoot.Query.Versions == nil { + break + } + + args, err := ec.field_Query_versions_args(ctx, rawArgs) + if err != nil { + return 0, false + } + + return e.ComplexityRoot.Query.Versions(childComplexity, args["functionId"].(string), args["limit"].(*int), args["offset"].(*int)), true + + case "VersionDiff.lines": + if e.ComplexityRoot.VersionDiff.Lines == nil { + break + } + + return e.ComplexityRoot.VersionDiff.Lines(childComplexity), true + case "VersionDiff.newVersion": + if e.ComplexityRoot.VersionDiff.NewVersion == nil { + break + } + + return e.ComplexityRoot.VersionDiff.NewVersion(childComplexity), true + case "VersionDiff.oldVersion": + if e.ComplexityRoot.VersionDiff.OldVersion == nil { + break + } + + return e.ComplexityRoot.VersionDiff.OldVersion(childComplexity), true + + } + return 0, false +} + +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + opCtx := graphql.GetOperationContext(ctx) + ec := newExecutionContext(opCtx, e, make(chan graphql.DeferredResult)) + inputUnmarshalMap := graphql.BuildUnmarshalerMap( + ec.unmarshalInputCreateFunctionInput, + ec.unmarshalInputUpdateFunctionInput, + ) + first := true + + switch opCtx.Operation.Operation { + case ast.Query: + return func(ctx context.Context) *graphql.Response { + var response graphql.Response + var data graphql.Marshaler + if first { + first = false + ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) + data = ec._Query(ctx, opCtx.Operation.SelectionSet) + } else { + if atomic.LoadInt32(&ec.PendingDeferred) > 0 { + result := <-ec.DeferredResults + atomic.AddInt32(&ec.PendingDeferred, -1) + data = result.Result + response.Path = result.Path + response.Label = result.Label + response.Errors = result.Errors + } else { + return nil + } + } + var buf bytes.Buffer + data.MarshalGQL(&buf) + response.Data = buf.Bytes() + if atomic.LoadInt32(&ec.Deferred) > 0 { + hasNext := atomic.LoadInt32(&ec.PendingDeferred) > 0 + response.HasNext = &hasNext + } + + return &response + } + case ast.Mutation: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) + data := ec._Mutation(ctx, opCtx.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + + default: + return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) + } +} + +type executionContext struct { + *graphql.ExecutionContextState[ResolverRoot, DirectiveRoot, ComplexityRoot] +} + +func newExecutionContext( + opCtx *graphql.OperationContext, + execSchema *executableSchema, + deferredResults chan graphql.DeferredResult, +) *executionContext { + return &executionContext{ + ExecutionContextState: graphql.NewExecutionContextState[ResolverRoot, DirectiveRoot, ComplexityRoot]( + opCtx, + (*graphql.ExecutableSchemaState[ResolverRoot, DirectiveRoot, ComplexityRoot])(execSchema), + parsedSchema, + deferredResults, + ), + } +} + +//go:embed "schema/common.graphqls" "schema/executions.graphqls" "schema/functions.graphqls" "schema/tokens.graphqls" "schema/versions.graphqls" +var sourcesFS embed.FS + +func sourceData(filename string) string { + data, err := sourcesFS.ReadFile(filename) + if err != nil { + panic(fmt.Sprintf("codegen problem: %s not available", filename)) + } + return string(data) +} + +var sources = []*ast.Source{ + {Name: "schema/common.graphqls", Input: sourceData("schema/common.graphqls"), BuiltIn: false}, + {Name: "schema/executions.graphqls", Input: sourceData("schema/executions.graphqls"), BuiltIn: false}, + {Name: "schema/functions.graphqls", Input: sourceData("schema/functions.graphqls"), BuiltIn: false}, + {Name: "schema/tokens.graphqls", Input: sourceData("schema/tokens.graphqls"), BuiltIn: false}, + {Name: "schema/versions.graphqls", Input: sourceData("schema/versions.graphqls"), BuiltIn: false}, +} +var parsedSchema = gqlparser.MustLoadSchema(sources...) + +// childFields_* functions provide shared child field context lookups. +// Each function is generated once per unique object type, deduplicating the +// switch statements that were previously inlined in every fieldContext_* function. + +func (ec *executionContext) childFields_AIRequest(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_AIRequest_id(ctx, field) + case "executionId": + return ec.fieldContext_AIRequest_executionId(ctx, field) + case "provider": + return ec.fieldContext_AIRequest_provider(ctx, field) + case "model": + return ec.fieldContext_AIRequest_model(ctx, field) + case "endpoint": + return ec.fieldContext_AIRequest_endpoint(ctx, field) + case "requestJson": + return ec.fieldContext_AIRequest_requestJson(ctx, field) + case "responseJson": + return ec.fieldContext_AIRequest_responseJson(ctx, field) + case "status": + return ec.fieldContext_AIRequest_status(ctx, field) + case "errorMessage": + return ec.fieldContext_AIRequest_errorMessage(ctx, field) + case "inputTokens": + return ec.fieldContext_AIRequest_inputTokens(ctx, field) + case "outputTokens": + return ec.fieldContext_AIRequest_outputTokens(ctx, field) + case "durationMs": + return ec.fieldContext_AIRequest_durationMs(ctx, field) + case "createdAt": + return ec.fieldContext_AIRequest_createdAt(ctx, field) + case "execution": + return ec.fieldContext_AIRequest_execution(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type AIRequest", field.Name) +} + +func (ec *executionContext) childFields_AIRequestConnection(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "nodes": + return ec.fieldContext_AIRequestConnection_nodes(ctx, field) + case "pageInfo": + return ec.fieldContext_AIRequestConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type AIRequestConnection", field.Name) +} + +func (ec *executionContext) childFields_APIToken(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_APIToken_id(ctx, field) + case "name": + return ec.fieldContext_APIToken_name(ctx, field) + case "createdAt": + return ec.fieldContext_APIToken_createdAt(ctx, field) + case "lastUsed": + return ec.fieldContext_APIToken_lastUsed(ctx, field) + case "revoked": + return ec.fieldContext_APIToken_revoked(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type APIToken", field.Name) +} + +func (ec *executionContext) childFields_DiffLine(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "lineType": + return ec.fieldContext_DiffLine_lineType(ctx, field) + case "oldLine": + return ec.fieldContext_DiffLine_oldLine(ctx, field) + case "newLine": + return ec.fieldContext_DiffLine_newLine(ctx, field) + case "content": + return ec.fieldContext_DiffLine_content(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type DiffLine", field.Name) +} + +func (ec *executionContext) childFields_EmailRequest(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_EmailRequest_id(ctx, field) + case "executionId": + return ec.fieldContext_EmailRequest_executionId(ctx, field) + case "from": + return ec.fieldContext_EmailRequest_from(ctx, field) + case "to": + return ec.fieldContext_EmailRequest_to(ctx, field) + case "subject": + return ec.fieldContext_EmailRequest_subject(ctx, field) + case "hasText": + return ec.fieldContext_EmailRequest_hasText(ctx, field) + case "hasHtml": + return ec.fieldContext_EmailRequest_hasHtml(ctx, field) + case "requestJson": + return ec.fieldContext_EmailRequest_requestJson(ctx, field) + case "responseJson": + return ec.fieldContext_EmailRequest_responseJson(ctx, field) + case "status": + return ec.fieldContext_EmailRequest_status(ctx, field) + case "errorMessage": + return ec.fieldContext_EmailRequest_errorMessage(ctx, field) + case "emailId": + return ec.fieldContext_EmailRequest_emailId(ctx, field) + case "durationMs": + return ec.fieldContext_EmailRequest_durationMs(ctx, field) + case "createdAt": + return ec.fieldContext_EmailRequest_createdAt(ctx, field) + case "execution": + return ec.fieldContext_EmailRequest_execution(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type EmailRequest", field.Name) +} + +func (ec *executionContext) childFields_EmailRequestConnection(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "nodes": + return ec.fieldContext_EmailRequestConnection_nodes(ctx, field) + case "pageInfo": + return ec.fieldContext_EmailRequestConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type EmailRequestConnection", field.Name) +} + +func (ec *executionContext) childFields_Execution(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Execution_id(ctx, field) + case "functionId": + return ec.fieldContext_Execution_functionId(ctx, field) + case "functionVersionId": + return ec.fieldContext_Execution_functionVersionId(ctx, field) + case "status": + return ec.fieldContext_Execution_status(ctx, field) + case "durationMs": + return ec.fieldContext_Execution_durationMs(ctx, field) + case "errorMessage": + return ec.fieldContext_Execution_errorMessage(ctx, field) + case "eventJson": + return ec.fieldContext_Execution_eventJson(ctx, field) + case "responseJson": + return ec.fieldContext_Execution_responseJson(ctx, field) + case "trigger": + return ec.fieldContext_Execution_trigger(ctx, field) + case "createdAt": + return ec.fieldContext_Execution_createdAt(ctx, field) + case "function": + return ec.fieldContext_Execution_function(ctx, field) + case "version": + return ec.fieldContext_Execution_version(ctx, field) + case "logs": + return ec.fieldContext_Execution_logs(ctx, field) + case "aiRequests": + return ec.fieldContext_Execution_aiRequests(ctx, field) + case "emailRequests": + return ec.fieldContext_Execution_emailRequests(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Execution", field.Name) +} + +func (ec *executionContext) childFields_ExecutionConnection(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "nodes": + return ec.fieldContext_ExecutionConnection_nodes(ctx, field) + case "pageInfo": + return ec.fieldContext_ExecutionConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ExecutionConnection", field.Name) +} + +func (ec *executionContext) childFields_Function(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Function_id(ctx, field) + case "name": + return ec.fieldContext_Function_name(ctx, field) + case "description": + return ec.fieldContext_Function_description(ctx, field) + case "disabled": + return ec.fieldContext_Function_disabled(ctx, field) + case "retentionDays": + return ec.fieldContext_Function_retentionDays(ctx, field) + case "cronSchedule": + return ec.fieldContext_Function_cronSchedule(ctx, field) + case "cronStatus": + return ec.fieldContext_Function_cronStatus(ctx, field) + case "saveResponse": + return ec.fieldContext_Function_saveResponse(ctx, field) + case "createdAt": + return ec.fieldContext_Function_createdAt(ctx, field) + case "updatedAt": + return ec.fieldContext_Function_updatedAt(ctx, field) + case "activeVersion": + return ec.fieldContext_Function_activeVersion(ctx, field) + case "versions": + return ec.fieldContext_Function_versions(ctx, field) + case "executions": + return ec.fieldContext_Function_executions(ctx, field) + case "nextRun": + return ec.fieldContext_Function_nextRun(ctx, field) + case "envVars": + return ec.fieldContext_Function_envVars(ctx, field) + case "scopedData": + return ec.fieldContext_Function_scopedData(ctx, field) + case "globalData": + return ec.fieldContext_Function_globalData(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Function", field.Name) +} + +func (ec *executionContext) childFields_FunctionConnection(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "nodes": + return ec.fieldContext_FunctionConnection_nodes(ctx, field) + case "pageInfo": + return ec.fieldContext_FunctionConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type FunctionConnection", field.Name) +} + +func (ec *executionContext) childFields_FunctionVersion(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_FunctionVersion_id(ctx, field) + case "functionId": + return ec.fieldContext_FunctionVersion_functionId(ctx, field) + case "version": + return ec.fieldContext_FunctionVersion_version(ctx, field) + case "code": + return ec.fieldContext_FunctionVersion_code(ctx, field) + case "createdAt": + return ec.fieldContext_FunctionVersion_createdAt(ctx, field) + case "createdBy": + return ec.fieldContext_FunctionVersion_createdBy(ctx, field) + case "isActive": + return ec.fieldContext_FunctionVersion_isActive(ctx, field) + case "function": + return ec.fieldContext_FunctionVersion_function(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type FunctionVersion", field.Name) +} + +func (ec *executionContext) childFields_FunctionVersionConnection(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "nodes": + return ec.fieldContext_FunctionVersionConnection_nodes(ctx, field) + case "pageInfo": + return ec.fieldContext_FunctionVersionConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type FunctionVersionConnection", field.Name) +} + +func (ec *executionContext) childFields_LogEntry(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "level": + return ec.fieldContext_LogEntry_level(ctx, field) + case "message": + return ec.fieldContext_LogEntry_message(ctx, field) + case "createdAt": + return ec.fieldContext_LogEntry_createdAt(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type LogEntry", field.Name) +} + +func (ec *executionContext) childFields_LogEntryConnection(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "nodes": + return ec.fieldContext_LogEntryConnection_nodes(ctx, field) + case "pageInfo": + return ec.fieldContext_LogEntryConnection_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type LogEntryConnection", field.Name) +} + +func (ec *executionContext) childFields_NextRun(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "hasSchedule": + return ec.fieldContext_NextRun_hasSchedule(ctx, field) + case "cronSchedule": + return ec.fieldContext_NextRun_cronSchedule(ctx, field) + case "cronStatus": + return ec.fieldContext_NextRun_cronStatus(ctx, field) + case "isPaused": + return ec.fieldContext_NextRun_isPaused(ctx, field) + case "nextRun": + return ec.fieldContext_NextRun_nextRun(ctx, field) + case "nextRunHuman": + return ec.fieldContext_NextRun_nextRunHuman(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type NextRun", field.Name) +} + +func (ec *executionContext) childFields_PageInfo(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "total": + return ec.fieldContext_PageInfo_total(ctx, field) + case "limit": + return ec.fieldContext_PageInfo_limit(ctx, field) + case "offset": + return ec.fieldContext_PageInfo_offset(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name) +} + +func (ec *executionContext) childFields_VersionDiff(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "oldVersion": + return ec.fieldContext_VersionDiff_oldVersion(ctx, field) + case "newVersion": + return ec.fieldContext_VersionDiff_newVersion(ctx, field) + case "lines": + return ec.fieldContext_VersionDiff_lines(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type VersionDiff", field.Name) +} + +func (ec *executionContext) childFields___Directive(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___Directive_name(ctx, field) + case "description": + return ec.fieldContext___Directive_description(ctx, field) + case "isRepeatable": + return ec.fieldContext___Directive_isRepeatable(ctx, field) + case "locations": + return ec.fieldContext___Directive_locations(ctx, field) + case "args": + return ec.fieldContext___Directive_args(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Directive", field.Name) +} + +func (ec *executionContext) childFields___EnumValue(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___EnumValue_name(ctx, field) + case "description": + return ec.fieldContext___EnumValue_description(ctx, field) + case "isDeprecated": + return ec.fieldContext___EnumValue_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___EnumValue_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __EnumValue", field.Name) +} + +func (ec *executionContext) childFields___Field(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___Field_name(ctx, field) + case "description": + return ec.fieldContext___Field_description(ctx, field) + case "args": + return ec.fieldContext___Field_args(ctx, field) + case "type": + return ec.fieldContext___Field_type(ctx, field) + case "isDeprecated": + return ec.fieldContext___Field_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___Field_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Field", field.Name) +} + +func (ec *executionContext) childFields___InputValue(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + case "isDeprecated": + return ec.fieldContext___InputValue_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___InputValue_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) +} + +func (ec *executionContext) childFields___Schema(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "description": + return ec.fieldContext___Schema_description(ctx, field) + case "types": + return ec.fieldContext___Schema_types(ctx, field) + case "queryType": + return ec.fieldContext___Schema_queryType(ctx, field) + case "mutationType": + return ec.fieldContext___Schema_mutationType(ctx, field) + case "subscriptionType": + return ec.fieldContext___Schema_subscriptionType(ctx, field) + case "directives": + return ec.fieldContext___Schema_directives(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Schema", field.Name) +} + +func (ec *executionContext) childFields___Type(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "isOneOf": + return ec.fieldContext___Type_isOneOf(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) +} + +// endregion ************************** generated!.gotpl ************************** + +// region ***************************** args.gotpl ***************************** + +func (ec *executionContext) field_Execution_aiRequests_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Execution_emailRequests_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Execution_logs_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Function_executions_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Function_versions_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Mutation_activateVersion_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "functionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["functionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "versionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["versionId"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Mutation_createFunction_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "input", + func(ctx context.Context, v any) (model.CreateFunctionInput, error) { + return ec.unmarshalNCreateFunctionInput2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐCreateFunctionInput(ctx, v) + }) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_deleteFunction_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_deleteVersion_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "functionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["functionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "versionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["versionId"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Mutation_revokeApiToken_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_setFunctionEnv_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "env", + func(ctx context.Context, v any) (model.StringMap, error) { + return ec.unmarshalNMap2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐStringMap(ctx, v) + }) + if err != nil { + return nil, err + } + args["env"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Mutation_setFunctionKv_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "kv", + func(ctx context.Context, v any) (model.StringMap, error) { + return ec.unmarshalNMap2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐStringMap(ctx, v) + }) + if err != nil { + return nil, err + } + args["kv"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "global", + func(ctx context.Context, v any) (*bool, error) { + return ec.unmarshalOBoolean2ᚖbool(ctx, v) + }) + if err != nil { + return nil, err + } + args["global"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Mutation_updateFunction_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "input", + func(ctx context.Context, v any) (model.UpdateFunctionInput, error) { + return ec.unmarshalNUpdateFunctionInput2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐUpdateFunctionInput(ctx, v) + }) + if err != nil { + return nil, err + } + args["input"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "name", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNString2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["name"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_executionAiRequests_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "executionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["executionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_executionEmailRequests_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "executionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["executionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_executionLogs_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "executionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["executionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_execution_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_executions_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "functionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["functionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_function_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "id", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_functions_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Query_nextRun_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "functionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["functionId"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_versionDiff_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "functionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["functionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "oldVersion", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNInt2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["oldVersion"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "newVersion", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNInt2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["newVersion"] = arg2 + return args, nil +} + +func (ec *executionContext) field_Query_version_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "functionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["functionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "version", + func(ctx context.Context, v any) (int, error) { + return ec.unmarshalNInt2int(ctx, v) + }) + if err != nil { + return nil, err + } + args["version"] = arg1 + return args, nil +} + +func (ec *executionContext) field_Query_versions_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "functionId", + func(ctx context.Context, v any) (string, error) { + return ec.unmarshalNID2string(ctx, v) + }) + if err != nil { + return nil, err + } + args["functionId"] = arg0 + arg1, err := graphql.ProcessArgField(ctx, rawArgs, "limit", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["limit"] = arg1 + arg2, err := graphql.ProcessArgField(ctx, rawArgs, "offset", + func(ctx context.Context, v any) (*int, error) { + return ec.unmarshalOInt2ᚖint(ctx, v) + }) + if err != nil { + return nil, err + } + args["offset"] = arg2 + return args, nil +} + +func (ec *executionContext) field___Directive_args_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "includeDeprecated", + func(ctx context.Context, v any) (*bool, error) { + return ec.unmarshalOBoolean2ᚖbool(ctx, v) + }) + if err != nil { + return nil, err + } + args["includeDeprecated"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Field_args_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "includeDeprecated", + func(ctx context.Context, v any) (*bool, error) { + return ec.unmarshalOBoolean2ᚖbool(ctx, v) + }) + if err != nil { + return nil, err + } + args["includeDeprecated"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "includeDeprecated", + func(ctx context.Context, v any) (bool, error) { + return ec.unmarshalOBoolean2bool(ctx, v) + }) + if err != nil { + return nil, err + } + args["includeDeprecated"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) { + var err error + args := map[string]any{} + arg0, err := graphql.ProcessArgField(ctx, rawArgs, "includeDeprecated", + func(ctx context.Context, v any) (bool, error) { + return ec.unmarshalOBoolean2bool(ctx, v) + }) + if err != nil { + return nil, err + } + args["includeDeprecated"] = arg0 + return args, nil +} + +// endregion ***************************** args.gotpl ***************************** + +// region ************************** directives.gotpl ************************** + +// endregion ************************** directives.gotpl ************************** + +// region **************************** field.gotpl ***************************** + +func (ec *executionContext) _AIRequest_id(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _AIRequest_executionId(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_executionId(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ExecutionID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_executionId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _AIRequest_provider(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_provider(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Provider, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_provider(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _AIRequest_model(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_model(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Model, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_model(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _AIRequest_endpoint(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_endpoint(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Endpoint, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_endpoint(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _AIRequest_requestJson(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_requestJson(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.RequestJSON, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_requestJson(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _AIRequest_responseJson(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_responseJson(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ResponseJSON, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_AIRequest_responseJson(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _AIRequest_status(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_status(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Status, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v store.AIRequestStatus) graphql.Marshaler { + return ec.marshalNAIRequestStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAIRequestStatus(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type AIRequestStatus does not have child fields")) +} + +func (ec *executionContext) _AIRequest_errorMessage(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_errorMessage(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ErrorMessage, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_AIRequest_errorMessage(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _AIRequest_inputTokens(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_inputTokens(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.InputTokens, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *int) graphql.Marshaler { + return ec.marshalOInt2ᚖint(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_AIRequest_inputTokens(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _AIRequest_outputTokens(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_outputTokens(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.OutputTokens, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *int) graphql.Marshaler { + return ec.marshalOInt2ᚖint(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_AIRequest_outputTokens(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _AIRequest_durationMs(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_durationMs(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.DurationMs, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_durationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _AIRequest_createdAt(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_createdAt(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CreatedAt, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequest_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("AIRequest", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _AIRequest_execution(ctx context.Context, field graphql.CollectedField, obj *store.AIRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequest_execution(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.AIRequest().Execution(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.Execution) graphql.Marshaler { + return ec.marshalOExecution2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecution(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_AIRequest_execution(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "AIRequest", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Execution(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _AIRequestConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *model.AIRequestConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequestConnection_nodes(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Nodes, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []store.AIRequest) graphql.Marshaler { + return ec.marshalNAIRequest2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAIRequestᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequestConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "AIRequestConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_AIRequest(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _AIRequestConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.AIRequestConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_AIRequestConnection_pageInfo(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.PageInfo, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.PaginationInfo) graphql.Marshaler { + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐPaginationInfo(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_AIRequestConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "AIRequestConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_PageInfo(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _APIToken_id(ctx context.Context, field graphql.CollectedField, obj *store.APIToken) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_APIToken_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_APIToken_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("APIToken", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _APIToken_name(ctx context.Context, field graphql.CollectedField, obj *store.APIToken) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_APIToken_name(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Name, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_APIToken_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("APIToken", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _APIToken_createdAt(ctx context.Context, field graphql.CollectedField, obj *store.APIToken) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_APIToken_createdAt(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CreatedAt, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_APIToken_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("APIToken", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _APIToken_lastUsed(ctx context.Context, field graphql.CollectedField, obj *store.APIToken) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_APIToken_lastUsed(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.LastUsed, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *int64) graphql.Marshaler { + return ec.marshalOInt2ᚖint64(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_APIToken_lastUsed(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("APIToken", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _APIToken_revoked(ctx context.Context, field graphql.CollectedField, obj *store.APIToken) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_APIToken_revoked(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Revoked, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_APIToken_revoked(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("APIToken", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) _DiffLine_lineType(ctx context.Context, field graphql.CollectedField, obj *model.DiffLine) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_DiffLine_lineType(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.LineType, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v model.DiffLineType) graphql.Marshaler { + return ec.marshalNDiffLineType2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐDiffLineType(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_DiffLine_lineType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("DiffLine", field, false, false, errors.New("field of type DiffLineType does not have child fields")) +} + +func (ec *executionContext) _DiffLine_oldLine(ctx context.Context, field graphql.CollectedField, obj *model.DiffLine) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_DiffLine_oldLine(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.OldLine, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *int) graphql.Marshaler { + return ec.marshalOInt2ᚖint(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_DiffLine_oldLine(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("DiffLine", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _DiffLine_newLine(ctx context.Context, field graphql.CollectedField, obj *model.DiffLine) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_DiffLine_newLine(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.NewLine, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *int) graphql.Marshaler { + return ec.marshalOInt2ᚖint(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_DiffLine_newLine(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("DiffLine", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _DiffLine_content(ctx context.Context, field graphql.CollectedField, obj *model.DiffLine) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_DiffLine_content(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Content, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_DiffLine_content(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("DiffLine", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_id(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_executionId(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_executionId(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ExecutionID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_executionId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_from(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_from(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.From, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_from(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_to(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_to(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.To, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []string) graphql.Marshaler { + return ec.marshalNString2ᚕstringᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_to(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_subject(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_subject(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Subject, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_subject(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_hasText(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_hasText(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.HasText, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_hasText(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_hasHtml(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_hasHtml(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.HasHTML, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_hasHtml(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_requestJson(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_requestJson(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.RequestJSON, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_requestJson(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_responseJson(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_responseJson(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ResponseJSON, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_responseJson(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_status(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_status(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Status, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v store.EmailRequestStatus) graphql.Marshaler { + return ec.marshalNEmailRequestStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐEmailRequestStatus(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type EmailRequestStatus does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_errorMessage(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_errorMessage(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ErrorMessage, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_errorMessage(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_emailId(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_emailId(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.EmailID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_emailId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_durationMs(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_durationMs(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.DurationMs, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_durationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_createdAt(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_createdAt(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CreatedAt, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("EmailRequest", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _EmailRequest_execution(ctx context.Context, field graphql.CollectedField, obj *store.EmailRequest) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequest_execution(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.EmailRequest().Execution(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.Execution) graphql.Marshaler { + return ec.marshalOExecution2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecution(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_EmailRequest_execution(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "EmailRequest", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Execution(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _EmailRequestConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *model.EmailRequestConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequestConnection_nodes(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Nodes, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []store.EmailRequest) graphql.Marshaler { + return ec.marshalNEmailRequest2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐEmailRequestᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequestConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "EmailRequestConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_EmailRequest(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _EmailRequestConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.EmailRequestConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_EmailRequestConnection_pageInfo(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.PageInfo, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.PaginationInfo) graphql.Marshaler { + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐPaginationInfo(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_EmailRequestConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "EmailRequestConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_PageInfo(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Execution_id(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _Execution_functionId(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_functionId(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.FunctionID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_functionId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _Execution_functionVersionId(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_functionVersionId(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.FunctionVersionID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_functionVersionId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _Execution_status(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_status(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Status, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v store.ExecutionStatus) graphql.Marshaler { + return ec.marshalNExecutionStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecutionStatus(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_status(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type ExecutionStatus does not have child fields")) +} + +func (ec *executionContext) _Execution_durationMs(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_durationMs(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.DurationMs, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *int64) graphql.Marshaler { + return ec.marshalOInt2ᚖint64(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Execution_durationMs(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _Execution_errorMessage(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_errorMessage(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ErrorMessage, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Execution_errorMessage(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _Execution_eventJson(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_eventJson(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.EventJSON, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Execution_eventJson(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _Execution_responseJson(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_responseJson(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ResponseJSON, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Execution_responseJson(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _Execution_trigger(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_trigger(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Trigger, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v store.ExecutionTrigger) graphql.Marshaler { + return ec.marshalNExecutionTrigger2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecutionTrigger(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_trigger(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type ExecutionTrigger does not have child fields")) +} + +func (ec *executionContext) _Execution_createdAt(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_createdAt(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CreatedAt, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Execution", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _Execution_function(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_function(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Execution().Function(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalOFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Execution_function(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Execution", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Execution_version(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_version(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Execution().Version(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionVersion) graphql.Marshaler { + return ec.marshalOFunctionVersion2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionVersion(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Execution_version(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Execution", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_FunctionVersion(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Execution_logs(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_logs(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Execution().Logs(ctx, obj, fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.LogEntryConnection) graphql.Marshaler { + return ec.marshalNLogEntryConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogEntryConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_logs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Execution", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_LogEntryConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Execution_logs_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Execution_aiRequests(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_aiRequests(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Execution().AiRequests(ctx, obj, fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.AIRequestConnection) graphql.Marshaler { + return ec.marshalNAIRequestConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐAIRequestConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_aiRequests(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Execution", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_AIRequestConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Execution_aiRequests_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Execution_emailRequests(ctx context.Context, field graphql.CollectedField, obj *store.Execution) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Execution_emailRequests(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Execution().EmailRequests(ctx, obj, fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.EmailRequestConnection) graphql.Marshaler { + return ec.marshalNEmailRequestConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐEmailRequestConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Execution_emailRequests(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Execution", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_EmailRequestConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Execution_emailRequests_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _ExecutionConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *model.ExecutionConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_ExecutionConnection_nodes(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Nodes, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []store.Execution) graphql.Marshaler { + return ec.marshalNExecution2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecutionᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_ExecutionConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExecutionConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Execution(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _ExecutionConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.ExecutionConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_ExecutionConnection_pageInfo(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.PageInfo, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.PaginationInfo) graphql.Marshaler { + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐPaginationInfo(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_ExecutionConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "ExecutionConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_PageInfo(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Function_id(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _Function_name(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_name(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Name, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _Function_description(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_description(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Description, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Function_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _Function_disabled(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_disabled(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Disabled, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_disabled(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) _Function_retentionDays(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_retentionDays(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.RetentionDays, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *int) graphql.Marshaler { + return ec.marshalOInt2ᚖint(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Function_retentionDays(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _Function_cronSchedule(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_cronSchedule(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CronSchedule, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Function_cronSchedule(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _Function_cronStatus(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_cronStatus(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Function().CronStatus(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.CronStatus) graphql.Marshaler { + return ec.marshalOCronStatus2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐCronStatus(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Function_cronStatus(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, true, true, errors.New("field of type CronStatus does not have child fields")) +} + +func (ec *executionContext) _Function_saveResponse(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_saveResponse(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.SaveResponse, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_saveResponse(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) _Function_createdAt(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_createdAt(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CreatedAt, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _Function_updatedAt(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_updatedAt(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.UpdatedAt, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_updatedAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _Function_activeVersion(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_activeVersion(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ActiveVersion, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v store.FunctionVersion) graphql.Marshaler { + return ec.marshalNFunctionVersion2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionVersion(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_activeVersion(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Function", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_FunctionVersion(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Function_versions(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_versions(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Function().Versions(ctx, obj, fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.FunctionVersionConnection) graphql.Marshaler { + return ec.marshalNFunctionVersionConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐFunctionVersionConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_versions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Function", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_FunctionVersionConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Function_versions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Function_executions(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_executions(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Function().Executions(ctx, obj, fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.ExecutionConnection) graphql.Marshaler { + return ec.marshalNExecutionConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐExecutionConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_executions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Function", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_ExecutionConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Function_executions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Function_nextRun(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_nextRun(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Function().NextRun(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.NextRun) graphql.Marshaler { + return ec.marshalNNextRun2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐNextRun(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_nextRun(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Function", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_NextRun(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Function_envVars(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_envVars(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Function().EnvVars(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v model.StringMap) graphql.Marshaler { + return ec.marshalNMap2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐStringMap(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_envVars(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, true, true, errors.New("field of type Map does not have child fields")) +} + +func (ec *executionContext) _Function_scopedData(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_scopedData(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Function().ScopedData(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v model.StringMap) graphql.Marshaler { + return ec.marshalNMap2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐStringMap(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_scopedData(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, true, true, errors.New("field of type Map does not have child fields")) +} + +func (ec *executionContext) _Function_globalData(ctx context.Context, field graphql.CollectedField, obj *store.FunctionWithActiveVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Function_globalData(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Function().GlobalData(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v model.StringMap) graphql.Marshaler { + return ec.marshalNMap2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐStringMap(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Function_globalData(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("Function", field, true, true, errors.New("field of type Map does not have child fields")) +} + +func (ec *executionContext) _FunctionConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *model.FunctionConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionConnection_nodes(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Nodes, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalNFunction2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersionᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FunctionConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _FunctionConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.FunctionConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionConnection_pageInfo(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.PageInfo, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.PaginationInfo) graphql.Marshaler { + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐPaginationInfo(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FunctionConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_PageInfo(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _FunctionVersion_id(ctx context.Context, field graphql.CollectedField, obj *store.FunctionVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersion_id(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.ID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionVersion_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("FunctionVersion", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _FunctionVersion_functionId(ctx context.Context, field graphql.CollectedField, obj *store.FunctionVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersion_functionId(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.FunctionID, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNID2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionVersion_functionId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("FunctionVersion", field, false, false, errors.New("field of type ID does not have child fields")) +} + +func (ec *executionContext) _FunctionVersion_version(ctx context.Context, field graphql.CollectedField, obj *store.FunctionVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersion_version(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Version, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNInt2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionVersion_version(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("FunctionVersion", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _FunctionVersion_code(ctx context.Context, field graphql.CollectedField, obj *store.FunctionVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersion_code(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Code, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionVersion_code(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("FunctionVersion", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _FunctionVersion_createdAt(ctx context.Context, field graphql.CollectedField, obj *store.FunctionVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersion_createdAt(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CreatedAt, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionVersion_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("FunctionVersion", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _FunctionVersion_createdBy(ctx context.Context, field graphql.CollectedField, obj *store.FunctionVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersion_createdBy(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CreatedBy, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_FunctionVersion_createdBy(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("FunctionVersion", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _FunctionVersion_isActive(ctx context.Context, field graphql.CollectedField, obj *store.FunctionVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersion_isActive(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.IsActive, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionVersion_isActive(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("FunctionVersion", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) _FunctionVersion_function(ctx context.Context, field graphql.CollectedField, obj *store.FunctionVersion) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersion_function(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.FunctionVersion().Function(ctx, obj) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalOFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_FunctionVersion_function(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FunctionVersion", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _FunctionVersionConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *model.FunctionVersionConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersionConnection_nodes(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Nodes, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []store.FunctionVersion) graphql.Marshaler { + return ec.marshalNFunctionVersion2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionVersionᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionVersionConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FunctionVersionConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_FunctionVersion(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _FunctionVersionConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.FunctionVersionConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_FunctionVersionConnection_pageInfo(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.PageInfo, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.PaginationInfo) graphql.Marshaler { + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐPaginationInfo(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_FunctionVersionConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "FunctionVersionConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_PageInfo(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _LogEntry_level(ctx context.Context, field graphql.CollectedField, obj *model.LogEntry) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_LogEntry_level(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Level, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v model.LogLevel) graphql.Marshaler { + return ec.marshalNLogLevel2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogLevel(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_LogEntry_level(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("LogEntry", field, false, false, errors.New("field of type LogLevel does not have child fields")) +} + +func (ec *executionContext) _LogEntry_message(ctx context.Context, field graphql.CollectedField, obj *model.LogEntry) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_LogEntry_message(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Message, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_LogEntry_message(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("LogEntry", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _LogEntry_createdAt(ctx context.Context, field graphql.CollectedField, obj *model.LogEntry) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_LogEntry_createdAt(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CreatedAt, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNInt2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_LogEntry_createdAt(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("LogEntry", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _LogEntryConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *model.LogEntryConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_LogEntryConnection_nodes(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Nodes, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []model.LogEntry) graphql.Marshaler { + return ec.marshalNLogEntry2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogEntryᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_LogEntryConnection_nodes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "LogEntryConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_LogEntry(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _LogEntryConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.LogEntryConnection) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_LogEntryConnection_pageInfo(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.PageInfo, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.PaginationInfo) graphql.Marshaler { + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐPaginationInfo(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_LogEntryConnection_pageInfo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "LogEntryConnection", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_PageInfo(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Mutation_createFunction(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_createFunction(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().CreateFunction(ctx, fc.Args["input"].(model.CreateFunctionInput)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalNFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_createFunction(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_createFunction_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_updateFunction(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_updateFunction(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().UpdateFunction(ctx, fc.Args["id"].(string), fc.Args["input"].(model.UpdateFunctionInput)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalNFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_updateFunction(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_updateFunction_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_deleteFunction(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_deleteFunction(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().DeleteFunction(ctx, fc.Args["id"].(string)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_deleteFunction(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_deleteFunction_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_setFunctionEnv(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_setFunctionEnv(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().SetFunctionEnv(ctx, fc.Args["id"].(string), fc.Args["env"].(model.StringMap)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalNFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_setFunctionEnv(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_setFunctionEnv_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_setFunctionKv(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_setFunctionKv(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().SetFunctionKv(ctx, fc.Args["id"].(string), fc.Args["kv"].(model.StringMap), fc.Args["global"].(*bool)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalNFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_setFunctionKv(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_setFunctionKv_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_revokeApiToken(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_revokeApiToken(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().RevokeAPIToken(ctx, fc.Args["id"].(string)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_revokeApiToken(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_revokeApiToken_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_activateVersion(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_activateVersion(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().ActivateVersion(ctx, fc.Args["functionId"].(string), fc.Args["versionId"].(string)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalNFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_activateVersion(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_activateVersion_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Mutation_deleteVersion(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Mutation_deleteVersion(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Mutation().DeleteVersion(ctx, fc.Args["functionId"].(string), fc.Args["versionId"].(string)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Mutation_deleteVersion(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_deleteVersion_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _NextRun_hasSchedule(ctx context.Context, field graphql.CollectedField, obj *model.NextRun) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_NextRun_hasSchedule(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.HasSchedule, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_NextRun_hasSchedule(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("NextRun", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) _NextRun_cronSchedule(ctx context.Context, field graphql.CollectedField, obj *model.NextRun) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_NextRun_cronSchedule(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CronSchedule, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_NextRun_cronSchedule(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("NextRun", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _NextRun_cronStatus(ctx context.Context, field graphql.CollectedField, obj *model.NextRun) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_NextRun_cronStatus(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.CronStatus, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.CronStatus) graphql.Marshaler { + return ec.marshalOCronStatus2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐCronStatus(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_NextRun_cronStatus(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("NextRun", field, false, false, errors.New("field of type CronStatus does not have child fields")) +} + +func (ec *executionContext) _NextRun_isPaused(ctx context.Context, field graphql.CollectedField, obj *model.NextRun) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_NextRun_isPaused(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.IsPaused, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_NextRun_isPaused(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("NextRun", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) _NextRun_nextRun(ctx context.Context, field graphql.CollectedField, obj *model.NextRun) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_NextRun_nextRun(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.NextRun, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *int) graphql.Marshaler { + return ec.marshalOInt2ᚖint(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_NextRun_nextRun(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("NextRun", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _NextRun_nextRunHuman(ctx context.Context, field graphql.CollectedField, obj *model.NextRun) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_NextRun_nextRunHuman(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.NextRunHuman, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_NextRun_nextRunHuman(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("NextRun", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) _PageInfo_total(ctx context.Context, field graphql.CollectedField, obj *store.PaginationInfo) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_PageInfo_total(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Total, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int64) graphql.Marshaler { + return ec.marshalNInt2int64(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_PageInfo_total(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("PageInfo", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _PageInfo_limit(ctx context.Context, field graphql.CollectedField, obj *store.PaginationInfo) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_PageInfo_limit(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Limit, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNInt2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_PageInfo_limit(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("PageInfo", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _PageInfo_offset(ctx context.Context, field graphql.CollectedField, obj *store.PaginationInfo) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_PageInfo_offset(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Offset, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNInt2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_PageInfo_offset(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("PageInfo", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _Query_functions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_functions(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().Functions(ctx, fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.FunctionConnection) graphql.Marshaler { + return ec.marshalNFunctionConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐFunctionConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_functions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_FunctionConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_functions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_function(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_function(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().Function(ctx, fc.Args["id"].(string)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + return ec.marshalOFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Query_function(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Function(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_function_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_executions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_executions(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().Executions(ctx, fc.Args["functionId"].(string), fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.ExecutionConnection) graphql.Marshaler { + return ec.marshalNExecutionConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐExecutionConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_executions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_ExecutionConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_executions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_execution(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_execution(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().Execution(ctx, fc.Args["id"].(string)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.Execution) graphql.Marshaler { + return ec.marshalOExecution2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecution(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Query_execution(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_Execution(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_execution_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_executionLogs(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_executionLogs(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().ExecutionLogs(ctx, fc.Args["executionId"].(string), fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.LogEntryConnection) graphql.Marshaler { + return ec.marshalNLogEntryConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogEntryConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_executionLogs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_LogEntryConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_executionLogs_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_executionAiRequests(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_executionAiRequests(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().ExecutionAiRequests(ctx, fc.Args["executionId"].(string), fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.AIRequestConnection) graphql.Marshaler { + return ec.marshalNAIRequestConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐAIRequestConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_executionAiRequests(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_AIRequestConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_executionAiRequests_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_executionEmailRequests(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_executionEmailRequests(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().ExecutionEmailRequests(ctx, fc.Args["executionId"].(string), fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.EmailRequestConnection) graphql.Marshaler { + return ec.marshalNEmailRequestConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐEmailRequestConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_executionEmailRequests(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_EmailRequestConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_executionEmailRequests_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_nextRun(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_nextRun(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().NextRun(ctx, fc.Args["functionId"].(string)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.NextRun) graphql.Marshaler { + return ec.marshalNNextRun2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐNextRun(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_nextRun(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_NextRun(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_nextRun_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_apiTokens(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_apiTokens(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.Resolvers.Query().APITokens(ctx) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []store.APIToken) graphql.Marshaler { + return ec.marshalNAPIToken2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAPITokenᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_apiTokens(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_APIToken(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_versions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_versions(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().Versions(ctx, fc.Args["functionId"].(string), fc.Args["limit"].(*int), fc.Args["offset"].(*int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.FunctionVersionConnection) graphql.Marshaler { + return ec.marshalNFunctionVersionConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐFunctionVersionConnection(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_versions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_FunctionVersionConnection(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_versions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_version(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_version(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().Version(ctx, fc.Args["functionId"].(string), fc.Args["version"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *store.FunctionVersion) graphql.Marshaler { + return ec.marshalOFunctionVersion2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionVersion(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Query_version(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_FunctionVersion(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_version_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_versionDiff(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query_versionDiff(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.Resolvers.Query().VersionDiff(ctx, fc.Args["functionId"].(string), fc.Args["oldVersion"].(int), fc.Args["newVersion"].(int)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *model.VersionDiff) graphql.Marshaler { + return ec.marshalNVersionDiff2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐVersionDiff(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_Query_versionDiff(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_VersionDiff(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_versionDiff_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query___type(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return ec.IntrospectType(fc.Args["name"].(string)) + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Query___type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query___type_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_Query___schema(ctx, field) + }, + func(ctx context.Context) (any, error) { + return ec.IntrospectSchema() + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *introspection.Schema) graphql.Marshaler { + return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext_Query___schema(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Schema(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) _VersionDiff_oldVersion(ctx context.Context, field graphql.CollectedField, obj *model.VersionDiff) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_VersionDiff_oldVersion(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.OldVersion, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNInt2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_VersionDiff_oldVersion(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("VersionDiff", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _VersionDiff_newVersion(ctx context.Context, field graphql.CollectedField, obj *model.VersionDiff) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_VersionDiff_newVersion(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.NewVersion, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v int) graphql.Marshaler { + return ec.marshalNInt2int(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_VersionDiff_newVersion(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("VersionDiff", field, false, false, errors.New("field of type Int does not have child fields")) +} + +func (ec *executionContext) _VersionDiff_lines(ctx context.Context, field graphql.CollectedField, obj *model.VersionDiff) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext_VersionDiff_lines(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Lines, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []model.DiffLine) graphql.Marshaler { + return ec.marshalNDiffLine2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐDiffLineᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext_VersionDiff_lines(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "VersionDiff", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields_DiffLine(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Directive_name(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Name, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Directive_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Directive", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Directive_description(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Description(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Directive_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Directive", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Directive_isRepeatable(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.IsRepeatable, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Directive_isRepeatable(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Directive", field, false, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Directive_locations(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Locations, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []string) graphql.Marshaler { + return ec.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Directive_locations(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Directive", field, false, false, errors.New("field of type __DirectiveLocation does not have child fields")) +} + +func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Directive_args(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Args, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Directive_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___InputValue(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field___Directive_args_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___EnumValue_name(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Name, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___EnumValue_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__EnumValue", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___EnumValue_description(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Description(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___EnumValue_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__EnumValue", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___EnumValue_isDeprecated(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.IsDeprecated(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___EnumValue_isDeprecated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__EnumValue", field, true, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___EnumValue_deprecationReason(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.DeprecationReason(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___EnumValue_deprecationReason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__EnumValue", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Field_name(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Name, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Field_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Field", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Field_description(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Description(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Field_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Field", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Field_args(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Args, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Field_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___InputValue(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field___Field_args_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Field_type(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Type, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Field_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Field_isDeprecated(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.IsDeprecated(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Field_isDeprecated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Field", field, true, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Field_deprecationReason(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.DeprecationReason(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Field_deprecationReason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Field", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___InputValue_name(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Name, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalNString2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___InputValue_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__InputValue", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___InputValue_description(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Description(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___InputValue_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__InputValue", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___InputValue_type(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Type, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___InputValue_type(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___InputValue_defaultValue(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.DefaultValue, nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___InputValue_defaultValue(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__InputValue", field, false, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___InputValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___InputValue_isDeprecated(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.IsDeprecated(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalNBoolean2bool(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___InputValue_isDeprecated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__InputValue", field, true, false, errors.New("field of type Boolean does not have child fields")) +} + +func (ec *executionContext) ___InputValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___InputValue_deprecationReason(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.DeprecationReason(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___InputValue_deprecationReason(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__InputValue", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Schema_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Schema_description(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Description(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Schema_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Schema", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Schema_types(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Types(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Schema_types(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Schema_queryType(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.QueryType(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Schema_queryType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Schema_mutationType(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.MutationType(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Schema_mutationType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Schema_subscriptionType(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.SubscriptionType(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Schema_subscriptionType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Schema_directives(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Directives(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { + return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Schema_directives(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Directive(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_kind(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Kind(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v string) graphql.Marshaler { + return ec.marshalN__TypeKind2string(ctx, selections, v) + }, + true, + true, + ) +} +func (ec *executionContext) fieldContext___Type_kind(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Type", field, true, false, errors.New("field of type __TypeKind does not have child fields")) +} + +func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_name(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Name(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_name(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Type", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_description(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Description(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_description(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Type", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Type_specifiedByURL(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_specifiedByURL(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.SpecifiedByURL(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *string) graphql.Marshaler { + return ec.marshalOString2ᚖstring(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_specifiedByURL(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Type", field, true, false, errors.New("field of type String does not have child fields")) +} + +func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_fields(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return obj.Fields(fc.Args["includeDeprecated"].(bool)), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.Field) graphql.Marshaler { + return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_fields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Field(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field___Type_fields_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_interfaces(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.Interfaces(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_interfaces(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_possibleTypes(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.PossibleTypes(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_possibleTypes(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_enumValues(ctx, field) + }, + func(ctx context.Context) (any, error) { + fc := graphql.GetFieldContext(ctx) + return obj.EnumValues(fc.Args["includeDeprecated"].(bool)), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { + return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_enumValues(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___EnumValue(ctx, field) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field___Type_enumValues_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_inputFields(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.InputFields(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_inputFields(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___InputValue(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_ofType(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.OfType(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_ofType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.childFields___Type(ctx, field) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_isOneOf(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + return graphql.ResolveField( + ctx, + ec.OperationContext, + field, + func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return ec.fieldContext___Type_isOneOf(ctx, field) + }, + func(ctx context.Context) (any, error) { + return obj.IsOneOf(), nil + }, + nil, + func(ctx context.Context, selections ast.SelectionSet, v bool) graphql.Marshaler { + return ec.marshalOBoolean2bool(ctx, selections, v) + }, + true, + false, + ) +} +func (ec *executionContext) fieldContext___Type_isOneOf(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + return graphql.NewScalarFieldContext("__Type", field, true, false, errors.New("field of type Boolean does not have child fields")) +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputCreateFunctionInput(ctx context.Context, obj any) (model.CreateFunctionInput, error) { + var it model.CreateFunctionInput + if obj == nil { + return it, nil + } + + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"name", "description", "code"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "name": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Name = data + case "description": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Description = data + case "code": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("code")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Code = data + } + } + return it, nil +} + +func (ec *executionContext) unmarshalInputUpdateFunctionInput(ctx context.Context, obj any) (model.UpdateFunctionInput, error) { + var it model.UpdateFunctionInput + if obj == nil { + return it, nil + } + + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"name", "description", "code", "disabled", "retentionDays", "cronSchedule", "cronStatus", "saveResponse"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "name": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Name = data + case "description": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("description")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Description = data + case "code": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("code")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.Code = data + case "disabled": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("disabled")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.Disabled = data + case "retentionDays": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("retentionDays")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + it.RetentionDays = data + case "cronSchedule": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("cronSchedule")) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + it.CronSchedule = data + case "cronStatus": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("cronStatus")) + data, err := ec.unmarshalOCronStatus2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐCronStatus(ctx, v) + if err != nil { + return it, err + } + it.CronStatus = data + case "saveResponse": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("saveResponse")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.SaveResponse = data + } + } + return it, nil +} + +// endregion **************************** input.gotpl ***************************** + +// region ************************** interface.gotpl *************************** + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var aIRequestImplementors = []string{"AIRequest"} + +func (ec *executionContext) _AIRequest(ctx context.Context, sel ast.SelectionSet, obj *store.AIRequest) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, aIRequestImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("AIRequest") + case "id": + out.Values[i] = ec._AIRequest_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "executionId": + out.Values[i] = ec._AIRequest_executionId(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "provider": + out.Values[i] = ec._AIRequest_provider(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "model": + out.Values[i] = ec._AIRequest_model(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "endpoint": + out.Values[i] = ec._AIRequest_endpoint(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "requestJson": + out.Values[i] = ec._AIRequest_requestJson(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "responseJson": + out.Values[i] = ec._AIRequest_responseJson(ctx, field, obj) + case "status": + out.Values[i] = ec._AIRequest_status(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "errorMessage": + out.Values[i] = ec._AIRequest_errorMessage(ctx, field, obj) + case "inputTokens": + out.Values[i] = ec._AIRequest_inputTokens(ctx, field, obj) + case "outputTokens": + out.Values[i] = ec._AIRequest_outputTokens(ctx, field, obj) + case "durationMs": + out.Values[i] = ec._AIRequest_durationMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "createdAt": + out.Values[i] = ec._AIRequest_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "execution": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._AIRequest_execution(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var aIRequestConnectionImplementors = []string{"AIRequestConnection"} + +func (ec *executionContext) _AIRequestConnection(ctx context.Context, sel ast.SelectionSet, obj *model.AIRequestConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, aIRequestConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("AIRequestConnection") + case "nodes": + out.Values[i] = ec._AIRequestConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._AIRequestConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var aPITokenImplementors = []string{"APIToken"} + +func (ec *executionContext) _APIToken(ctx context.Context, sel ast.SelectionSet, obj *store.APIToken) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, aPITokenImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("APIToken") + case "id": + out.Values[i] = ec._APIToken_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "name": + out.Values[i] = ec._APIToken_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "createdAt": + out.Values[i] = ec._APIToken_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "lastUsed": + out.Values[i] = ec._APIToken_lastUsed(ctx, field, obj) + case "revoked": + out.Values[i] = ec._APIToken_revoked(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var diffLineImplementors = []string{"DiffLine"} + +func (ec *executionContext) _DiffLine(ctx context.Context, sel ast.SelectionSet, obj *model.DiffLine) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, diffLineImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DiffLine") + case "lineType": + out.Values[i] = ec._DiffLine_lineType(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "oldLine": + out.Values[i] = ec._DiffLine_oldLine(ctx, field, obj) + case "newLine": + out.Values[i] = ec._DiffLine_newLine(ctx, field, obj) + case "content": + out.Values[i] = ec._DiffLine_content(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var emailRequestImplementors = []string{"EmailRequest"} + +func (ec *executionContext) _EmailRequest(ctx context.Context, sel ast.SelectionSet, obj *store.EmailRequest) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, emailRequestImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("EmailRequest") + case "id": + out.Values[i] = ec._EmailRequest_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "executionId": + out.Values[i] = ec._EmailRequest_executionId(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "from": + out.Values[i] = ec._EmailRequest_from(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "to": + out.Values[i] = ec._EmailRequest_to(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "subject": + out.Values[i] = ec._EmailRequest_subject(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "hasText": + out.Values[i] = ec._EmailRequest_hasText(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "hasHtml": + out.Values[i] = ec._EmailRequest_hasHtml(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "requestJson": + out.Values[i] = ec._EmailRequest_requestJson(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "responseJson": + out.Values[i] = ec._EmailRequest_responseJson(ctx, field, obj) + case "status": + out.Values[i] = ec._EmailRequest_status(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "errorMessage": + out.Values[i] = ec._EmailRequest_errorMessage(ctx, field, obj) + case "emailId": + out.Values[i] = ec._EmailRequest_emailId(ctx, field, obj) + case "durationMs": + out.Values[i] = ec._EmailRequest_durationMs(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "createdAt": + out.Values[i] = ec._EmailRequest_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "execution": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._EmailRequest_execution(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var emailRequestConnectionImplementors = []string{"EmailRequestConnection"} + +func (ec *executionContext) _EmailRequestConnection(ctx context.Context, sel ast.SelectionSet, obj *model.EmailRequestConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, emailRequestConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("EmailRequestConnection") + case "nodes": + out.Values[i] = ec._EmailRequestConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._EmailRequestConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var executionImplementors = []string{"Execution"} + +func (ec *executionContext) _Execution(ctx context.Context, sel ast.SelectionSet, obj *store.Execution) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, executionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Execution") + case "id": + out.Values[i] = ec._Execution_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "functionId": + out.Values[i] = ec._Execution_functionId(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "functionVersionId": + out.Values[i] = ec._Execution_functionVersionId(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "status": + out.Values[i] = ec._Execution_status(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "durationMs": + out.Values[i] = ec._Execution_durationMs(ctx, field, obj) + case "errorMessage": + out.Values[i] = ec._Execution_errorMessage(ctx, field, obj) + case "eventJson": + out.Values[i] = ec._Execution_eventJson(ctx, field, obj) + case "responseJson": + out.Values[i] = ec._Execution_responseJson(ctx, field, obj) + case "trigger": + out.Values[i] = ec._Execution_trigger(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "createdAt": + out.Values[i] = ec._Execution_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "function": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Execution_function(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "version": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Execution_version(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "logs": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Execution_logs(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "aiRequests": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Execution_aiRequests(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "emailRequests": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Execution_emailRequests(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var executionConnectionImplementors = []string{"ExecutionConnection"} + +func (ec *executionContext) _ExecutionConnection(ctx context.Context, sel ast.SelectionSet, obj *model.ExecutionConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, executionConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("ExecutionConnection") + case "nodes": + out.Values[i] = ec._ExecutionConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._ExecutionConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var functionImplementors = []string{"Function"} + +func (ec *executionContext) _Function(ctx context.Context, sel ast.SelectionSet, obj *store.FunctionWithActiveVersion) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, functionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Function") + case "id": + out.Values[i] = ec._Function_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "name": + out.Values[i] = ec._Function_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "description": + out.Values[i] = ec._Function_description(ctx, field, obj) + case "disabled": + out.Values[i] = ec._Function_disabled(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "retentionDays": + out.Values[i] = ec._Function_retentionDays(ctx, field, obj) + case "cronSchedule": + out.Values[i] = ec._Function_cronSchedule(ctx, field, obj) + case "cronStatus": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Function_cronStatus(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "saveResponse": + out.Values[i] = ec._Function_saveResponse(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "createdAt": + out.Values[i] = ec._Function_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "updatedAt": + out.Values[i] = ec._Function_updatedAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "activeVersion": + out.Values[i] = ec._Function_activeVersion(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "versions": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Function_versions(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "executions": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Function_executions(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "nextRun": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Function_nextRun(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "envVars": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Function_envVars(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "scopedData": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Function_scopedData(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "globalData": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Function_globalData(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var functionConnectionImplementors = []string{"FunctionConnection"} + +func (ec *executionContext) _FunctionConnection(ctx context.Context, sel ast.SelectionSet, obj *model.FunctionConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, functionConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("FunctionConnection") + case "nodes": + out.Values[i] = ec._FunctionConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._FunctionConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var functionVersionImplementors = []string{"FunctionVersion"} + +func (ec *executionContext) _FunctionVersion(ctx context.Context, sel ast.SelectionSet, obj *store.FunctionVersion) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, functionVersionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("FunctionVersion") + case "id": + out.Values[i] = ec._FunctionVersion_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "functionId": + out.Values[i] = ec._FunctionVersion_functionId(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "version": + out.Values[i] = ec._FunctionVersion_version(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "code": + out.Values[i] = ec._FunctionVersion_code(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "createdAt": + out.Values[i] = ec._FunctionVersion_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "createdBy": + out.Values[i] = ec._FunctionVersion_createdBy(ctx, field, obj) + case "isActive": + out.Values[i] = ec._FunctionVersion_isActive(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } + case "function": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._FunctionVersion_function(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var functionVersionConnectionImplementors = []string{"FunctionVersionConnection"} + +func (ec *executionContext) _FunctionVersionConnection(ctx context.Context, sel ast.SelectionSet, obj *model.FunctionVersionConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, functionVersionConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("FunctionVersionConnection") + case "nodes": + out.Values[i] = ec._FunctionVersionConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._FunctionVersionConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var logEntryImplementors = []string{"LogEntry"} + +func (ec *executionContext) _LogEntry(ctx context.Context, sel ast.SelectionSet, obj *model.LogEntry) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, logEntryImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("LogEntry") + case "level": + out.Values[i] = ec._LogEntry_level(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "message": + out.Values[i] = ec._LogEntry_message(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "createdAt": + out.Values[i] = ec._LogEntry_createdAt(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var logEntryConnectionImplementors = []string{"LogEntryConnection"} + +func (ec *executionContext) _LogEntryConnection(ctx context.Context, sel ast.SelectionSet, obj *model.LogEntryConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, logEntryConnectionImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("LogEntryConnection") + case "nodes": + out.Values[i] = ec._LogEntryConnection_nodes(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._LogEntryConnection_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var mutationImplementors = []string{"Mutation"} + +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Mutation", + }) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Mutation") + case "createFunction": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_createFunction(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "updateFunction": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_updateFunction(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deleteFunction": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_deleteFunction(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "setFunctionEnv": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_setFunctionEnv(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "setFunctionKv": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_setFunctionKv(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "revokeApiToken": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_revokeApiToken(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "activateVersion": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_activateVersion(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deleteVersion": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_deleteVersion(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var nextRunImplementors = []string{"NextRun"} + +func (ec *executionContext) _NextRun(ctx context.Context, sel ast.SelectionSet, obj *model.NextRun) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, nextRunImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("NextRun") + case "hasSchedule": + out.Values[i] = ec._NextRun_hasSchedule(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "cronSchedule": + out.Values[i] = ec._NextRun_cronSchedule(ctx, field, obj) + case "cronStatus": + out.Values[i] = ec._NextRun_cronStatus(ctx, field, obj) + case "isPaused": + out.Values[i] = ec._NextRun_isPaused(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "nextRun": + out.Values[i] = ec._NextRun_nextRun(ctx, field, obj) + case "nextRunHuman": + out.Values[i] = ec._NextRun_nextRunHuman(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var pageInfoImplementors = []string{"PageInfo"} + +func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, obj *store.PaginationInfo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, pageInfoImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("PageInfo") + case "total": + out.Values[i] = ec._PageInfo_total(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "limit": + out.Values[i] = ec._PageInfo_limit(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "offset": + out.Values[i] = ec._PageInfo_offset(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var queryImplementors = []string{"Query"} + +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Query", + }) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Query") + case "functions": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_functions(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "function": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_function(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "executions": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_executions(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "execution": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_execution(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "executionLogs": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_executionLogs(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "executionAiRequests": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_executionAiRequests(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "executionEmailRequests": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_executionEmailRequests(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "nextRun": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_nextRun(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "apiTokens": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_apiTokens(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "versions": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_versions(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "version": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_version(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "versionDiff": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_versionDiff(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) + case "__type": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Query___type(ctx, field) + }) + case "__schema": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Query___schema(ctx, field) + }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var versionDiffImplementors = []string{"VersionDiff"} + +func (ec *executionContext) _VersionDiff(ctx context.Context, sel ast.SelectionSet, obj *model.VersionDiff) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, versionDiffImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("VersionDiff") + case "oldVersion": + out.Values[i] = ec._VersionDiff_oldVersion(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "newVersion": + out.Values[i] = ec._VersionDiff_newVersion(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "lines": + out.Values[i] = ec._VersionDiff_lines(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __DirectiveImplementors = []string{"__Directive"} + +func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Directive") + case "name": + out.Values[i] = ec.___Directive_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec.___Directive_description(ctx, field, obj) + case "isRepeatable": + out.Values[i] = ec.___Directive_isRepeatable(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "locations": + out.Values[i] = ec.___Directive_locations(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "args": + out.Values[i] = ec.___Directive_args(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __EnumValueImplementors = []string{"__EnumValue"} + +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__EnumValue") + case "name": + out.Values[i] = ec.___EnumValue_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec.___EnumValue_description(ctx, field, obj) + case "isDeprecated": + out.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __FieldImplementors = []string{"__Field"} + +func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Field") + case "name": + out.Values[i] = ec.___Field_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec.___Field_description(ctx, field, obj) + case "args": + out.Values[i] = ec.___Field_args(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "type": + out.Values[i] = ec.___Field_type(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "isDeprecated": + out.Values[i] = ec.___Field_isDeprecated(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___Field_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __InputValueImplementors = []string{"__InputValue"} + +func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__InputValue") + case "name": + out.Values[i] = ec.___InputValue_name(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "description": + out.Values[i] = ec.___InputValue_description(ctx, field, obj) + case "type": + out.Values[i] = ec.___InputValue_type(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "defaultValue": + out.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj) + case "isDeprecated": + out.Values[i] = ec.___InputValue_isDeprecated(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___InputValue_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __SchemaImplementors = []string{"__Schema"} + +func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Schema") + case "description": + out.Values[i] = ec.___Schema_description(ctx, field, obj) + case "types": + out.Values[i] = ec.___Schema_types(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "queryType": + out.Values[i] = ec.___Schema_queryType(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "mutationType": + out.Values[i] = ec.___Schema_mutationType(ctx, field, obj) + case "subscriptionType": + out.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj) + case "directives": + out.Values[i] = ec.___Schema_directives(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var __TypeImplementors = []string{"__Type"} + +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Type") + case "kind": + out.Values[i] = ec.___Type_kind(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "name": + out.Values[i] = ec.___Type_name(ctx, field, obj) + case "description": + out.Values[i] = ec.___Type_description(ctx, field, obj) + case "specifiedByURL": + out.Values[i] = ec.___Type_specifiedByURL(ctx, field, obj) + case "fields": + out.Values[i] = ec.___Type_fields(ctx, field, obj) + case "interfaces": + out.Values[i] = ec.___Type_interfaces(ctx, field, obj) + case "possibleTypes": + out.Values[i] = ec.___Type_possibleTypes(ctx, field, obj) + case "enumValues": + out.Values[i] = ec.___Type_enumValues(ctx, field, obj) + case "inputFields": + out.Values[i] = ec.___Type_inputFields(ctx, field, obj) + case "ofType": + out.Values[i] = ec.___Type_ofType(ctx, field, obj) + case "isOneOf": + out.Values[i] = ec.___Type_isOneOf(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.Deferred, int32(min(len(deferred), math.MaxInt32))) + + for label, dfs := range deferred { + ec.ProcessDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +// endregion **************************** object.gotpl **************************** + +// region ***************************** type.gotpl ***************************** + +func (ec *executionContext) marshalNAIRequest2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAIRequest(ctx context.Context, sel ast.SelectionSet, v store.AIRequest) graphql.Marshaler { + return ec._AIRequest(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAIRequest2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAIRequestᚄ(ctx context.Context, sel ast.SelectionSet, v []store.AIRequest) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNAIRequest2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAIRequest(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNAIRequestConnection2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐAIRequestConnection(ctx context.Context, sel ast.SelectionSet, v model.AIRequestConnection) graphql.Marshaler { + return ec._AIRequestConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAIRequestConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐAIRequestConnection(ctx context.Context, sel ast.SelectionSet, v *model.AIRequestConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._AIRequestConnection(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNAIRequestStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAIRequestStatus(ctx context.Context, v any) (store.AIRequestStatus, error) { + tmp, err := graphql.UnmarshalString(v) + res := store.AIRequestStatus(tmp) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNAIRequestStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAIRequestStatus(ctx context.Context, sel ast.SelectionSet, v store.AIRequestStatus) graphql.Marshaler { + _ = sel + res := graphql.MarshalString(string(v)) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalNAPIToken2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAPIToken(ctx context.Context, sel ast.SelectionSet, v store.APIToken) graphql.Marshaler { + return ec._APIToken(ctx, sel, &v) +} + +func (ec *executionContext) marshalNAPIToken2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAPITokenᚄ(ctx context.Context, sel ast.SelectionSet, v []store.APIToken) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNAPIToken2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐAPIToken(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v any) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + _ = sel + res := graphql.MarshalBoolean(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNCreateFunctionInput2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐCreateFunctionInput(ctx context.Context, v any) (model.CreateFunctionInput, error) { + res, err := ec.unmarshalInputCreateFunctionInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDiffLine2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐDiffLine(ctx context.Context, sel ast.SelectionSet, v model.DiffLine) graphql.Marshaler { + return ec._DiffLine(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDiffLine2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐDiffLineᚄ(ctx context.Context, sel ast.SelectionSet, v []model.DiffLine) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNDiffLine2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐDiffLine(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalNDiffLineType2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐDiffLineType(ctx context.Context, v any) (model.DiffLineType, error) { + var res model.DiffLineType + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDiffLineType2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐDiffLineType(ctx context.Context, sel ast.SelectionSet, v model.DiffLineType) graphql.Marshaler { + return v +} + +func (ec *executionContext) marshalNEmailRequest2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐEmailRequest(ctx context.Context, sel ast.SelectionSet, v store.EmailRequest) graphql.Marshaler { + return ec._EmailRequest(ctx, sel, &v) +} + +func (ec *executionContext) marshalNEmailRequest2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐEmailRequestᚄ(ctx context.Context, sel ast.SelectionSet, v []store.EmailRequest) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNEmailRequest2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐEmailRequest(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNEmailRequestConnection2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐEmailRequestConnection(ctx context.Context, sel ast.SelectionSet, v model.EmailRequestConnection) graphql.Marshaler { + return ec._EmailRequestConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNEmailRequestConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐEmailRequestConnection(ctx context.Context, sel ast.SelectionSet, v *model.EmailRequestConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._EmailRequestConnection(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNEmailRequestStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐEmailRequestStatus(ctx context.Context, v any) (store.EmailRequestStatus, error) { + tmp, err := graphql.UnmarshalString(v) + res := store.EmailRequestStatus(tmp) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNEmailRequestStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐEmailRequestStatus(ctx context.Context, sel ast.SelectionSet, v store.EmailRequestStatus) graphql.Marshaler { + _ = sel + res := graphql.MarshalString(string(v)) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalNExecution2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecution(ctx context.Context, sel ast.SelectionSet, v store.Execution) graphql.Marshaler { + return ec._Execution(ctx, sel, &v) +} + +func (ec *executionContext) marshalNExecution2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecutionᚄ(ctx context.Context, sel ast.SelectionSet, v []store.Execution) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNExecution2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecution(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNExecutionConnection2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐExecutionConnection(ctx context.Context, sel ast.SelectionSet, v model.ExecutionConnection) graphql.Marshaler { + return ec._ExecutionConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNExecutionConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐExecutionConnection(ctx context.Context, sel ast.SelectionSet, v *model.ExecutionConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._ExecutionConnection(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNExecutionStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecutionStatus(ctx context.Context, v any) (store.ExecutionStatus, error) { + tmp, err := graphql.UnmarshalString(v) + res := store.ExecutionStatus(tmp) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNExecutionStatus2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecutionStatus(ctx context.Context, sel ast.SelectionSet, v store.ExecutionStatus) graphql.Marshaler { + _ = sel + res := graphql.MarshalString(string(v)) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNExecutionTrigger2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecutionTrigger(ctx context.Context, v any) (store.ExecutionTrigger, error) { + tmp, err := graphql.UnmarshalString(v) + res := store.ExecutionTrigger(tmp) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNExecutionTrigger2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecutionTrigger(ctx context.Context, sel ast.SelectionSet, v store.ExecutionTrigger) graphql.Marshaler { + _ = sel + res := graphql.MarshalString(string(v)) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalNFunction2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx context.Context, sel ast.SelectionSet, v store.FunctionWithActiveVersion) graphql.Marshaler { + return ec._Function(ctx, sel, &v) +} + +func (ec *executionContext) marshalNFunction2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersionᚄ(ctx context.Context, sel ast.SelectionSet, v []store.FunctionWithActiveVersion) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNFunction2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx context.Context, sel ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._Function(ctx, sel, v) +} + +func (ec *executionContext) marshalNFunctionConnection2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐFunctionConnection(ctx context.Context, sel ast.SelectionSet, v model.FunctionConnection) graphql.Marshaler { + return ec._FunctionConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNFunctionConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐFunctionConnection(ctx context.Context, sel ast.SelectionSet, v *model.FunctionConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._FunctionConnection(ctx, sel, v) +} + +func (ec *executionContext) marshalNFunctionVersion2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionVersion(ctx context.Context, sel ast.SelectionSet, v store.FunctionVersion) graphql.Marshaler { + return ec._FunctionVersion(ctx, sel, &v) +} + +func (ec *executionContext) marshalNFunctionVersion2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionVersionᚄ(ctx context.Context, sel ast.SelectionSet, v []store.FunctionVersion) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNFunctionVersion2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionVersion(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNFunctionVersionConnection2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐFunctionVersionConnection(ctx context.Context, sel ast.SelectionSet, v model.FunctionVersionConnection) graphql.Marshaler { + return ec._FunctionVersionConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNFunctionVersionConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐFunctionVersionConnection(ctx context.Context, sel ast.SelectionSet, v *model.FunctionVersionConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._FunctionVersionConnection(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNID2string(ctx context.Context, v any) (string, error) { + res, err := graphql.UnmarshalID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + _ = sel + res := graphql.MarshalID(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v any) (int, error) { + res, err := graphql.UnmarshalInt(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + _ = sel + res := graphql.MarshalInt(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNInt2int64(ctx context.Context, v any) (int64, error) { + res, err := graphql.UnmarshalInt64(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNInt2int64(ctx context.Context, sel ast.SelectionSet, v int64) graphql.Marshaler { + _ = sel + res := graphql.MarshalInt64(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalNLogEntry2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogEntry(ctx context.Context, sel ast.SelectionSet, v model.LogEntry) graphql.Marshaler { + return ec._LogEntry(ctx, sel, &v) +} + +func (ec *executionContext) marshalNLogEntry2ᚕgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogEntryᚄ(ctx context.Context, sel ast.SelectionSet, v []model.LogEntry) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalNLogEntry2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogEntry(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNLogEntryConnection2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogEntryConnection(ctx context.Context, sel ast.SelectionSet, v model.LogEntryConnection) graphql.Marshaler { + return ec._LogEntryConnection(ctx, sel, &v) +} + +func (ec *executionContext) marshalNLogEntryConnection2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogEntryConnection(ctx context.Context, sel ast.SelectionSet, v *model.LogEntryConnection) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._LogEntryConnection(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNLogLevel2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogLevel(ctx context.Context, v any) (model.LogLevel, error) { + var res model.LogLevel + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNLogLevel2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐLogLevel(ctx context.Context, sel ast.SelectionSet, v model.LogLevel) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalNMap2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐStringMap(ctx context.Context, v any) (model.StringMap, error) { + var res model.StringMap + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNMap2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐStringMap(ctx context.Context, sel ast.SelectionSet, v model.StringMap) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return v +} + +func (ec *executionContext) marshalNNextRun2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐNextRun(ctx context.Context, sel ast.SelectionSet, v model.NextRun) graphql.Marshaler { + return ec._NextRun(ctx, sel, &v) +} + +func (ec *executionContext) marshalNNextRun2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐNextRun(ctx context.Context, sel ast.SelectionSet, v *model.NextRun) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._NextRun(ctx, sel, v) +} + +func (ec *executionContext) marshalNPageInfo2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐPaginationInfo(ctx context.Context, sel ast.SelectionSet, v *store.PaginationInfo) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._PageInfo(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNString2string(ctx context.Context, v any) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + _ = sel + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNString2ᚕstringᚄ(ctx context.Context, v any) ([]string, error) { + var vSlice []any + vSlice = graphql.CoerceList(v) + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNString2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNString2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNString2string(ctx, sel, v[i]) + } + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalNUpdateFunctionInput2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐUpdateFunctionInput(ctx context.Context, v any) (model.UpdateFunctionInput, error) { + res, err := ec.unmarshalInputUpdateFunctionInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNVersionDiff2githubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐVersionDiff(ctx context.Context, sel ast.SelectionSet, v model.VersionDiff) graphql.Marshaler { + return ec._VersionDiff(ctx, sel, &v) +} + +func (ec *executionContext) marshalNVersionDiff2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋgraphᚋmodelᚐVersionDiff(ctx context.Context, sel ast.SelectionSet, v *model.VersionDiff) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._VersionDiff(ctx, sel, v) +} + +func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { + return ec.___Directive(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v any) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + _ = sel + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v any) ([]string, error) { + var vSlice []any + vSlice = graphql.CoerceList(v) + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalN__DirectiveLocation2string(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler { + return ec.___EnumValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler { + return ec.___Field(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler { + return ec.___InputValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { + return ec.___Type(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v any) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + _ = sel + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v any) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + _ = sel + _ = ctx + res := graphql.MarshalBoolean(v) + return res +} + +func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v any) (*bool, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalBoolean(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { + if v == nil { + return graphql.Null + } + _ = sel + _ = ctx + res := graphql.MarshalBoolean(*v) + return res +} + +func (ec *executionContext) unmarshalOCronStatus2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐCronStatus(ctx context.Context, v any) (*store.CronStatus, error) { + if v == nil { + return nil, nil + } + tmp, err := graphql.UnmarshalString(v) + res := store.CronStatus(tmp) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOCronStatus2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐCronStatus(ctx context.Context, sel ast.SelectionSet, v *store.CronStatus) graphql.Marshaler { + if v == nil { + return graphql.Null + } + _ = sel + _ = ctx + res := graphql.MarshalString(string(*v)) + return res +} + +func (ec *executionContext) marshalOExecution2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐExecution(ctx context.Context, sel ast.SelectionSet, v *store.Execution) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Execution(ctx, sel, v) +} + +func (ec *executionContext) marshalOFunction2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionWithActiveVersion(ctx context.Context, sel ast.SelectionSet, v *store.FunctionWithActiveVersion) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Function(ctx, sel, v) +} + +func (ec *executionContext) marshalOFunctionVersion2ᚖgithubᚗcomᚋdimiro1ᚋlunarᚋinternalᚋstoreᚐFunctionVersion(ctx context.Context, sel ast.SelectionSet, v *store.FunctionVersion) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._FunctionVersion(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOInt2ᚖint(ctx context.Context, v any) (*int, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalInt(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.SelectionSet, v *int) graphql.Marshaler { + if v == nil { + return graphql.Null + } + _ = sel + _ = ctx + res := graphql.MarshalInt(*v) + return res +} + +func (ec *executionContext) unmarshalOInt2ᚖint64(ctx context.Context, v any) (*int64, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalInt64(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOInt2ᚖint64(ctx context.Context, sel ast.SelectionSet, v *int64) graphql.Marshaler { + if v == nil { + return graphql.Null + } + _ = sel + _ = ctx + res := graphql.MarshalInt64(*v) + return res +} + +func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v any) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalString(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + _ = sel + _ = ctx + res := graphql.MarshalString(*v) + return res +} + +func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Schema(ctx, sel, v) +} + +func (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := graphql.MarshalSliceConcurrently(ctx, len(v), 0, false, func(ctx context.Context, i int) graphql.Marshaler { + fc := graphql.GetFieldContext(ctx) + fc.Result = &v[i] + return ec.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + }) + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +// endregion ***************************** type.gotpl ***************************** diff --git a/internal/graph/model/models_gen.go b/internal/graph/model/models_gen.go new file mode 100644 index 0000000..74ed0d5 --- /dev/null +++ b/internal/graph/model/models_gen.go @@ -0,0 +1,236 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package model + +import ( + "bytes" + "fmt" + "io" + "strconv" + + "github.com/dimiro1/lunar/internal/store" +) + +// A paginated list of AI requests. +type AIRequestConnection struct { + Nodes []store.AIRequest `json:"nodes"` + PageInfo *store.PaginationInfo `json:"pageInfo"` +} + +// Fields for creating a function and its initial version. +type CreateFunctionInput struct { + Name string `json:"name"` + Description *string `json:"description,omitempty"` + // Lua source code for the initial version. + Code string `json:"code"` +} + +// A single line in a version diff. +type DiffLine struct { + LineType DiffLineType `json:"lineType"` + // Line number in the old version, if present. + OldLine *int `json:"oldLine,omitempty"` + // Line number in the new version, if present. + NewLine *int `json:"newLine,omitempty"` + Content string `json:"content"` +} + +// A paginated list of email requests. +type EmailRequestConnection struct { + Nodes []store.EmailRequest `json:"nodes"` + PageInfo *store.PaginationInfo `json:"pageInfo"` +} + +// A paginated list of executions. +type ExecutionConnection struct { + Nodes []store.Execution `json:"nodes"` + PageInfo *store.PaginationInfo `json:"pageInfo"` +} + +// A paginated list of functions. +type FunctionConnection struct { + // The functions in this page. + Nodes []store.FunctionWithActiveVersion `json:"nodes"` + // Pagination metadata for the list. + PageInfo *store.PaginationInfo `json:"pageInfo"` +} + +// A paginated list of function versions. +type FunctionVersionConnection struct { + // The versions in this page. + Nodes []store.FunctionVersion `json:"nodes"` + // Pagination metadata for the list. + PageInfo *store.PaginationInfo `json:"pageInfo"` +} + +// A single log line emitted during an execution. +type LogEntry struct { + Level LogLevel `json:"level"` + Message string `json:"message"` + CreatedAt int `json:"createdAt"` +} + +// A paginated list of log entries. +type LogEntryConnection struct { + Nodes []LogEntry `json:"nodes"` + PageInfo *store.PaginationInfo `json:"pageInfo"` +} + +type Mutation struct { +} + +// A function's next scheduled run, derived from its cron settings. +type NextRun struct { + // Whether the function has a cron schedule configured. + HasSchedule bool `json:"hasSchedule"` + CronSchedule *string `json:"cronSchedule,omitempty"` + CronStatus *store.CronStatus `json:"cronStatus,omitempty"` + // Whether the schedule exists but is paused. + IsPaused bool `json:"isPaused"` + // Next run time (Unix seconds), if scheduled and active. + NextRun *int `json:"nextRun,omitempty"` + // Human-readable next run time, if scheduled and active. + NextRunHuman *string `json:"nextRunHuman,omitempty"` +} + +type Query struct { +} + +// Fields for updating a function. All fields are optional; providing `code` +// creates a new active version, and changing cron settings reschedules the +// function. +type UpdateFunctionInput struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Code *string `json:"code,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + RetentionDays *int `json:"retentionDays,omitempty"` + CronSchedule *string `json:"cronSchedule,omitempty"` + CronStatus *store.CronStatus `json:"cronStatus,omitempty"` + SaveResponse *bool `json:"saveResponse,omitempty"` +} + +// A line-by-line diff between two versions of a function. +type VersionDiff struct { + OldVersion int `json:"oldVersion"` + NewVersion int `json:"newVersion"` + Lines []DiffLine `json:"lines"` +} + +// The kind of change a diff line represents. +type DiffLineType string + +const ( + DiffLineTypeUnchanged DiffLineType = "unchanged" + DiffLineTypeAdded DiffLineType = "added" + DiffLineTypeRemoved DiffLineType = "removed" +) + +var AllDiffLineType = []DiffLineType{ + DiffLineTypeUnchanged, + DiffLineTypeAdded, + DiffLineTypeRemoved, +} + +func (e DiffLineType) IsValid() bool { + switch e { + case DiffLineTypeUnchanged, DiffLineTypeAdded, DiffLineTypeRemoved: + return true + } + return false +} + +func (e DiffLineType) String() string { + return string(e) +} + +func (e *DiffLineType) UnmarshalGQL(v any) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = DiffLineType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid DiffLineType", str) + } + return nil +} + +func (e DiffLineType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +func (e *DiffLineType) UnmarshalJSON(b []byte) error { + s, err := strconv.Unquote(string(b)) + if err != nil { + return err + } + return e.UnmarshalGQL(s) +} + +func (e DiffLineType) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + e.MarshalGQL(&buf) + return buf.Bytes(), nil +} + +// Severity of a log entry. +type LogLevel string + +const ( + LogLevelDebug LogLevel = "debug" + LogLevelInfo LogLevel = "info" + LogLevelWarn LogLevel = "warn" + LogLevelError LogLevel = "error" +) + +var AllLogLevel = []LogLevel{ + LogLevelDebug, + LogLevelInfo, + LogLevelWarn, + LogLevelError, +} + +func (e LogLevel) IsValid() bool { + switch e { + case LogLevelDebug, LogLevelInfo, LogLevelWarn, LogLevelError: + return true + } + return false +} + +func (e LogLevel) String() string { + return string(e) +} + +func (e *LogLevel) UnmarshalGQL(v any) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = LogLevel(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid LogLevel", str) + } + return nil +} + +func (e LogLevel) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +func (e *LogLevel) UnmarshalJSON(b []byte) error { + s, err := strconv.Unquote(string(b)) + if err != nil { + return err + } + return e.UnmarshalGQL(s) +} + +func (e LogLevel) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + e.MarshalGQL(&buf) + return buf.Bytes(), nil +} diff --git a/internal/graph/model/scalars.go b/internal/graph/model/scalars.go new file mode 100644 index 0000000..34d6599 --- /dev/null +++ b/internal/graph/model/scalars.go @@ -0,0 +1,53 @@ +package model + +import ( + "encoding/json" + "fmt" + "io" +) + +// StringMap is the Go type backing the GraphQL `Map` scalar: an arbitrary +// string→string mapping serialized as a JSON object. It is used for environment +// variables and key/value store entries, matching the JSON shape the REST API +// exposed today. +// +// This file is hand-written; gqlgen binds the `Map` scalar to it via gqlgen.yml +// and never regenerates it. +type StringMap map[string]string + +// MarshalGQL writes the map as a compact JSON object. encoding/json sorts string +// keys, so the output is deterministic. +func (m StringMap) MarshalGQL(w io.Writer) { + if m == nil { + _, _ = io.WriteString(w, "{}") + return + } + b, err := json.Marshal(map[string]string(m)) + if err != nil { + _, _ = io.WriteString(w, "{}") + return + } + _, _ = w.Write(b) +} + +// UnmarshalGQL accepts a JSON object with string values (the shape produced when +// a `Map` is supplied as a GraphQL input) and populates the map. +func (m *StringMap) UnmarshalGQL(v any) error { + switch val := v.(type) { + case map[string]string: + *m = val + case map[string]any: + out := make(StringMap, len(val)) + for k, raw := range val { + s, ok := raw.(string) + if !ok { + return fmt.Errorf("invalid Map value for key %q: must be a string, got %T", k, raw) + } + out[k] = s + } + *m = out + default: + return fmt.Errorf("invalid Map: must be an object, got %T", v) + } + return nil +} diff --git a/internal/graph/module.go b/internal/graph/module.go new file mode 100644 index 0000000..e164a37 --- /dev/null +++ b/internal/graph/module.go @@ -0,0 +1,70 @@ +package graph + +import ( + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/extension" + "github.com/99designs/gqlgen/graphql/handler/lru" + "github.com/99designs/gqlgen/graphql/handler/transport" + internalcron "github.com/dimiro1/lunar/internal/cron" + "github.com/dimiro1/lunar/internal/services/ai" + "github.com/dimiro1/lunar/internal/services/email" + "github.com/dimiro1/lunar/internal/services/env" + "github.com/dimiro1/lunar/internal/services/kv" + "github.com/dimiro1/lunar/internal/services/logger" + "github.com/dimiro1/lunar/internal/store" + "github.com/vektah/gqlparser/v2/ast" + "go.uber.org/fx" +) + +// Module provides the GraphQL resolver root and the gqlgen HTTP handler. The +// handler is consumed by the api module, which mounts it at /graphql; this +// module deliberately owns no lifecycle of its own. +var Module = fx.Module("graphql", + fx.Provide( + newResolver, + NewServer, + ), +) + +// resolverParams gathers the resolver's dependencies from the fx graph. +type resolverParams struct { + fx.In + + DB store.DB + EnvStore env.Store + KVStore kv.Store + Scheduler *internalcron.FunctionScheduler + Logger logger.Logger + AITracker ai.Tracker + EmailTracker email.Tracker +} + +// newResolver builds the root resolver from its injected dependencies. New +// resolver dependencies are added as fields on Resolver and on resolverParams. +func newResolver(p resolverParams) *Resolver { + return &Resolver{ + DB: p.DB, + EnvStore: p.EnvStore, + KVStore: p.KVStore, + Scheduler: p.Scheduler, + Logger: p.Logger, + AITracker: p.AITracker, + EmailTracker: p.EmailTracker, + } +} + +// NewServer assembles the gqlgen HTTP handler from the executable schema. It +// enables the GET and POST transports, an LRU query cache, and schema +// introspection (used by the playground and by generated clients). +func NewServer(r *Resolver) *handler.Server { + srv := handler.New(NewExecutableSchema(Config{Resolvers: r})) + + srv.AddTransport(transport.GET{}) + srv.AddTransport(transport.POST{}) + + srv.SetQueryCache(lru.New[*ast.QueryDocument](1000)) + + srv.Use(extension.Introspection{}) + + return srv +} diff --git a/internal/graph/resolver.go b/internal/graph/resolver.go new file mode 100644 index 0000000..de95449 --- /dev/null +++ b/internal/graph/resolver.go @@ -0,0 +1,225 @@ +package graph + +import ( + "context" + "errors" + "fmt" + + internalcron "github.com/dimiro1/lunar/internal/cron" + "github.com/dimiro1/lunar/internal/graph/model" + "github.com/dimiro1/lunar/internal/services/ai" + "github.com/dimiro1/lunar/internal/services/email" + "github.com/dimiro1/lunar/internal/services/env" + "github.com/dimiro1/lunar/internal/services/kv" + "github.com/dimiro1/lunar/internal/services/logger" + "github.com/dimiro1/lunar/internal/store" +) + +//go:generate go tool gqlgen generate + +// Resolver is the root resolver and the injection point for the dependencies the +// GraphQL resolvers need. gqlgen wires the generated Query/Mutation resolvers to +// this struct; fields added here are reachable from every resolver method. +// +// It is hand-written (gqlgen will not overwrite an existing resolver.go), so new +// dependencies are added by extending this struct and the fx provider in +// module.go. +type Resolver struct { + DB store.DB + EnvStore env.Store + KVStore kv.Store + Scheduler *internalcron.FunctionScheduler + Logger logger.Logger + AITracker ai.Tracker + EmailTracker email.Tracker +} + +// paginationParams builds normalized pagination parameters from optional +// GraphQL limit/offset arguments (which default via the schema but may be null). +func paginationParams(limit, offset *int) store.PaginationParams { + p := store.PaginationParams{} + if limit != nil { + p.Limit = *limit + } + if offset != nil { + p.Offset = *offset + } + return p.Normalize() +} + +// pageInfo builds the PageInfo for a paginated response. +func pageInfo(total int64, p store.PaginationParams) *store.PaginationInfo { + return &store.PaginationInfo{Total: total, Limit: p.Limit, Offset: p.Offset} +} + +// loadFunction fetches a function together with its active version. It returns +// (nil, nil) when the function does not exist, which Query.function surfaces as +// a null result. +func (r *Resolver) loadFunction(ctx context.Context, id string) (*store.FunctionWithActiveVersion, error) { + fn, err := r.DB.GetFunction(ctx, id) + if err != nil { + if errors.Is(err, store.ErrFunctionNotFound) { + return nil, nil + } + return nil, err + } + active, err := r.DB.GetActiveVersion(ctx, id) + if err != nil { + return nil, err + } + return &store.FunctionWithActiveVersion{Function: fn, ActiveVersion: active}, nil +} + +// reloadFunction is loadFunction for non-null results: mutations use it to return +// the affected function, treating a missing function as an error. +func (r *Resolver) reloadFunction(ctx context.Context, id string) (*store.FunctionWithActiveVersion, error) { + fn, err := r.loadFunction(ctx, id) + if err != nil { + return nil, err + } + if fn == nil { + return nil, fmt.Errorf("function %q not found", id) + } + return fn, nil +} + +// cronStatusEnum converts the store's *string cron status into the CronStatus +// enum, mapping nil or empty (no schedule configured) to null. +func cronStatusEnum(s *string) *store.CronStatus { + if s == nil || *s == "" { + return nil + } + cs := store.CronStatus(*s) + return &cs +} + +// cronStatusString is the inverse of cronStatusEnum: it converts a CronStatus +// enum back to the *string the store layer expects. +func cronStatusString(c *store.CronStatus) *string { + if c == nil { + return nil + } + s := string(*c) + return &s +} + +// loadExecution fetches an execution by ID, returning (nil, nil) when it does +// not exist so reverse edges (AIRequest.execution, …) resolve to null. +func (r *Resolver) loadExecution(ctx context.Context, id string) (*store.Execution, error) { + exec, err := r.DB.GetExecution(ctx, id) + if err != nil { + if errors.Is(err, store.ErrExecutionNotFound) { + return nil, nil + } + return nil, err + } + return &exec, nil +} + +// loadVersionByID fetches a version by its ID, returning (nil, nil) when it does +// not exist so Execution.version resolves to null for a deleted version. +func (r *Resolver) loadVersionByID(ctx context.Context, versionID string) (*store.FunctionVersion, error) { + v, err := r.DB.GetVersionByID(ctx, versionID) + if err != nil { + if errors.Is(err, store.ErrVersionNotFound) { + return nil, nil + } + return nil, err + } + return &v, nil +} + +// executionConnection lists a function's executions as a paginated connection. +// Shared by the top-level executions query and Function.executions. +func (r *Resolver) executionConnection(ctx context.Context, functionID string, limit, offset *int) (*model.ExecutionConnection, error) { + params := paginationParams(limit, offset) + executions, total, err := r.DB.ListExecutions(ctx, functionID, params) + if err != nil { + return nil, err + } + return &model.ExecutionConnection{Nodes: executions, PageInfo: pageInfo(total, params)}, nil +} + +// logEntryConnection builds a paginated LogEntryConnection for an execution. +// Shared by the top-level executionLogs query and Execution.logs. +func (r *Resolver) logEntryConnection(executionID string, limit, offset *int) *model.LogEntryConnection { + params := paginationParams(limit, offset) + entries, total := r.Logger.EntriesPaginated(executionID, params.Limit, params.Offset) + nodes := make([]model.LogEntry, len(entries)) + for i, e := range entries { + nodes[i] = model.LogEntry{ + Level: mapLogLevel(e.Level), + Message: e.Message, + CreatedAt: int(e.Timestamp), + } + } + return &model.LogEntryConnection{Nodes: nodes, PageInfo: pageInfo(total, params)} +} + +// aiRequestConnection builds a paginated AIRequestConnection for an execution. +// Shared by the top-level executionAiRequests query and Execution.aiRequests. +func (r *Resolver) aiRequestConnection(executionID string, limit, offset *int) *model.AIRequestConnection { + params := paginationParams(limit, offset) + requests, total := r.AITracker.RequestsPaginated(executionID, params.Limit, params.Offset) + return &model.AIRequestConnection{Nodes: requests, PageInfo: pageInfo(total, params)} +} + +// emailRequestConnection builds a paginated EmailRequestConnection for an +// execution. Shared by executionEmailRequests and Execution.emailRequests. +func (r *Resolver) emailRequestConnection(executionID string, limit, offset *int) *model.EmailRequestConnection { + params := paginationParams(limit, offset) + requests, total := r.EmailTracker.RequestsPaginated(executionID, params.Limit, params.Offset) + return &model.EmailRequestConnection{Nodes: requests, PageInfo: pageInfo(total, params)} +} + +// computeNextRun derives a function's next scheduled run from its cron settings. +// Shared by the top-level nextRun query and Function.nextRun. +func computeNextRun(fn store.Function) (*model.NextRun, error) { + if fn.CronSchedule == nil || *fn.CronSchedule == "" { + return &model.NextRun{HasSchedule: false}, nil + } + + if fn.CronStatus == nil || *fn.CronStatus != string(store.CronStatusActive) { + return &model.NextRun{ + HasSchedule: true, + CronSchedule: fn.CronSchedule, + CronStatus: cronStatusEnum(fn.CronStatus), + IsPaused: true, + }, nil + } + + nextRun, err := internalcron.GetNextRunFromSchedule(*fn.CronSchedule) + if err != nil { + return nil, err + } + + out := &model.NextRun{ + HasSchedule: true, + CronSchedule: fn.CronSchedule, + CronStatus: cronStatusEnum(fn.CronStatus), + IsPaused: false, + } + if nextRun != nil { + unix := int(nextRun.Unix()) + human := internalcron.FormatNextRun(*nextRun) + out.NextRun = &unix + out.NextRunHuman = &human + } + return out, nil +} + +// mapLogLevel converts a logger severity to the GraphQL LogLevel enum. +func mapLogLevel(l logger.LogLevel) model.LogLevel { + switch l { + case logger.Debug: + return model.LogLevelDebug + case logger.Info: + return model.LogLevelInfo + case logger.Warn: + return model.LogLevelWarn + case logger.Error: + return model.LogLevelError + default: + return model.LogLevelInfo + } +} diff --git a/internal/graph/resolver_test.go b/internal/graph/resolver_test.go new file mode 100644 index 0000000..ed91ffc --- /dev/null +++ b/internal/graph/resolver_test.go @@ -0,0 +1,321 @@ +package graph_test + +import ( + "context" + "maps" + "testing" + + "github.com/99designs/gqlgen/client" + "github.com/dimiro1/lunar/internal/graph" + "github.com/dimiro1/lunar/internal/services/env" + "github.com/dimiro1/lunar/internal/services/kv" + "github.com/dimiro1/lunar/internal/store" +) + +// fakeEnvStore is an in-memory env.Store that also records how often All is +// called, so tests can assert the env store is untouched unless envVars is +// selected. Unused interface methods are inherited from the embedded nil. +type fakeEnvStore struct { + env.Store + vars map[string]string + allCalls int +} + +func (f *fakeEnvStore) Set(_, key, value string) error { f.vars[key] = value; return nil } +func (f *fakeEnvStore) Delete(_, key string) error { delete(f.vars, key); return nil } +func (f *fakeEnvStore) All(string) (map[string]string, error) { + f.allCalls++ + return maps.Clone(f.vars), nil +} + +// fakeKVStore is an in-memory kv.Store keyed by scope ("" == global) that records +// All / AllGlobal calls. +type fakeKVStore struct { + kv.Store + data map[string]map[string]string + allCalls int + allGlobalCalls int +} + +func (f *fakeKVStore) scope(s string) map[string]string { + if f.data[s] == nil { + f.data[s] = map[string]string{} + } + return f.data[s] +} +func (f *fakeKVStore) Set(functionID, key, value string) error { f.scope(functionID)[key] = value; return nil } +func (f *fakeKVStore) Delete(functionID, key string) error { delete(f.scope(functionID), key); return nil } +func (f *fakeKVStore) All(functionID string) (map[string]string, error) { + f.allCalls++ + return maps.Clone(f.scope(functionID)), nil +} +func (f *fakeKVStore) AllGlobal() (map[string]string, error) { + f.allGlobalCalls++ + return maps.Clone(f.scope("")), nil +} + +// newTestClient builds the real gqlgen server (same constructor used in +// production wiring) backed by an in-memory store and counting env/kv fakes, so +// these tests exercise the schema → resolver → store path end to end without +// HTTP or auth. +func newTestClient(t *testing.T) (*client.Client, store.DB, *fakeEnvStore, *fakeKVStore) { + t.Helper() + db := store.NewMemoryDB() + envStore := &fakeEnvStore{vars: map[string]string{}} + kvStore := &fakeKVStore{data: map[string]map[string]string{}} + srv := graph.NewServer(&graph.Resolver{DB: db, EnvStore: envStore, KVStore: kvStore}) + return client.New(srv), db, envStore, kvStore +} + +func seedFunction(t *testing.T, db store.DB, id, name, code string) { + t.Helper() + ctx := context.Background() + if _, err := db.CreateFunction(ctx, store.Function{ID: id, Name: name}); err != nil { + t.Fatalf("CreateFunction(%q): %v", id, err) + } + if _, err := db.CreateVersion(ctx, id, code, nil); err != nil { + t.Fatalf("CreateVersion(%q): %v", id, err) + } +} + +func TestFunctionsQuery(t *testing.T) { + c, db, _, _ := newTestClient(t) + seedFunction(t, db, "fn1", "hello", "return 1") + + var resp struct { + Functions struct { + Nodes []struct { + ID string + Name string + ActiveVersion struct { + Version int + Code string + IsActive bool + } + } + PageInfo struct { + Total int + Limit int + Offset int + } + } + } + + c.MustPost(`{ + functions { + nodes { id name activeVersion { version code isActive } } + pageInfo { total limit offset } + } + }`, &resp) + + if got := resp.Functions.PageInfo.Total; got != 1 { + t.Fatalf("pageInfo.total = %d, want 1", got) + } + if got := resp.Functions.PageInfo.Limit; got != 20 { + t.Errorf("pageInfo.limit = %d, want default 20", got) + } + if n := len(resp.Functions.Nodes); n != 1 { + t.Fatalf("got %d nodes, want 1", n) + } + node := resp.Functions.Nodes[0] + if node.ID != "fn1" || node.Name != "hello" { + t.Errorf("node = {id:%q name:%q}, want {fn1 hello}", node.ID, node.Name) + } + if node.ActiveVersion.Code != "return 1" || !node.ActiveVersion.IsActive { + t.Errorf("activeVersion = %+v, want code=%q isActive=true", node.ActiveVersion, "return 1") + } +} + +func TestVersionsQuery(t *testing.T) { + c, db, _, _ := newTestClient(t) + seedFunction(t, db, "fn1", "hello", "return 1") + + var resp struct { + Versions struct { + Nodes []struct { + Version int + Code string + IsActive bool + } + PageInfo struct{ Total int } + } + } + + c.MustPost(`{ + versions(functionId: "fn1") { + nodes { version code isActive } + pageInfo { total } + } + }`, &resp) + + if got := resp.Versions.PageInfo.Total; got != 1 { + t.Fatalf("versions total = %d, want 1", got) + } + if n := len(resp.Versions.Nodes); n != 1 { + t.Fatalf("got %d versions, want 1", n) + } + if v := resp.Versions.Nodes[0]; v.Version != 1 || v.Code != "return 1" || !v.IsActive { + t.Errorf("version = %+v, want {1 \"return 1\" true}", v) + } +} + +// TestGraphEdges exercises the relation edges that let the graph be traversed in +// both directions: Function.versions[].function (reverse), Function.executions, +// Function.nextRun, Execution.function, and Execution.version. The logs/AI/email +// edges need the logger/trackers (covered by live verification) and are omitted +// here, where only the DB is wired. +func TestGraphEdges(t *testing.T) { + c, db, _, _ := newTestClient(t) + ctx := context.Background() + if _, err := db.CreateFunction(ctx, store.Function{ID: "fn1", Name: "edges"}); err != nil { + t.Fatalf("CreateFunction: %v", err) + } + ver, err := db.CreateVersion(ctx, "fn1", "return 1", nil) + if err != nil { + t.Fatalf("CreateVersion: %v", err) + } + if _, err := db.CreateExecution(ctx, store.Execution{ + ID: "ex1", + FunctionID: "fn1", + FunctionVersionID: ver.ID, + Status: store.ExecutionStatus("success"), + Trigger: store.ExecutionTriggerHTTP, + }); err != nil { + t.Fatalf("CreateExecution: %v", err) + } + + var resp struct { + Function struct { + Name string + NextRun struct{ HasSchedule bool } + Versions struct { + Nodes []struct { + Version int + Function struct{ ID, Name string } + } + } + Executions struct { + Nodes []struct { + ID string + Function struct{ ID string } + Version struct { + ID string + Version int + } + } + } + } + } + + c.MustPost(`{ + function(id: "fn1") { + name + nextRun { hasSchedule } + versions { nodes { version function { id name } } } + executions { nodes { id function { id } version { id version } } } + } + }`, &resp) + + f := resp.Function + if f.NextRun.HasSchedule { + t.Error("nextRun.hasSchedule = true, want false (no cron configured)") + } + if n := len(f.Versions.Nodes); n != 1 { + t.Fatalf("got %d versions, want 1", n) + } + if fn := f.Versions.Nodes[0].Function; fn.ID != "fn1" || fn.Name != "edges" { + t.Errorf("versions[0].function (reverse edge) = %+v, want {fn1 edges}", fn) + } + if n := len(f.Executions.Nodes); n != 1 { + t.Fatalf("got %d executions, want 1", n) + } + e := f.Executions.Nodes[0] + if e.ID != "ex1" { + t.Errorf("executions[0].id = %q, want ex1", e.ID) + } + if e.Function.ID != "fn1" { + t.Errorf("execution.function.id = %q, want fn1", e.Function.ID) + } + if e.Version.ID != ver.ID || e.Version.Version != 1 { + t.Errorf("execution.version = %+v, want {%s 1}", e.Version, ver.ID) + } +} + +func TestFunctionEnvKvLazy(t *testing.T) { + c, db, envStore, kvStore := newTestClient(t) + envStore.vars = map[string]string{"API_KEY": "secret"} + kvStore.data = map[string]map[string]string{ + "fn1": {"counter": "1"}, + "": {"shared": "x"}, + } + seedFunction(t, db, "fn1", "hello", "return 1") + + // Selecting only scalar fields must NOT touch the env/kv stores — this is the + // overfetch fix: the list/detail view pays for env/kv only when it asks. + var bare struct { + Function *struct { + ID string + Name string + } + } + c.MustPost(`{ function(id: "fn1") { id name } }`, &bare) + if envStore.allCalls != 0 || kvStore.allCalls != 0 || kvStore.allGlobalCalls != 0 { + t.Fatalf("scalar-only query touched stores; env=%d kvScoped=%d kvGlobal=%d, want all 0", + envStore.allCalls, kvStore.allCalls, kvStore.allGlobalCalls) + } + + // Selecting the map fields fetches them lazily, exactly once each. + var withMaps struct { + Function *struct { + EnvVars map[string]string + ScopedData map[string]string + GlobalData map[string]string + } + } + c.MustPost(`{ function(id: "fn1") { envVars scopedData globalData } }`, &withMaps) + if withMaps.Function == nil { + t.Fatal("function(fn1) = nil") + } + if got := withMaps.Function.EnvVars["API_KEY"]; got != "secret" { + t.Errorf("envVars[API_KEY] = %q, want secret", got) + } + if got := withMaps.Function.ScopedData["counter"]; got != "1" { + t.Errorf("scopedData[counter] = %q, want 1", got) + } + if got := withMaps.Function.GlobalData["shared"]; got != "x" { + t.Errorf("globalData[shared] = %q, want x", got) + } + if envStore.allCalls != 1 || kvStore.allCalls != 1 || kvStore.allGlobalCalls != 1 { + t.Errorf("expected one lookup each; got env=%d kvScoped=%d kvGlobal=%d", + envStore.allCalls, kvStore.allCalls, kvStore.allGlobalCalls) + } +} + +func TestFunctionByID(t *testing.T) { + c, db, _, _ := newTestClient(t) + seedFunction(t, db, "fn1", "hello", "return 1") + + var resp struct { + Function *struct { + ID string + ActiveVersion struct{ Code string } + } + Missing *struct{ ID string } + } + + c.MustPost(`{ + function(id: "fn1") { id activeVersion { code } } + missing: function(id: "does-not-exist") { id } + }`, &resp) + + if resp.Function == nil { + t.Fatal("function(fn1) = nil, want a result") + } + if resp.Function.ID != "fn1" || resp.Function.ActiveVersion.Code != "return 1" { + t.Errorf("function = %+v, want id=fn1 code=%q", resp.Function, "return 1") + } + // A missing function resolves to null rather than erroring. + if resp.Missing != nil { + t.Errorf("missing function = %+v, want nil", resp.Missing) + } +} diff --git a/internal/graph/schema/common.graphqls b/internal/graph/schema/common.graphqls new file mode 100644 index 0000000..28d29cc --- /dev/null +++ b/internal/graph/schema/common.graphqls @@ -0,0 +1,23 @@ +# Shared types used across the whole schema. +# +# The schema is split into one file per domain (functions, versions, …). Because +# gqlgen uses the follow-schema layout, each .graphqls produces its own +# .resolvers.go — so no single resolver file grows unbounded. +# +# Timestamps are Unix epoch seconds carried as `Int`. gqlgen.yml binds `Int` to +# both graphql.Int and graphql.Int64, so the underlying int64 values round-trip +# at full width (no 32-bit truncation). A dedicated `Timestamp` scalar would add +# semantic clarity but no correctness — it is intentionally not introduced. + +"""An arbitrary string→string mapping, serialized as a JSON object.""" +scalar Map + +"""Pagination metadata shared by all paginated lists.""" +type PageInfo { + """Total number of items across all pages.""" + total: Int! + """Maximum number of items requested per page.""" + limit: Int! + """Number of items skipped before this page.""" + offset: Int! +} diff --git a/internal/graph/schema/executions.graphqls b/internal/graph/schema/executions.graphqls new file mode 100644 index 0000000..e2fccac --- /dev/null +++ b/internal/graph/schema/executions.graphqls @@ -0,0 +1,167 @@ +# Executions domain: execution records and their logs, AI requests, email +# requests, plus a function's next scheduled run. + +"""The outcome of a function execution.""" +enum ExecutionStatus { + pending + success + error +} + +"""How an execution was triggered.""" +enum ExecutionTrigger { + http + cron +} + +"""A record of a single function execution.""" +type Execution { + id: ID! + functionId: ID! + functionVersionId: ID! + status: ExecutionStatus! + """Wall-clock duration in milliseconds, if the execution finished.""" + durationMs: Int + errorMessage: String + """JSON-encoded event the function received.""" + eventJson: String + """JSON-encoded response the function returned, if persisted.""" + responseJson: String + trigger: ExecutionTrigger! + createdAt: Int! + """ + The function this execution belongs to, resolved from functionId. Lets a + single query fetch an execution together with its parent function (e.g. for + the execution-detail view) instead of a second round-trip. Null if the + function has since been deleted. + """ + function: Function + """The specific function version that produced this execution, or null if it + has since been deleted.""" + version: FunctionVersion + """Log entries emitted during this execution. Fetched lazily.""" + logs(limit: Int = 20, offset: Int = 0): LogEntryConnection! + """AI provider requests made during this execution. Fetched lazily.""" + aiRequests(limit: Int = 20, offset: Int = 0): AIRequestConnection! + """Email send requests made during this execution. Fetched lazily.""" + emailRequests(limit: Int = 20, offset: Int = 0): EmailRequestConnection! +} + +"""A paginated list of executions.""" +type ExecutionConnection { + nodes: [Execution!]! + pageInfo: PageInfo! +} + +"""Severity of a log entry.""" +enum LogLevel { + debug + info + warn + error +} + +"""A single log line emitted during an execution.""" +type LogEntry { + level: LogLevel! + message: String! + createdAt: Int! +} + +"""A paginated list of log entries.""" +type LogEntryConnection { + nodes: [LogEntry!]! + pageInfo: PageInfo! +} + +"""The outcome of an AI provider request.""" +enum AIRequestStatus { + success + error +} + +"""A tracked AI provider request made during an execution.""" +type AIRequest { + id: ID! + executionId: ID! + provider: String! + model: String! + endpoint: String! + requestJson: String! + responseJson: String + status: AIRequestStatus! + errorMessage: String + inputTokens: Int + outputTokens: Int + durationMs: Int! + createdAt: Int! + """The execution during which this AI request was made, or null if deleted.""" + execution: Execution +} + +"""A paginated list of AI requests.""" +type AIRequestConnection { + nodes: [AIRequest!]! + pageInfo: PageInfo! +} + +"""The outcome of an email send request.""" +enum EmailRequestStatus { + success + error +} + +"""A tracked email send request made during an execution.""" +type EmailRequest { + id: ID! + executionId: ID! + from: String! + to: [String!]! + subject: String! + hasText: Boolean! + hasHtml: Boolean! + requestJson: String! + responseJson: String + status: EmailRequestStatus! + errorMessage: String + emailId: String + durationMs: Int! + createdAt: Int! + """The execution during which this email request was made, or null if deleted.""" + execution: Execution +} + +"""A paginated list of email requests.""" +type EmailRequestConnection { + nodes: [EmailRequest!]! + pageInfo: PageInfo! +} + +"""A function's next scheduled run, derived from its cron settings.""" +type NextRun { + """Whether the function has a cron schedule configured.""" + hasSchedule: Boolean! + cronSchedule: String + cronStatus: CronStatus + """Whether the schedule exists but is paused.""" + isPaused: Boolean! + """Next run time (Unix seconds), if scheduled and active.""" + nextRun: Int + """Human-readable next run time, if scheduled and active.""" + nextRunHuman: String +} + +extend type Query { + """List a function's executions, newest first.""" + executions(functionId: ID!, limit: Int = 20, offset: Int = 0): ExecutionConnection! + """Fetch a single execution by ID, or null if it does not exist.""" + execution(id: ID!): Execution + """List the log entries emitted by an execution.""" + executionLogs(executionId: ID!, limit: Int = 20, offset: Int = 0): LogEntryConnection! + """List the AI requests made during an execution.""" + executionAiRequests(executionId: ID!, limit: Int = 20, offset: Int = 0): AIRequestConnection! + """List the email requests made during an execution.""" + executionEmailRequests(executionId: ID!, limit: Int = 20, offset: Int = 0): EmailRequestConnection! + """Compute the next scheduled run for a function.""" + nextRun(functionId: ID!): NextRun! +} diff --git a/internal/graph/schema/functions.graphqls b/internal/graph/schema/functions.graphqls new file mode 100644 index 0000000..e1e299b --- /dev/null +++ b/internal/graph/schema/functions.graphqls @@ -0,0 +1,105 @@ +# Functions domain: the function entity and its read queries. + +"""The status of a function's cron schedule.""" +enum CronStatus { + active + paused +} + +"""A serverless Lua function and its currently active version.""" +type Function { + """Unique function identifier.""" + id: ID! + """Human-readable function name.""" + name: String! + """Optional description of what the function does.""" + description: String + """Whether the function is disabled (will not execute).""" + disabled: Boolean! + """Number of days execution history is retained, if set.""" + retentionDays: Int + """Cron expression for scheduled execution, if configured.""" + cronSchedule: String + """Status of the cron schedule, if configured.""" + cronStatus: CronStatus + """Whether responses from executions are persisted.""" + saveResponse: Boolean! + """Creation time (Unix seconds).""" + createdAt: Int! + """Last update time (Unix seconds).""" + updatedAt: Int! + """The version currently served when the function is invoked.""" + activeVersion: FunctionVersion! + """ + All versions of this function, newest first. Paginated and fetched lazily — + only queries that select it read the version store. + """ + versions(limit: Int = 20, offset: Int = 0): FunctionVersionConnection! + """ + This function's executions, newest first. Paginated and fetched lazily. + """ + executions(limit: Int = 20, offset: Int = 0): ExecutionConnection! + """The function's next scheduled run, derived from its cron settings.""" + nextRun: NextRun! + """ + Environment variables available to the function at runtime. Fetched lazily — + only queries that select this field read the env store. + """ + envVars: Map! + """Function-scoped key/value store entries. Fetched lazily.""" + scopedData: Map! + """Global key/value store entries shared across all functions. Fetched lazily.""" + globalData: Map! +} + +"""A paginated list of functions.""" +type FunctionConnection { + """The functions in this page.""" + nodes: [Function!]! + """Pagination metadata for the list.""" + pageInfo: PageInfo! +} + +type Query { + """List functions with their active version, newest first.""" + functions(limit: Int = 20, offset: Int = 0): FunctionConnection! + """Fetch a single function by ID, or null if it does not exist.""" + function(id: ID!): Function +} + +"""Fields for creating a function and its initial version.""" +input CreateFunctionInput { + name: String! + description: String + """Lua source code for the initial version.""" + code: String! +} + +""" +Fields for updating a function. All fields are optional; providing `code` +creates a new active version, and changing cron settings reschedules the +function. +""" +input UpdateFunctionInput { + name: String + description: String + code: String + disabled: Boolean + retentionDays: Int + cronSchedule: String + cronStatus: CronStatus + saveResponse: Boolean +} + +type Mutation { + """Create a function with an initial version.""" + createFunction(input: CreateFunctionInput!): Function! + """Update function metadata and/or create a new version from `code`.""" + updateFunction(id: ID!, input: UpdateFunctionInput!): Function! + """Delete a function and all of its associated data. Returns true on success.""" + deleteFunction(id: ID!): Boolean! + """Replace the function's environment variables with the given set.""" + setFunctionEnv(id: ID!, env: Map!): Function! + """Replace function-scoped (or global) KV entries with the given set.""" + setFunctionKv(id: ID!, kv: Map!, global: Boolean = false): Function! +} diff --git a/internal/graph/schema/tokens.graphqls b/internal/graph/schema/tokens.graphqls new file mode 100644 index 0000000..eeeb2b1 --- /dev/null +++ b/internal/graph/schema/tokens.graphqls @@ -0,0 +1,21 @@ +# API tokens domain: management of tokens used by the CLI / connected clients. + +"""An API token issued to a connected client (e.g. the CLI).""" +type APIToken { + id: ID! + name: String! + createdAt: Int! + """Last time the token was used (Unix seconds), if ever.""" + lastUsed: Int + revoked: Boolean! +} + +extend type Query { + """List all API tokens, newest first.""" + apiTokens: [APIToken!]! +} + +extend type Mutation { + """Revoke an API token. Returns true on success.""" + revokeApiToken(id: ID!): Boolean! +} diff --git a/internal/graph/schema/versions.graphqls b/internal/graph/schema/versions.graphqls new file mode 100644 index 0000000..43c2e29 --- /dev/null +++ b/internal/graph/schema/versions.graphqls @@ -0,0 +1,70 @@ +# Versions domain: immutable per-function code versions and their read queries. + +"""A specific, immutable version of a function's source code.""" +type FunctionVersion { + """Unique version identifier.""" + id: ID! + """ID of the function this version belongs to.""" + functionId: ID! + """Monotonic version number within the function.""" + version: Int! + """The Lua source code for this version.""" + code: String! + """Creation time (Unix seconds).""" + createdAt: Int! + """Identifier of the actor that created this version, if known.""" + createdBy: String + """Whether this is the function's active version.""" + isActive: Boolean! + """The function this version belongs to, or null if it has since been + deleted.""" + function: Function +} + +"""A paginated list of function versions.""" +type FunctionVersionConnection { + """The versions in this page.""" + nodes: [FunctionVersion!]! + """Pagination metadata for the list.""" + pageInfo: PageInfo! +} + +"""The kind of change a diff line represents.""" +enum DiffLineType { + unchanged + added + removed +} + +"""A single line in a version diff.""" +type DiffLine { + lineType: DiffLineType! + """Line number in the old version, if present.""" + oldLine: Int + """Line number in the new version, if present.""" + newLine: Int + content: String! +} + +"""A line-by-line diff between two versions of a function.""" +type VersionDiff { + oldVersion: Int! + newVersion: Int! + lines: [DiffLine!]! +} + +extend type Query { + """List a function's versions, newest first.""" + versions(functionId: ID!, limit: Int = 20, offset: Int = 0): FunctionVersionConnection! + """Fetch a single version by function ID and version number, or null if absent.""" + version(functionId: ID!, version: Int!): FunctionVersion + """Compute the diff between two versions of a function.""" + versionDiff(functionId: ID!, oldVersion: Int!, newVersion: Int!): VersionDiff! +} + +extend type Mutation { + """Make the given version the function's active version; returns the function.""" + activateVersion(functionId: ID!, versionId: ID!): Function! + """Delete a version (the active version cannot be deleted). Returns true on success.""" + deleteVersion(functionId: ID!, versionId: ID!): Boolean! +} diff --git a/internal/graph/tokens.resolvers.go b/internal/graph/tokens.resolvers.go new file mode 100644 index 0000000..9955787 --- /dev/null +++ b/internal/graph/tokens.resolvers.go @@ -0,0 +1,26 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver +// implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.90 + +import ( + "context" + + "github.com/dimiro1/lunar/internal/store" +) + +// RevokeAPIToken is the resolver for the revokeApiToken field. +func (r *mutationResolver) RevokeAPIToken(ctx context.Context, id string) (bool, error) { + if err := r.DB.RevokeAPIToken(ctx, id); err != nil { + return false, err + } + return true, nil +} + +// APITokens is the resolver for the apiTokens field. A nil slice marshals as an +// empty list, matching the non-null [APIToken!]! return type. +func (r *queryResolver) APITokens(ctx context.Context) ([]store.APIToken, error) { + return r.DB.ListAPITokens(ctx) +} diff --git a/internal/graph/versions.resolvers.go b/internal/graph/versions.resolvers.go new file mode 100644 index 0000000..ef77411 --- /dev/null +++ b/internal/graph/versions.resolvers.go @@ -0,0 +1,97 @@ +package graph + +// This file will be automatically regenerated based on the schema, any resolver +// implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.90 + +import ( + "context" + "errors" + + "github.com/dimiro1/lunar/internal/diff" + "github.com/dimiro1/lunar/internal/graph/model" + "github.com/dimiro1/lunar/internal/store" +) + +// Function is the resolver for the function field — the reverse edge from a +// version back to its owning function (null if the function was deleted). +func (r *functionVersionResolver) Function(ctx context.Context, obj *store.FunctionVersion) (*store.FunctionWithActiveVersion, error) { + return r.loadFunction(ctx, obj.FunctionID) +} + +// ActivateVersion is the resolver for the activateVersion field. It returns the +// function so callers get its now-active version in one round-trip. +func (r *mutationResolver) ActivateVersion(ctx context.Context, functionID string, versionID string) (*store.FunctionWithActiveVersion, error) { + if err := r.DB.ActivateVersion(ctx, versionID); err != nil { + return nil, err + } + return r.reloadFunction(ctx, functionID) +} + +// DeleteVersion is the resolver for the deleteVersion field. The active version +// cannot be deleted (the store enforces this). +func (r *mutationResolver) DeleteVersion(ctx context.Context, functionID string, versionID string) (bool, error) { + if err := r.DB.DeleteVersion(ctx, versionID); err != nil { + return false, err + } + return true, nil +} + +// Versions is the resolver for the versions field. +func (r *queryResolver) Versions(ctx context.Context, functionID string, limit *int, offset *int) (*model.FunctionVersionConnection, error) { + params := paginationParams(limit, offset) + versions, total, err := r.DB.ListVersions(ctx, functionID, params) + if err != nil { + return nil, err + } + return &model.FunctionVersionConnection{Nodes: versions, PageInfo: pageInfo(total, params)}, nil +} + +// Version is the resolver for the version field. +func (r *queryResolver) Version(ctx context.Context, functionID string, version int) (*store.FunctionVersion, error) { + v, err := r.DB.GetVersion(ctx, functionID, version) + if err != nil { + // A missing version is a null result in GraphQL, not an error. + if errors.Is(err, store.ErrVersionNotFound) { + return nil, nil + } + return nil, err + } + + return &v, nil +} + +// VersionDiff is the resolver for the versionDiff field. +func (r *queryResolver) VersionDiff(ctx context.Context, functionID string, oldVersion int, newVersion int) (*model.VersionDiff, error) { + v1, err := r.DB.GetVersion(ctx, functionID, oldVersion) + if err != nil { + return nil, err + } + v2, err := r.DB.GetVersion(ctx, functionID, newVersion) + if err != nil { + return nil, err + } + + result := diff.Compare(v1.Code, v2.Code) + lines := make([]model.DiffLine, len(result.Lines)) + for i, line := range result.Lines { + lines[i] = model.DiffLine{ + LineType: model.DiffLineType(line.Type), + OldLine: line.OldLine, + NewLine: line.NewLine, + Content: line.Content, + } + } + + return &model.VersionDiff{ + OldVersion: oldVersion, + NewVersion: newVersion, + Lines: lines, + }, nil +} + +// FunctionVersion returns FunctionVersionResolver implementation. +func (r *Resolver) FunctionVersion() FunctionVersionResolver { return &functionVersionResolver{r} } + +type functionVersionResolver struct{ *Resolver } diff --git a/internal/validation/validation.go b/internal/validation/validation.go new file mode 100644 index 0000000..2225174 --- /dev/null +++ b/internal/validation/validation.go @@ -0,0 +1,301 @@ +// Package validation holds the input-validation rules for functions, versions, +// environment variables, and KV entries. +// +// It is transport-agnostic: both the REST handlers (internal/api) and the +// GraphQL resolvers (internal/graph) call into it, so the rules have a single +// home and cannot drift between the two APIs. When the REST layer is removed, +// validation continues to live here. +package validation + +import ( + "fmt" + "slices" + "strings" + + "github.com/dimiro1/lunar/internal/store" + "github.com/robfig/cron/v3" +) + +const ( + // MaxFunctionNameLength is the maximum length for function names. + MaxFunctionNameLength = 100 + // MaxDescriptionLength is the maximum length for function descriptions. + MaxDescriptionLength = 500 + // MaxCodeLength is the maximum length for function code. + MaxCodeLength = 1024 * 1024 // 1MB + // MaxEnvVarKeyLength is the maximum length for environment variable keys. + MaxEnvVarKeyLength = 100 + // MaxEnvVarValueLength is the maximum length for environment variable values. + MaxEnvVarValueLength = 10000 + // MaxEnvVars is the maximum number of environment variables per function. + MaxEnvVars = 100 + // MaxStoreKeyLength is the maximum length for store keys. + MaxStoreKeyLength = 100 + // MaxStoreValueLength is the maximum length for store values. + MaxStoreValueLength = 10000 +) + +// AllowedRetentionDays lists the permitted execution-history retention windows. +var AllowedRetentionDays = []int{7, 15, 30, 365} + +// AllowedCronStatuses lists the permitted cron schedule statuses. +var AllowedCronStatuses = []string{string(store.CronStatusActive), string(store.CronStatusPaused)} + +// Error is a validation failure tied to a specific field. +type Error struct { + Field string + Message string +} + +func (e *Error) Error() string { + return fmt.Sprintf("%s: %s", e.Field, e.Message) +} + +// CreateFunction validates the fields supplied when creating a function. +func CreateFunction(name string, description *string, code string) error { + if err := FunctionName(name); err != nil { + return err + } + if description != nil { + if err := Description(*description); err != nil { + return err + } + } + return Code(code) +} + +// UpdateFunctionRequest validates a function update. At least one field must be +// set, and any provided field must itself be valid. +func UpdateFunctionRequest(req *store.UpdateFunctionRequest) error { + if req == nil { + return &Error{Field: "request", Message: "request cannot be nil"} + } + + if req.Name == nil && req.Description == nil && req.Code == nil && req.Disabled == nil && req.RetentionDays == nil && req.CronSchedule == nil && req.CronStatus == nil && req.SaveResponse == nil { + return &Error{Field: "request", Message: "at least one field must be provided for update"} + } + + if req.Name != nil { + if err := FunctionName(*req.Name); err != nil { + return err + } + } + if req.Description != nil { + if err := Description(*req.Description); err != nil { + return err + } + } + if req.Code != nil { + if err := Code(*req.Code); err != nil { + return err + } + } + if req.RetentionDays != nil { + if err := RetentionDays(*req.RetentionDays); err != nil { + return err + } + } + if req.CronSchedule != nil { + if err := CronSchedule(*req.CronSchedule); err != nil { + return err + } + } + if req.CronStatus != nil { + if err := CronStatus(*req.CronStatus); err != nil { + return err + } + } + return nil +} + +// EnvVars validates a complete set of environment variables (count and each +// key/value). It does not reject an empty map. +func EnvVars(envVars map[string]string) error { + if len(envVars) > MaxEnvVars { + return &Error{ + Field: "env_vars", + Message: fmt.Sprintf("cannot have more than %d environment variables", MaxEnvVars), + } + } + for key, value := range envVars { + if err := EnvVarKey(key); err != nil { + return err + } + if err := EnvVarValue(value); err != nil { + return err + } + } + return nil +} + +// KVEntries validates a complete set of key/value store entries. +func KVEntries(entries map[string]string) error { + for key, value := range entries { + if err := StoreKey(key); err != nil { + return err + } + if err := StoreValue(value); err != nil { + return err + } + } + return nil +} + +// FunctionName validates a function name. +func FunctionName(name string) error { + trimmed := strings.TrimSpace(name) + if trimmed == "" { + return &Error{Field: "name", Message: "name cannot be empty"} + } + if len(trimmed) > MaxFunctionNameLength { + return &Error{ + Field: "name", + Message: fmt.Sprintf("name cannot be longer than %d characters", MaxFunctionNameLength), + } + } + return nil +} + +// Description validates a function description. +func Description(description string) error { + if len(description) > MaxDescriptionLength { + return &Error{ + Field: "description", + Message: fmt.Sprintf("description cannot be longer than %d characters", MaxDescriptionLength), + } + } + return nil +} + +// Code validates function code. +func Code(code string) error { + trimmed := strings.TrimSpace(code) + if trimmed == "" { + return &Error{Field: "code", Message: "code cannot be empty"} + } + if len(code) > MaxCodeLength { + return &Error{ + Field: "code", + Message: fmt.Sprintf("code cannot be longer than %d bytes", MaxCodeLength), + } + } + return nil +} + +// EnvVarKey validates an environment variable key. +func EnvVarKey(key string) error { + trimmed := strings.TrimSpace(key) + if trimmed == "" { + return &Error{Field: "env_var_key", Message: "environment variable key cannot be empty"} + } + if len(key) > MaxEnvVarKeyLength { + return &Error{ + Field: "env_var_key", + Message: fmt.Sprintf("environment variable key cannot be longer than %d characters", MaxEnvVarKeyLength), + } + } + if !IsValidEnvVarKey(key) { + return &Error{ + Field: "env_var_key", + Message: "environment variable key can only contain letters, numbers, and underscores", + } + } + return nil +} + +// EnvVarValue validates an environment variable value. +func EnvVarValue(value string) error { + trimmed := strings.TrimSpace(value) + if trimmed == "" { + return &Error{Field: "env_var_value", Message: "environment variable value cannot be empty"} + } + if len(value) > MaxEnvVarValueLength { + return &Error{ + Field: "env_var_value", + Message: fmt.Sprintf("environment variable value cannot be longer than %d characters", MaxEnvVarValueLength), + } + } + return nil +} + +// IsValidEnvVarKey reports whether a string is a valid environment variable key +// (letters, numbers, and underscores only). +func IsValidEnvVarKey(key string) bool { + if key == "" { + return false + } + for _, char := range key { + if (char < 'a' || char > 'z') && (char < 'A' || char > 'Z') && (char < '0' || char > '9') && char != '_' { + return false + } + } + return true +} + +// RetentionDays validates an execution-history retention window. +func RetentionDays(days int) error { + if slices.Contains(AllowedRetentionDays, days) { + return nil + } + return &Error{ + Field: "retention_days", + Message: fmt.Sprintf("retention_days must be one of: %v", AllowedRetentionDays), + } +} + +// CronSchedule validates a cron expression. An empty schedule is allowed (it +// clears the schedule). +func CronSchedule(schedule string) error { + if schedule == "" { + return nil + } + parser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow) + if _, err := parser.Parse(schedule); err != nil { + return &Error{ + Field: "cron_schedule", + Message: fmt.Sprintf("invalid cron expression: %v", err), + } + } + return nil +} + +// CronStatus validates a cron status value. +func CronStatus(status string) error { + if slices.Contains(AllowedCronStatuses, status) { + return nil + } + return &Error{ + Field: "cron_status", + Message: fmt.Sprintf("cron_status must be one of: %v", AllowedCronStatuses), + } +} + +// StoreKey validates a KV store key. +func StoreKey(key string) error { + trimmed := strings.TrimSpace(key) + if trimmed == "" { + return &Error{Field: "key", Message: "key cannot be empty"} + } + if len(key) > MaxStoreKeyLength { + return &Error{ + Field: "key", + Message: fmt.Sprintf("key cannot be longer than %d characters", MaxStoreKeyLength), + } + } + return nil +} + +// StoreValue validates a KV store value. +func StoreValue(value string) error { + trimmed := strings.TrimSpace(value) + if trimmed == "" { + return &Error{Field: "value", Message: "value cannot be empty"} + } + if len(value) > MaxStoreValueLength { + return &Error{ + Field: "value", + Message: fmt.Sprintf("value cannot be longer than %d characters", MaxStoreValueLength), + } + } + return nil +} diff --git a/lunar-cli/README.md b/lunar-cli/README.md index 1cbed50..8426927 100644 --- a/lunar-cli/README.md +++ b/lunar-cli/README.md @@ -1,8 +1,8 @@ # lunar-cli -Command-line client for [Lunar](https://github.com/dimiro1/lunar). This README is for contributors working on the CLI internals and code generation. If you just want to install and use the CLI, start with the [root README](../README.md#cli). +Command-line client for [Lunar](https://github.com/dimiro1/lunar). This README is for contributors working on the CLI internals. If you just want to install and use the CLI, start with the [root README](../README.md#cli). -The majority of commands are **auto-generated** from the OpenAPI spec at `../internal/api/docs/openapi.yaml`, so the CLI always stays in sync with the API. +The CLI is a thin client over the server's **GraphQL API** (`/graphql`). The GraphQL schema is the single source of truth — the server won't compile until every field has a resolver, and the CLI's queries are validated against the live schema by introspection. There is no code-generation step: commands are hand-written Go, which keeps each file small and self-contained. ## Prerequisites @@ -14,143 +14,85 @@ The released executable is named `lunar-cli`, and the Cobra help output uses the ## How it works -Code generation runs in two layers: - -``` -internal/api/docs/openapi.yaml (source of truth) - │ - ├─▶ oapi-codegen ──────▶ client/client.gen.go - │ (typed HTTP client + all schema types) - │ - └─▶ tools/gen ─────────▶ cmd/functions.gen.go - cmd/versions.gen.go - cmd/executions.gen.go - cmd/tokens.gen.go - (Cobra subcommands) -``` - -**Layer 1 — HTTP client (`oapi-codegen`)** - -`client/generate.go` runs [`oapi-codegen`](https://github.com/oapi-codegen/oapi-codegen) against the spec to produce `client/client.gen.go`. This file contains all schema types (`Function`, `Execution`, etc.) and a `ClientWithResponses` struct with one typed method per API operation (e.g. `ListFunctionsWithResponse`, `CreateFunctionWithResponse`). - -**Layer 2 — Cobra commands (`tools/gen`)** - -`generate.go` runs the custom generator at `tools/gen/main.go`. It parses the spec and, for each API tag that maps to a CLI group, emits a `*.gen.go` file containing Cobra commands wired to the generated HTTP client. - -Tags → files: - -| OpenAPI tag | Generated file | -|-------------|----------------| -| Functions | `cmd/functions.gen.go` | -| Versions | `cmd/versions.gen.go` | -| Executions | `cmd/executions.gen.go` | -| API Tokens | `cmd/tokens.gen.go` | - -Tags **not** generated (implemented manually): - -| OpenAPI tag | Manual file | Reason | -|-------------|-------------|--------| -| Authentication | `cmd/auth.go` | Device auth flow needs interactive browser handling | -| Device Authorization | `cmd/auth.go` | Same as above | -| Runtime | `cmd/invoke.go` | Pass-through HTTP call, not a typed API request | +Each command builds a GraphQL operation as a string, runs it through a small set +of helpers, and prints the result. Two endpoints stay REST and bypass GraphQL: +the device-auth login flow (`cmd/auth.go`) and direct function invocation +(`cmd/invoke.go`, the pass-through `/fn/*` endpoint). + +**GraphQL client (`cmd/graphql.go`)** + +A thin wrapper around [`hasura/go-graphql-client`](https://github.com/hasura/go-graphql-client). +`mustGraphQLClient()` targets `/graphql` and injects the bearer token via +a custom `http.RoundTripper`. `execRaw` runs an operation and returns the decoded +top-level `data` object. Higher-level helpers shape that into the output the +renderer (and existing scripts) expect: + +| Helper | Use | Output shape | +|--------|-----|--------------| +| `gqlObject` | single resource (errors on `null`, the GraphQL 404) | the object | +| `gqlConnection` | paginated list (`{nodes, pageInfo}`) | `{: [...], "pagination": {...}}` | +| `gqlList` | plain list | `{: [...]}` | +| `gqlSuccess` | boolean mutation (delete/revoke) | `{"success": }` | + +**Command files (`cmd/*.go`)** + +Commands are grouped by domain, one file each. Each file declares a `const` +GraphQL selection (aliased from the schema's camelCase to the snake_case the +output renderer expects, e.g. `created_at: createdAt`) and a Cobra command per +operation: + +| File | Commands | +|------|----------| +| `cmd/functions.go` | `functions list/get/create/update/delete/env/kv/next-run` | +| `cmd/versions.go` | `versions list/get/activate/delete/diff` | +| `cmd/executions.go` | `executions list/get/logs/ai-requests/email-requests` | +| `cmd/tokens.go` | `tokens list/revoke` | +| `cmd/auth.go` | `login` / `logout` (REST device flow) | +| `cmd/invoke.go` | `invoke` (REST `/fn/*` pass-through) | +| `cmd/llms.go` | `llms` (fetches `/llms.txt`) | ## Directory structure ``` -cli/ +lunar-cli/ ├── main.go Entry point -├── generate.go go:generate directive for the Cobra generator ├── go.mod Module: github.com/dimiro1/lunar/lunar-cli │ ├── cmd/ -│ ├── root.go Root command, global flags (--server, --token), mustClient() -│ ├── auth.go lunar-cli login / logout (manual) -│ ├── invoke.go lunar-cli invoke (manual) -│ ├── functions.gen.go lunar-cli functions ... (generated) -│ ├── versions.gen.go lunar-cli versions ... (generated) -│ ├── executions.gen.go lunar-cli executions ... (generated) -│ └── tokens.gen.go lunar-cli tokens ... (generated) -│ -├── client/ -│ ├── generate.go go:generate directive for oapi-codegen -│ ├── oapi-codegen.yaml oapi-codegen configuration -│ └── client.gen.go Generated HTTP client (do not edit) +│ ├── root.go Root command, global flags (--server, --token), output helpers +│ ├── graphql.go GraphQL client + gqlObject/gqlConnection/gqlList/gqlSuccess helpers +│ ├── functions.go lunar-cli functions ... +│ ├── versions.go lunar-cli versions ... +│ ├── executions.go lunar-cli executions ... +│ ├── tokens.go lunar-cli tokens ... +│ ├── auth.go lunar-cli login / logout (REST device flow) +│ ├── invoke.go lunar-cli invoke (REST /fn/* pass-through) +│ ├── llms.go lunar-cli llms +│ └── output.go Pretty / JSON rendering │ ├── config/ │ └── config.go Read/write ~/.config/lunar/config.yaml │ -└── tools/ - ├── tools.go Build-constraint import keeping oapi-codegen in go.sum - └── gen/ - └── main.go Generator: openapi.yaml → cmd/*.gen.go -``` - -## Regenerating after an API change - -Whenever `../internal/api/docs/openapi.yaml` is updated, run from this directory: - -```bash -go generate ./... -``` - -This runs both generators in order: - -1. `client/generate.go` → regenerates `client/client.gen.go` via `oapi-codegen` -2. `generate.go` → regenerates `cmd/*.gen.go` via `tools/gen` - -Then verify the result compiles: - -```bash -go build ./... -``` - -## How the generator works (`tools/gen/main.go`) - -The generator is a standalone Go program invoked via `go run ./tools/gen`. It: - -1. Parses `openapi.yaml` into minimal Go structs (paths, operations, schemas, parameters). -2. Groups operations by OpenAPI tag using `tagConfigs`. -3. For each tag group, iterates operations and derives: - - **Command name** — from the `operationId` (strip the tag noun suffix, e.g. `listFunctions` → `list`). Override map handles special cases (`updateEnvVars` → `env`, `getVersionDiff` → `diff`, etc.). - - **Path params** → positional `cobra.ExactArgs` arguments. - - **Query params** → `--flag` flags bound to a `client.XxxParams` struct. - - **Body fields** → `--flag` flags; required fields get `MarkFlagRequired`; optional fields check `cmd.Flags().Changed()` before setting the pointer field. Enum fields are cast to the appropriate `client.XxxType`. - - **Map body fields** (e.g. `env_vars`, `kv`) → `--flag KEY=VALUE` repeatable flags parsed with `strings.SplitN`. - - **Code fields** — any `string` field named `code` also accepts `"-"` to read from stdin. -4. Renders the Go source using `fmt.Fprintf` into a `bytes.Buffer`. -5. Formats the result with `go/format` and writes the file. - -To add support for a new tag, add an entry to `tagConfigs` in `tools/gen/main.go`: - -```go -var tagConfigs = map[string]tagConfig{ - // ...existing tags... - "My Tag": {fileBase: "mytag", varName: "mytag", commandUse: "mytag", stripSuffix: []string{"mytag", "mytags"}}, -} -``` - -To override a generated command name for a specific operation, add it to `commandNameOverrides`: - -```go -var commandNameOverrides = map[string]string{ - // ...existing overrides... - "myOperationId": "my-command", -} +└── skills/ Bundled AI agent skill definitions ``` -## Adding a manual command +## Adding a command -If an operation is too complex to generate (interactive prompts, streaming, etc.): - -1. Create `cmd/mycommand.go` in the `cmd` package. -2. Register the command in `init()`: +1. Pick (or create) the domain file in `cmd/`, e.g. `cmd/functions.go`. +2. Declare the Cobra command and register it in an `init()`: ```go func init() { - rootCmd.AddCommand(myCmd) // top-level - // or: someGroupCmd.AddCommand(myCmd) + functionsCmd.AddCommand(myCmd) // or rootCmd.AddCommand for a top-level command + } + ``` +3. In the `RunE`, build the GraphQL operation and call the matching helper: + ```go + func runMyCommand(cmd *cobra.Command, args []string) error { + query := `query ($id: ID!) { function(id: $id) {` + functionFields + `} }` + return gqlObject(cmd.Context(), query, map[string]any{"id": args[0]}, "function") } ``` -3. Use `mustClient()` to get an authenticated HTTP client and `printJSON(resp.Body)` to print the response. + Use field aliases (`snake_case: camelCase`) in the selection so the output matches the rest of the CLI. After adding the field/operation to the server's GraphQL schema, run `go build ./...` — introspection and the schema's resolver requirement keep the CLI and server honest. ## AI Agent Skills diff --git a/lunar-cli/client/client.gen.go b/lunar-cli/client/client.gen.go deleted file mode 100644 index 22138d1..0000000 --- a/lunar-cli/client/client.gen.go +++ /dev/null @@ -1,5526 +0,0 @@ -// Package client provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.6.0 DO NOT EDIT. -package client - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "strings" - - "github.com/oapi-codegen/runtime" -) - -const ( - BearerAuthScopes = "BearerAuth.Scopes" - CookieAuthScopes = "CookieAuth.Scopes" -) - -// Defines values for AIRequestProvider. -const ( - Anthropic AIRequestProvider = "anthropic" - Openai AIRequestProvider = "openai" -) - -// Valid indicates whether the value is a known member of the AIRequestProvider enum. -func (e AIRequestProvider) Valid() bool { - switch e { - case Anthropic: - return true - case Openai: - return true - default: - return false - } -} - -// Defines values for AIRequestStatus. -const ( - AIRequestStatusError AIRequestStatus = "error" - AIRequestStatusSuccess AIRequestStatus = "success" -) - -// Valid indicates whether the value is a known member of the AIRequestStatus enum. -func (e AIRequestStatus) Valid() bool { - switch e { - case AIRequestStatusError: - return true - case AIRequestStatusSuccess: - return true - default: - return false - } -} - -// Defines values for DeviceApproveRequestAction. -const ( - Allow DeviceApproveRequestAction = "allow" - Deny DeviceApproveRequestAction = "deny" -) - -// Valid indicates whether the value is a known member of the DeviceApproveRequestAction enum. -func (e DeviceApproveRequestAction) Valid() bool { - switch e { - case Allow: - return true - case Deny: - return true - default: - return false - } -} - -// Defines values for DeviceApproveStatusResponseStatus. -const ( - DeviceApproveStatusResponseStatusApproved DeviceApproveStatusResponseStatus = "approved" - DeviceApproveStatusResponseStatusDenied DeviceApproveStatusResponseStatus = "denied" - DeviceApproveStatusResponseStatusPending DeviceApproveStatusResponseStatus = "pending" -) - -// Valid indicates whether the value is a known member of the DeviceApproveStatusResponseStatus enum. -func (e DeviceApproveStatusResponseStatus) Valid() bool { - switch e { - case DeviceApproveStatusResponseStatusApproved: - return true - case DeviceApproveStatusResponseStatusDenied: - return true - case DeviceApproveStatusResponseStatusPending: - return true - default: - return false - } -} - -// Defines values for DeviceTokenResponseStatus. -const ( - DeviceTokenResponseStatusApproved DeviceTokenResponseStatus = "approved" - DeviceTokenResponseStatusDenied DeviceTokenResponseStatus = "denied" - DeviceTokenResponseStatusPending DeviceTokenResponseStatus = "pending" -) - -// Valid indicates whether the value is a known member of the DeviceTokenResponseStatus enum. -func (e DeviceTokenResponseStatus) Valid() bool { - switch e { - case DeviceTokenResponseStatusApproved: - return true - case DeviceTokenResponseStatusDenied: - return true - case DeviceTokenResponseStatusPending: - return true - default: - return false - } -} - -// Defines values for DiffLineLineType. -const ( - Added DiffLineLineType = "added" - Removed DiffLineLineType = "removed" - Unchanged DiffLineLineType = "unchanged" -) - -// Valid indicates whether the value is a known member of the DiffLineLineType enum. -func (e DiffLineLineType) Valid() bool { - switch e { - case Added: - return true - case Removed: - return true - case Unchanged: - return true - default: - return false - } -} - -// Defines values for EmailRequestStatus. -const ( - EmailRequestStatusError EmailRequestStatus = "error" - EmailRequestStatusSuccess EmailRequestStatus = "success" -) - -// Valid indicates whether the value is a known member of the EmailRequestStatus enum. -func (e EmailRequestStatus) Valid() bool { - switch e { - case EmailRequestStatusError: - return true - case EmailRequestStatusSuccess: - return true - default: - return false - } -} - -// Defines values for ExecutionStatus. -const ( - ExecutionStatusError ExecutionStatus = "error" - ExecutionStatusPending ExecutionStatus = "pending" - ExecutionStatusSuccess ExecutionStatus = "success" -) - -// Valid indicates whether the value is a known member of the ExecutionStatus enum. -func (e ExecutionStatus) Valid() bool { - switch e { - case ExecutionStatusError: - return true - case ExecutionStatusPending: - return true - case ExecutionStatusSuccess: - return true - default: - return false - } -} - -// Defines values for ExecutionTrigger. -const ( - ExecutionTriggerCron ExecutionTrigger = "cron" - ExecutionTriggerHttp ExecutionTrigger = "http" -) - -// Valid indicates whether the value is a known member of the ExecutionTrigger enum. -func (e ExecutionTrigger) Valid() bool { - switch e { - case ExecutionTriggerCron: - return true - case ExecutionTriggerHttp: - return true - default: - return false - } -} - -// Defines values for ExecutionWithLogCountStatus. -const ( - ExecutionWithLogCountStatusError ExecutionWithLogCountStatus = "error" - ExecutionWithLogCountStatusPending ExecutionWithLogCountStatus = "pending" - ExecutionWithLogCountStatusSuccess ExecutionWithLogCountStatus = "success" -) - -// Valid indicates whether the value is a known member of the ExecutionWithLogCountStatus enum. -func (e ExecutionWithLogCountStatus) Valid() bool { - switch e { - case ExecutionWithLogCountStatusError: - return true - case ExecutionWithLogCountStatusPending: - return true - case ExecutionWithLogCountStatusSuccess: - return true - default: - return false - } -} - -// Defines values for ExecutionWithLogCountTrigger. -const ( - ExecutionWithLogCountTriggerCron ExecutionWithLogCountTrigger = "cron" - ExecutionWithLogCountTriggerHttp ExecutionWithLogCountTrigger = "http" -) - -// Valid indicates whether the value is a known member of the ExecutionWithLogCountTrigger enum. -func (e ExecutionWithLogCountTrigger) Valid() bool { - switch e { - case ExecutionWithLogCountTriggerCron: - return true - case ExecutionWithLogCountTriggerHttp: - return true - default: - return false - } -} - -// Defines values for ExecutionWithLogsStatus. -const ( - ExecutionWithLogsStatusError ExecutionWithLogsStatus = "error" - ExecutionWithLogsStatusPending ExecutionWithLogsStatus = "pending" - ExecutionWithLogsStatusSuccess ExecutionWithLogsStatus = "success" -) - -// Valid indicates whether the value is a known member of the ExecutionWithLogsStatus enum. -func (e ExecutionWithLogsStatus) Valid() bool { - switch e { - case ExecutionWithLogsStatusError: - return true - case ExecutionWithLogsStatusPending: - return true - case ExecutionWithLogsStatusSuccess: - return true - default: - return false - } -} - -// Defines values for ExecutionWithLogsTrigger. -const ( - Cron ExecutionWithLogsTrigger = "cron" - Http ExecutionWithLogsTrigger = "http" -) - -// Valid indicates whether the value is a known member of the ExecutionWithLogsTrigger enum. -func (e ExecutionWithLogsTrigger) Valid() bool { - switch e { - case Cron: - return true - case Http: - return true - default: - return false - } -} - -// Defines values for FunctionCronStatus. -const ( - FunctionCronStatusActive FunctionCronStatus = "active" - FunctionCronStatusPaused FunctionCronStatus = "paused" -) - -// Valid indicates whether the value is a known member of the FunctionCronStatus enum. -func (e FunctionCronStatus) Valid() bool { - switch e { - case FunctionCronStatusActive: - return true - case FunctionCronStatusPaused: - return true - default: - return false - } -} - -// Defines values for FunctionRetentionDays. -const ( - FunctionRetentionDaysN15 FunctionRetentionDays = 15 - FunctionRetentionDaysN30 FunctionRetentionDays = 30 - FunctionRetentionDaysN365 FunctionRetentionDays = 365 - FunctionRetentionDaysN7 FunctionRetentionDays = 7 -) - -// Valid indicates whether the value is a known member of the FunctionRetentionDays enum. -func (e FunctionRetentionDays) Valid() bool { - switch e { - case FunctionRetentionDaysN15: - return true - case FunctionRetentionDaysN30: - return true - case FunctionRetentionDaysN365: - return true - case FunctionRetentionDaysN7: - return true - default: - return false - } -} - -// Defines values for FunctionWithActiveVersionCronStatus. -const ( - FunctionWithActiveVersionCronStatusActive FunctionWithActiveVersionCronStatus = "active" - FunctionWithActiveVersionCronStatusPaused FunctionWithActiveVersionCronStatus = "paused" -) - -// Valid indicates whether the value is a known member of the FunctionWithActiveVersionCronStatus enum. -func (e FunctionWithActiveVersionCronStatus) Valid() bool { - switch e { - case FunctionWithActiveVersionCronStatusActive: - return true - case FunctionWithActiveVersionCronStatusPaused: - return true - default: - return false - } -} - -// Defines values for FunctionWithActiveVersionRetentionDays. -const ( - FunctionWithActiveVersionRetentionDaysN15 FunctionWithActiveVersionRetentionDays = 15 - FunctionWithActiveVersionRetentionDaysN30 FunctionWithActiveVersionRetentionDays = 30 - FunctionWithActiveVersionRetentionDaysN365 FunctionWithActiveVersionRetentionDays = 365 - FunctionWithActiveVersionRetentionDaysN7 FunctionWithActiveVersionRetentionDays = 7 -) - -// Valid indicates whether the value is a known member of the FunctionWithActiveVersionRetentionDays enum. -func (e FunctionWithActiveVersionRetentionDays) Valid() bool { - switch e { - case FunctionWithActiveVersionRetentionDaysN15: - return true - case FunctionWithActiveVersionRetentionDaysN30: - return true - case FunctionWithActiveVersionRetentionDaysN365: - return true - case FunctionWithActiveVersionRetentionDaysN7: - return true - default: - return false - } -} - -// Defines values for LogEntryLevel. -const ( - LogEntryLevelDebug LogEntryLevel = "debug" - LogEntryLevelError LogEntryLevel = "error" - LogEntryLevelInfo LogEntryLevel = "info" - LogEntryLevelWarn LogEntryLevel = "warn" -) - -// Valid indicates whether the value is a known member of the LogEntryLevel enum. -func (e LogEntryLevel) Valid() bool { - switch e { - case LogEntryLevelDebug: - return true - case LogEntryLevelError: - return true - case LogEntryLevelInfo: - return true - case LogEntryLevelWarn: - return true - default: - return false - } -} - -// Defines values for UpdateFunctionRequestCronStatus. -const ( - Active UpdateFunctionRequestCronStatus = "active" - Paused UpdateFunctionRequestCronStatus = "paused" -) - -// Valid indicates whether the value is a known member of the UpdateFunctionRequestCronStatus enum. -func (e UpdateFunctionRequestCronStatus) Valid() bool { - switch e { - case Active: - return true - case Paused: - return true - default: - return false - } -} - -// Defines values for UpdateFunctionRequestRetentionDays. -const ( - N15 UpdateFunctionRequestRetentionDays = 15 - N30 UpdateFunctionRequestRetentionDays = 30 - N365 UpdateFunctionRequestRetentionDays = 365 - N7 UpdateFunctionRequestRetentionDays = 7 -) - -// Valid indicates whether the value is a known member of the UpdateFunctionRequestRetentionDays enum. -func (e UpdateFunctionRequestRetentionDays) Valid() bool { - switch e { - case N15: - return true - case N30: - return true - case N365: - return true - case N7: - return true - default: - return false - } -} - -// AIRequest defines model for AIRequest. -type AIRequest struct { - // CreatedAt Unix timestamp when the request was made - CreatedAt int64 `json:"created_at"` - - // DurationMs Request duration in milliseconds - DurationMs int64 `json:"duration_ms"` - - // Endpoint API endpoint called - Endpoint string `json:"endpoint"` - - // ErrorMessage Error message if the request failed - ErrorMessage *string `json:"error_message,omitempty"` - - // ExecutionId ID of the execution this request belongs to - ExecutionId string `json:"execution_id"` - - // Id Unique identifier for the AI request - Id string `json:"id"` - - // InputTokens Number of input tokens used - InputTokens *int `json:"input_tokens,omitempty"` - - // Model Model name used for the request - Model string `json:"model"` - - // OutputTokens Number of output tokens generated - OutputTokens *int `json:"output_tokens,omitempty"` - - // Provider AI provider name - Provider AIRequestProvider `json:"provider"` - - // RequestJson JSON-encoded request payload (sensitive data masked) - RequestJson string `json:"request_json"` - - // ResponseJson JSON-encoded response payload (sensitive data masked) - ResponseJson *string `json:"response_json,omitempty"` - - // Status Status of the AI request - Status AIRequestStatus `json:"status"` -} - -// AIRequestProvider AI provider name -type AIRequestProvider string - -// AIRequestStatus Status of the AI request -type AIRequestStatus string - -// APIToken defines model for APIToken. -type APIToken struct { - // CreatedAt Unix timestamp when the token was created - CreatedAt int64 `json:"created_at"` - - // Id Unique identifier for the API token - Id string `json:"id"` - - // LastUsed Unix timestamp when the token was last used (null if never used) - LastUsed *int64 `json:"last_used,omitempty"` - - // Name Human-readable name for the token - Name string `json:"name"` - - // Revoked Whether the token has been revoked - Revoked bool `json:"revoked"` -} - -// CreateFunctionRequest defines model for CreateFunctionRequest. -type CreateFunctionRequest struct { - // Code Lua code for the function (must be non-empty after trimming whitespace) - Code string `json:"code"` - - // Description Optional description - Description *string `json:"description,omitempty"` - - // Name Name for the function (must be non-empty after trimming whitespace) - Name string `json:"name"` -} - -// DeviceApproveRequest defines model for DeviceApproveRequest. -type DeviceApproveRequest struct { - // Action The action to take on the authorization request - Action DeviceApproveRequestAction `json:"action"` - - // DeviceCode The device code from the authorization request - DeviceCode string `json:"device_code"` -} - -// DeviceApproveRequestAction The action to take on the authorization request -type DeviceApproveRequestAction string - -// DeviceApproveStatusResponse defines model for DeviceApproveStatusResponse. -type DeviceApproveStatusResponse struct { - // DeviceCode The device code for this authorization request - DeviceCode string `json:"device_code"` - - // ExpiresAt Unix timestamp when this authorization request expires - ExpiresAt int64 `json:"expires_at"` - - // Status Current status of the authorization request - Status DeviceApproveStatusResponseStatus `json:"status"` - - // UserCode The user verification code - UserCode string `json:"user_code"` -} - -// DeviceApproveStatusResponseStatus Current status of the authorization request -type DeviceApproveStatusResponseStatus string - -// DeviceRequestResponse defines model for DeviceRequestResponse. -type DeviceRequestResponse struct { - // ApprovalUrl URL where the user should approve the device authorization - ApprovalUrl string `json:"approval_url"` - - // DeviceCode Unique device code used to identify this authorization request - DeviceCode string `json:"device_code"` - - // ExpiresIn Number of seconds until this authorization request expires - ExpiresIn int `json:"expires_in"` - - // Interval Recommended polling interval in seconds for the device-token endpoint - Interval int `json:"interval"` - - // UserCode Short alphanumeric code displayed to the user for verification - UserCode string `json:"user_code"` -} - -// DeviceTokenResponse defines model for DeviceTokenResponse. -type DeviceTokenResponse struct { - // Status Current status of the authorization request - Status DeviceTokenResponseStatus `json:"status"` - - // Token The API token (only present when status is "approved"). This is the only time the raw token is returned. - Token *string `json:"token,omitempty"` -} - -// DeviceTokenResponseStatus Current status of the authorization request -type DeviceTokenResponseStatus string - -// DiffLine defines model for DiffLine. -type DiffLine struct { - // Content Content of the line - Content string `json:"content"` - - // LineType Type of change for this line - LineType DiffLineLineType `json:"line_type"` - - // NewLine Line number in new version (null for removed lines) - NewLine *int `json:"new_line,omitempty"` - - // OldLine Line number in old version (null for added lines) - OldLine *int `json:"old_line,omitempty"` -} - -// DiffLineLineType Type of change for this line -type DiffLineLineType string - -// EmailRequest defines model for EmailRequest. -type EmailRequest struct { - // CreatedAt Unix timestamp when the request was made - CreatedAt int64 `json:"created_at"` - - // DurationMs Request duration in milliseconds - DurationMs int64 `json:"duration_ms"` - - // EmailId ID returned by the email provider (Resend) - EmailId *string `json:"email_id,omitempty"` - - // ErrorMessage Error message if the request failed - ErrorMessage *string `json:"error_message,omitempty"` - - // ExecutionId ID of the execution this request belongs to - ExecutionId string `json:"execution_id"` - - // From Sender email address - From string `json:"from"` - - // HasHtml Whether the email contains HTML content - HasHtml bool `json:"has_html"` - - // HasText Whether the email contains plain text content - HasText bool `json:"has_text"` - - // Id Unique identifier for the email request - Id string `json:"id"` - - // RequestJson JSON-encoded request payload (sensitive data masked) - RequestJson string `json:"request_json"` - - // ResponseJson JSON-encoded response payload - ResponseJson *string `json:"response_json,omitempty"` - - // Status Status of the email request - Status EmailRequestStatus `json:"status"` - - // Subject Email subject line - Subject string `json:"subject"` - - // To List of recipient email addresses - To []string `json:"to"` -} - -// EmailRequestStatus Status of the email request -type EmailRequestStatus string - -// ErrorResponse defines model for ErrorResponse. -type ErrorResponse struct { - // Error Error message - Error string `json:"error"` -} - -// Execution defines model for Execution. -type Execution struct { - // CreatedAt Unix timestamp when execution started - CreatedAt int64 `json:"created_at"` - - // DurationMs Execution duration in milliseconds - DurationMs *int64 `json:"duration_ms,omitempty"` - - // ErrorMessage Error message if execution failed - ErrorMessage *string `json:"error_message,omitempty"` - - // ExecutionId Unique execution identifier - ExecutionId string `json:"execution_id"` - - // FunctionId ID of the function that was executed - FunctionId string `json:"function_id"` - - // FunctionVersionId ID of the version that was executed - FunctionVersionId string `json:"function_version_id"` - - // Id Internal database ID - Id string `json:"id"` - - // ResponseJson JSON-encoded HTTP response (only present if save_response is enabled on the function). Contains statusCode, headers, body, and isBase64Encoded. Body is truncated to 1MB if larger. - ResponseJson *string `json:"response_json,omitempty"` - - // Status Status of the execution - Status ExecutionStatus `json:"status"` - - // Trigger What triggered this execution - Trigger *ExecutionTrigger `json:"trigger,omitempty"` -} - -// ExecutionStatus Status of the execution -type ExecutionStatus string - -// ExecutionTrigger What triggered this execution -type ExecutionTrigger string - -// ExecutionWithLogCount defines model for ExecutionWithLogCount. -type ExecutionWithLogCount struct { - // CreatedAt Unix timestamp when execution started - CreatedAt int64 `json:"created_at"` - - // DurationMs Execution duration in milliseconds - DurationMs *int64 `json:"duration_ms,omitempty"` - - // ErrorMessage Error message if execution failed - ErrorMessage *string `json:"error_message,omitempty"` - - // ExecutionId Unique execution identifier - ExecutionId string `json:"execution_id"` - - // FunctionId ID of the function that was executed - FunctionId string `json:"function_id"` - - // FunctionVersionId ID of the version that was executed - FunctionVersionId string `json:"function_version_id"` - - // Id Internal database ID - Id string `json:"id"` - - // LogCount Number of log entries for this execution - LogCount int64 `json:"log_count"` - - // ResponseJson JSON-encoded HTTP response (only present if save_response is enabled on the function). Contains statusCode, headers, body, and isBase64Encoded. Body is truncated to 1MB if larger. - ResponseJson *string `json:"response_json,omitempty"` - - // Status Status of the execution - Status ExecutionWithLogCountStatus `json:"status"` - - // Trigger What triggered this execution - Trigger *ExecutionWithLogCountTrigger `json:"trigger,omitempty"` -} - -// ExecutionWithLogCountStatus Status of the execution -type ExecutionWithLogCountStatus string - -// ExecutionWithLogCountTrigger What triggered this execution -type ExecutionWithLogCountTrigger string - -// ExecutionWithLogs defines model for ExecutionWithLogs. -type ExecutionWithLogs struct { - // CreatedAt Unix timestamp when execution started - CreatedAt int64 `json:"created_at"` - - // DurationMs Execution duration in milliseconds - DurationMs *int64 `json:"duration_ms,omitempty"` - - // ErrorMessage Error message if execution failed - ErrorMessage *string `json:"error_message,omitempty"` - - // ExecutionId Unique execution identifier - ExecutionId string `json:"execution_id"` - - // FunctionId ID of the function that was executed - FunctionId string `json:"function_id"` - - // FunctionVersionId ID of the version that was executed - FunctionVersionId string `json:"function_version_id"` - - // Id Internal database ID - Id string `json:"id"` - Logs []LogEntry `json:"logs"` - Pagination PaginationInfo `json:"pagination"` - - // ResponseJson JSON-encoded HTTP response (only present if save_response is enabled on the function). Contains statusCode, headers, body, and isBase64Encoded. Body is truncated to 1MB if larger. - ResponseJson *string `json:"response_json,omitempty"` - - // Status Status of the execution - Status ExecutionWithLogsStatus `json:"status"` - - // Trigger What triggered this execution - Trigger *ExecutionWithLogsTrigger `json:"trigger,omitempty"` -} - -// ExecutionWithLogsStatus Status of the execution -type ExecutionWithLogsStatus string - -// ExecutionWithLogsTrigger What triggered this execution -type ExecutionWithLogsTrigger string - -// Function defines model for Function. -type Function struct { - // CreatedAt Unix timestamp when the function was created - CreatedAt int64 `json:"created_at"` - - // CronSchedule Cron expression for scheduled execution (standard 5-field format) - CronSchedule *string `json:"cron_schedule,omitempty"` - - // CronStatus Status of the cron schedule - CronStatus *FunctionCronStatus `json:"cron_status,omitempty"` - - // Description Optional description of what the function does - Description *string `json:"description,omitempty"` - - // Disabled Whether the function is disabled and cannot be executed - Disabled bool `json:"disabled"` - - // EnvVars Environment variables available to the function - EnvVars map[string]string `json:"env_vars"` - - // Id Unique identifier for the function - Id string `json:"id"` - - // Name Human-readable name for the function - Name string `json:"name"` - - // RetentionDays Number of days to retain execution logs (default is 7 days) - RetentionDays *FunctionRetentionDays `json:"retention_days,omitempty"` - - // SaveResponse Whether to save HTTP responses with executions for debugging - SaveResponse *bool `json:"save_response,omitempty"` - - // UpdatedAt Unix timestamp when the function was last updated - UpdatedAt int64 `json:"updated_at"` -} - -// FunctionCronStatus Status of the cron schedule -type FunctionCronStatus string - -// FunctionRetentionDays Number of days to retain execution logs (default is 7 days) -type FunctionRetentionDays int - -// FunctionVersion defines model for FunctionVersion. -type FunctionVersion struct { - // Code Lua code for this version - Code string `json:"code"` - - // CreatedAt Unix timestamp when this version was created - CreatedAt int64 `json:"created_at"` - - // CreatedBy User who created this version (if applicable) - CreatedBy *string `json:"created_by,omitempty"` - - // FunctionId ID of the parent function - FunctionId string `json:"function_id"` - - // Id Unique identifier for this version - Id string `json:"id"` - - // IsActive Whether this is the currently active version - IsActive bool `json:"is_active"` - - // Version Version number (incremental) - Version int `json:"version"` -} - -// FunctionWithActiveVersion defines model for FunctionWithActiveVersion. -type FunctionWithActiveVersion struct { - ActiveVersion FunctionVersion `json:"active_version"` - - // CreatedAt Unix timestamp when the function was created - CreatedAt int64 `json:"created_at"` - - // CronSchedule Cron expression for scheduled execution (standard 5-field format) - CronSchedule *string `json:"cron_schedule,omitempty"` - - // CronStatus Status of the cron schedule - CronStatus *FunctionWithActiveVersionCronStatus `json:"cron_status,omitempty"` - - // Description Optional description of what the function does - Description *string `json:"description,omitempty"` - - // Disabled Whether the function is disabled and cannot be executed - Disabled bool `json:"disabled"` - - // EnvVars Environment variables available to the function - EnvVars map[string]string `json:"env_vars"` - - // Id Unique identifier for the function - Id string `json:"id"` - - // Name Human-readable name for the function - Name string `json:"name"` - - // RetentionDays Number of days to retain execution logs (default is 7 days) - RetentionDays *FunctionWithActiveVersionRetentionDays `json:"retention_days,omitempty"` - - // SaveResponse Whether to save HTTP responses with executions for debugging - SaveResponse *bool `json:"save_response,omitempty"` - - // UpdatedAt Unix timestamp when the function was last updated - UpdatedAt int64 `json:"updated_at"` -} - -// FunctionWithActiveVersionCronStatus Status of the cron schedule -type FunctionWithActiveVersionCronStatus string - -// FunctionWithActiveVersionRetentionDays Number of days to retain execution logs (default is 7 days) -type FunctionWithActiveVersionRetentionDays int - -// ListAIRequestsResponse defines model for ListAIRequestsResponse. -type ListAIRequestsResponse struct { - AiRequests []AIRequest `json:"ai_requests"` - Pagination PaginationInfo `json:"pagination"` -} - -// ListAPITokensResponse defines model for ListAPITokensResponse. -type ListAPITokensResponse struct { - // Tokens List of API tokens - Tokens []APIToken `json:"tokens"` -} - -// ListEmailRequestsResponse defines model for ListEmailRequestsResponse. -type ListEmailRequestsResponse struct { - EmailRequests []EmailRequest `json:"email_requests"` - Pagination PaginationInfo `json:"pagination"` -} - -// ListExecutionsResponse defines model for ListExecutionsResponse. -type ListExecutionsResponse struct { - Executions []ExecutionWithLogCount `json:"executions"` - Pagination PaginationInfo `json:"pagination"` -} - -// ListFunctionsResponse defines model for ListFunctionsResponse. -type ListFunctionsResponse struct { - Functions []FunctionWithActiveVersion `json:"functions"` - Pagination PaginationInfo `json:"pagination"` -} - -// ListVersionsResponse defines model for ListVersionsResponse. -type ListVersionsResponse struct { - Pagination PaginationInfo `json:"pagination"` - Versions []FunctionVersion `json:"versions"` -} - -// LogEntry defines model for LogEntry. -type LogEntry struct { - // CreatedAt Unix timestamp when log was created - CreatedAt int64 `json:"created_at"` - - // ExecutionId ID of the execution this log belongs to - ExecutionId string `json:"execution_id"` - - // Id Unique identifier for the log entry - Id string `json:"id"` - - // Level Log level - Level LogEntryLevel `json:"level"` - - // Message Log message content - Message string `json:"message"` -} - -// LogEntryLevel Log level -type LogEntryLevel string - -// LoginRequest defines model for LoginRequest. -type LoginRequest struct { - // ApiKey API key used to authenticate requests. - ApiKey string `json:"apiKey"` -} - -// LoginResponse defines model for LoginResponse. -type LoginResponse struct { - // Error Error message when the operation fails. - Error *string `json:"error,omitempty"` - - // Success Indicates whether the authentication action succeeded. - Success bool `json:"success"` -} - -// NextRunResponse defines model for NextRunResponse. -type NextRunResponse struct { - // NextRun Unix timestamp of the next scheduled execution (null if no active schedule) - NextRun *int64 `json:"next_run,omitempty"` - - // NextRunHuman Human-readable description of when the next run will occur (e.g., "in 2 hours") - NextRunHuman *string `json:"next_run_human,omitempty"` -} - -// PaginationInfo defines model for PaginationInfo. -type PaginationInfo struct { - // Limit Number of items per page - Limit int `json:"limit"` - - // Offset Number of items skipped - Offset int `json:"offset"` - - // Total Total number of items available - Total int64 `json:"total"` -} - -// UpdateEnvVarsRequest defines model for UpdateEnvVarsRequest. -type UpdateEnvVarsRequest struct { - // EnvVars Environment variables to set (max 100 variables). - // Keys must contain only letters, numbers, and underscores (max 100 chars). - // Values can be up to 10,000 characters. - EnvVars map[string]string `json:"env_vars"` -} - -// UpdateFunctionRequest At least one field must be provided -type UpdateFunctionRequest struct { - // Code New code (creates a new version, must be non-empty after trimming whitespace) - Code *string `json:"code,omitempty"` - - // CronSchedule Cron expression for scheduled execution (standard 5-field format: minute hour day month weekday). - // Examples: "*/5 * * * *" (every 5 minutes), "0 9 * * 1-5" (weekdays at 9am). - // Set to empty string to clear the schedule. - CronSchedule *string `json:"cron_schedule,omitempty"` - - // CronStatus Status of the cron schedule. Set to "active" to enable scheduled execution. - CronStatus *UpdateFunctionRequestCronStatus `json:"cron_status,omitempty"` - - // Description New description - Description *string `json:"description,omitempty"` - - // Disabled Set to true to disable the function (preventing execution), false to enable it - Disabled *bool `json:"disabled,omitempty"` - - // Name New name for the function (must be non-empty after trimming whitespace) - Name *string `json:"name,omitempty"` - - // RetentionDays Number of days to retain execution logs - RetentionDays *UpdateFunctionRequestRetentionDays `json:"retention_days,omitempty"` - - // SaveResponse Whether to save HTTP responses with executions for debugging - SaveResponse *bool `json:"save_response,omitempty"` -} - -// UpdateFunctionRequestCronStatus Status of the cron schedule. Set to "active" to enable scheduled execution. -type UpdateFunctionRequestCronStatus string - -// UpdateFunctionRequestRetentionDays Number of days to retain execution logs -type UpdateFunctionRequestRetentionDays int - -// UpdateKVRequest defines model for UpdateKVRequest. -type UpdateKVRequest struct { - // Global Whether the KV pairs are global or function-scoped - Global bool `json:"global"` - - // Kv Key-value pairs to set in the function's KV store (max 100 pairs). - // Keys must contain only letters, numbers, and underscores (max 100 chars). - // Values can be up to 10,000 characters. - Kv map[string]string `json:"kv"` -} - -// VersionDiffResponse defines model for VersionDiffResponse. -type VersionDiffResponse struct { - // Diff Line-by-line diff - Diff []DiffLine `json:"diff"` - - // NewVersion Second version number - NewVersion int `json:"new_version"` - - // OldVersion First version number - OldVersion int `json:"old_version"` -} - -// DeviceApproveStatusParams defines parameters for DeviceApproveStatus. -type DeviceApproveStatusParams struct { - // Code The device code from the authorization request - Code string `form:"code" json:"code"` -} - -// DeviceTokenParams defines parameters for DeviceToken. -type DeviceTokenParams struct { - // Code The device code from the authorization request - Code string `form:"code" json:"code"` -} - -// GetExecutionAIRequestsParams defines parameters for GetExecutionAIRequests. -type GetExecutionAIRequestsParams struct { - // Limit Maximum number of AI requests to return (default 20, max 100) - Limit *int `form:"limit,omitempty" json:"limit,omitempty"` - - // Offset Number of AI requests to skip - Offset *int `form:"offset,omitempty" json:"offset,omitempty"` -} - -// GetExecutionEmailRequestsParams defines parameters for GetExecutionEmailRequests. -type GetExecutionEmailRequestsParams struct { - // Limit Maximum number of email requests to return (default 20, max 100) - Limit *int `form:"limit,omitempty" json:"limit,omitempty"` - - // Offset Number of email requests to skip - Offset *int `form:"offset,omitempty" json:"offset,omitempty"` -} - -// GetExecutionLogsParams defines parameters for GetExecutionLogs. -type GetExecutionLogsParams struct { - // Limit Maximum number of log entries to return (default 20, max 100) - Limit *int `form:"limit,omitempty" json:"limit,omitempty"` - - // Offset Number of log entries to skip - Offset *int `form:"offset,omitempty" json:"offset,omitempty"` -} - -// ListFunctionsParams defines parameters for ListFunctions. -type ListFunctionsParams struct { - // Limit Maximum number of items to return (default 20, max 100) - Limit *int `form:"limit,omitempty" json:"limit,omitempty"` - - // Offset Number of items to skip - Offset *int `form:"offset,omitempty" json:"offset,omitempty"` -} - -// ListExecutionsParams defines parameters for ListExecutions. -type ListExecutionsParams struct { - // Limit Maximum number of items to return (default 20, max 100) - Limit *int `form:"limit,omitempty" json:"limit,omitempty"` - - // Offset Number of items to skip - Offset *int `form:"offset,omitempty" json:"offset,omitempty"` -} - -// ListVersionsParams defines parameters for ListVersions. -type ListVersionsParams struct { - // Limit Maximum number of items to return (default 20, max 100) - Limit *int `form:"limit,omitempty" json:"limit,omitempty"` - - // Offset Number of items to skip - Offset *int `form:"offset,omitempty" json:"offset,omitempty"` -} - -// ExecuteFunctionDeleteParams defines parameters for ExecuteFunctionDelete. -type ExecuteFunctionDeleteParams struct { - QueryParameters *map[string]string `form:"query parameters,omitempty" json:"query parameters,omitempty"` -} - -// ExecuteFunctionGetParams defines parameters for ExecuteFunctionGet. -type ExecuteFunctionGetParams struct { - // QueryParameters Any query parameters are passed to the function - QueryParameters *map[string]string `form:"query parameters,omitempty" json:"query parameters,omitempty"` -} - -// ExecuteFunctionPostParams defines parameters for ExecuteFunctionPost. -type ExecuteFunctionPostParams struct { - // QueryParameters Any query parameters are passed to the function - QueryParameters *map[string]string `form:"query parameters,omitempty" json:"query parameters,omitempty"` -} - -// ExecuteFunctionPutParams defines parameters for ExecuteFunctionPut. -type ExecuteFunctionPutParams struct { - QueryParameters *map[string]string `form:"query parameters,omitempty" json:"query parameters,omitempty"` -} - -// DeviceApproveJSONRequestBody defines body for DeviceApprove for application/json ContentType. -type DeviceApproveJSONRequestBody = DeviceApproveRequest - -// LoginJSONRequestBody defines body for Login for application/json ContentType. -type LoginJSONRequestBody = LoginRequest - -// CreateFunctionJSONRequestBody defines body for CreateFunction for application/json ContentType. -type CreateFunctionJSONRequestBody = CreateFunctionRequest - -// UpdateFunctionJSONRequestBody defines body for UpdateFunction for application/json ContentType. -type UpdateFunctionJSONRequestBody = UpdateFunctionRequest - -// UpdateEnvVarsJSONRequestBody defines body for UpdateEnvVars for application/json ContentType. -type UpdateEnvVarsJSONRequestBody = UpdateEnvVarsRequest - -// UpdateKVJSONRequestBody defines body for UpdateKV for application/json ContentType. -type UpdateKVJSONRequestBody = UpdateKVRequest - -// RequestEditorFn is the function signature for the RequestEditor callback function -type RequestEditorFn func(ctx context.Context, req *http.Request) error - -// Doer performs HTTP requests. -// -// The standard http.Client implements this interface. -type HttpRequestDoer interface { - Do(req *http.Request) (*http.Response, error) -} - -// Client which conforms to the OpenAPI3 specification for this service. -type Client struct { - // The endpoint of the server conforming to this interface, with scheme, - // https://api.deepmap.com for example. This can contain a path relative - // to the server, such as https://api.deepmap.com/dev-test, and all the - // paths in the swagger spec will be appended to the server. - Server string - - // Doer for performing requests, typically a *http.Client with any - // customized settings, such as certificate chains. - Client HttpRequestDoer - - // A list of callbacks for modifying requests which are generated before sending over - // the network. - RequestEditors []RequestEditorFn -} - -// ClientOption allows setting custom parameters during construction -type ClientOption func(*Client) error - -// Creates a new Client, with reasonable defaults -func NewClient(server string, opts ...ClientOption) (*Client, error) { - // create a client with sane default values - client := Client{ - Server: server, - } - // mutate client and add all optional params - for _, o := range opts { - if err := o(&client); err != nil { - return nil, err - } - } - // ensure the server URL always has a trailing slash - if !strings.HasSuffix(client.Server, "/") { - client.Server += "/" - } - // create httpClient, if not already present - if client.Client == nil { - client.Client = &http.Client{} - } - return &client, nil -} - -// WithHTTPClient allows overriding the default Doer, which is -// automatically created using http.Client. This is useful for tests. -func WithHTTPClient(doer HttpRequestDoer) ClientOption { - return func(c *Client) error { - c.Client = doer - return nil - } -} - -// WithRequestEditorFn allows setting up a callback function, which will be -// called right before sending the request. This can be used to mutate the request. -func WithRequestEditorFn(fn RequestEditorFn) ClientOption { - return func(c *Client) error { - c.RequestEditors = append(c.RequestEditors, fn) - return nil - } -} - -// The interface specification for the client above. -type ClientInterface interface { - // DeviceApproveStatus request - DeviceApproveStatus(ctx context.Context, params *DeviceApproveStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // DeviceApproveWithBody request with any body - DeviceApproveWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - DeviceApprove(ctx context.Context, body DeviceApproveJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // DeviceRequest request - DeviceRequest(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // DeviceToken request - DeviceToken(ctx context.Context, params *DeviceTokenParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // LoginWithBody request with any body - LoginWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - Login(ctx context.Context, body LoginJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // Logout request - Logout(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetExecution request - GetExecution(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetExecutionAIRequests request - GetExecutionAIRequests(ctx context.Context, id string, params *GetExecutionAIRequestsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetExecutionEmailRequests request - GetExecutionEmailRequests(ctx context.Context, id string, params *GetExecutionEmailRequestsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetExecutionLogs request - GetExecutionLogs(ctx context.Context, id string, params *GetExecutionLogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ListFunctions request - ListFunctions(ctx context.Context, params *ListFunctionsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // CreateFunctionWithBody request with any body - CreateFunctionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - CreateFunction(ctx context.Context, body CreateFunctionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // DeleteFunction request - DeleteFunction(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetFunction request - GetFunction(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // UpdateFunctionWithBody request with any body - UpdateFunctionWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - UpdateFunction(ctx context.Context, id string, body UpdateFunctionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetVersionDiff request - GetVersionDiff(ctx context.Context, id string, v1 int, v2 int, reqEditors ...RequestEditorFn) (*http.Response, error) - - // UpdateEnvVarsWithBody request with any body - UpdateEnvVarsWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - UpdateEnvVars(ctx context.Context, id string, body UpdateEnvVarsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ListExecutions request - ListExecutions(ctx context.Context, id string, params *ListExecutionsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // UpdateKVWithBody request with any body - UpdateKVWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - UpdateKV(ctx context.Context, id string, body UpdateKVJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetNextRun request - GetNextRun(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ListVersions request - ListVersions(ctx context.Context, id string, params *ListVersionsParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // DeleteVersion request - DeleteVersion(ctx context.Context, id string, versionId string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ActivateVersion request - ActivateVersion(ctx context.Context, id string, versionId string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetVersion request - GetVersion(ctx context.Context, id string, version int, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ListTokens request - ListTokens(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // RevokeToken request - RevokeToken(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ExecuteFunctionDelete request - ExecuteFunctionDelete(ctx context.Context, functionId string, params *ExecuteFunctionDeleteParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ExecuteFunctionGet request - ExecuteFunctionGet(ctx context.Context, functionId string, params *ExecuteFunctionGetParams, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ExecuteFunctionPostWithBody request with any body - ExecuteFunctionPostWithBody(ctx context.Context, functionId string, params *ExecuteFunctionPostParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - // ExecuteFunctionPutWithBody request with any body - ExecuteFunctionPutWithBody(ctx context.Context, functionId string, params *ExecuteFunctionPutParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) -} - -func (c *Client) DeviceApproveStatus(ctx context.Context, params *DeviceApproveStatusParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeviceApproveStatusRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) DeviceApproveWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeviceApproveRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) DeviceApprove(ctx context.Context, body DeviceApproveJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeviceApproveRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) DeviceRequest(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeviceRequestRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) DeviceToken(ctx context.Context, params *DeviceTokenParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeviceTokenRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) LoginWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewLoginRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) Login(ctx context.Context, body LoginJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewLoginRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) Logout(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewLogoutRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetExecution(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetExecutionRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetExecutionAIRequests(ctx context.Context, id string, params *GetExecutionAIRequestsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetExecutionAIRequestsRequest(c.Server, id, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetExecutionEmailRequests(ctx context.Context, id string, params *GetExecutionEmailRequestsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetExecutionEmailRequestsRequest(c.Server, id, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetExecutionLogs(ctx context.Context, id string, params *GetExecutionLogsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetExecutionLogsRequest(c.Server, id, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ListFunctions(ctx context.Context, params *ListFunctionsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewListFunctionsRequest(c.Server, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) CreateFunctionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateFunctionRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) CreateFunction(ctx context.Context, body CreateFunctionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewCreateFunctionRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) DeleteFunction(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteFunctionRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetFunction(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetFunctionRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateFunctionWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateFunctionRequestWithBody(c.Server, id, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateFunction(ctx context.Context, id string, body UpdateFunctionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateFunctionRequest(c.Server, id, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetVersionDiff(ctx context.Context, id string, v1 int, v2 int, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetVersionDiffRequest(c.Server, id, v1, v2) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateEnvVarsWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateEnvVarsRequestWithBody(c.Server, id, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateEnvVars(ctx context.Context, id string, body UpdateEnvVarsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateEnvVarsRequest(c.Server, id, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ListExecutions(ctx context.Context, id string, params *ListExecutionsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewListExecutionsRequest(c.Server, id, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateKVWithBody(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateKVRequestWithBody(c.Server, id, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) UpdateKV(ctx context.Context, id string, body UpdateKVJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewUpdateKVRequest(c.Server, id, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetNextRun(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetNextRunRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ListVersions(ctx context.Context, id string, params *ListVersionsParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewListVersionsRequest(c.Server, id, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) DeleteVersion(ctx context.Context, id string, versionId string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewDeleteVersionRequest(c.Server, id, versionId) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ActivateVersion(ctx context.Context, id string, versionId string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewActivateVersionRequest(c.Server, id, versionId) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetVersion(ctx context.Context, id string, version int, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetVersionRequest(c.Server, id, version) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ListTokens(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewListTokensRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) RevokeToken(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewRevokeTokenRequest(c.Server, id) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ExecuteFunctionDelete(ctx context.Context, functionId string, params *ExecuteFunctionDeleteParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewExecuteFunctionDeleteRequest(c.Server, functionId, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ExecuteFunctionGet(ctx context.Context, functionId string, params *ExecuteFunctionGetParams, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewExecuteFunctionGetRequest(c.Server, functionId, params) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ExecuteFunctionPostWithBody(ctx context.Context, functionId string, params *ExecuteFunctionPostParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewExecuteFunctionPostRequestWithBody(c.Server, functionId, params, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) ExecuteFunctionPutWithBody(ctx context.Context, functionId string, params *ExecuteFunctionPutParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewExecuteFunctionPutRequestWithBody(c.Server, functionId, params, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -// NewDeviceApproveStatusRequest generates requests for DeviceApproveStatus -func NewDeviceApproveStatusRequest(server string, params *DeviceApproveStatusParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/auth/device-approve") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "code", params.Code, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewDeviceApproveRequest calls the generic DeviceApprove builder with application/json body -func NewDeviceApproveRequest(server string, body DeviceApproveJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewDeviceApproveRequestWithBody(server, "application/json", bodyReader) -} - -// NewDeviceApproveRequestWithBody generates requests for DeviceApprove with any type of body -func NewDeviceApproveRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/auth/device-approve") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewDeviceRequestRequest generates requests for DeviceRequest -func NewDeviceRequestRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/auth/device-request") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewDeviceTokenRequest generates requests for DeviceToken -func NewDeviceTokenRequest(server string, params *DeviceTokenParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/auth/device-token") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "code", params.Code, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewLoginRequest calls the generic Login builder with application/json body -func NewLoginRequest(server string, body LoginJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewLoginRequestWithBody(server, "application/json", bodyReader) -} - -// NewLoginRequestWithBody generates requests for Login with any type of body -func NewLoginRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/auth/login") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewLogoutRequest generates requests for Logout -func NewLogoutRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/auth/logout") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetExecutionRequest generates requests for GetExecution -func NewGetExecutionRequest(server string, id string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/executions/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetExecutionAIRequestsRequest generates requests for GetExecutionAIRequests -func NewGetExecutionAIRequestsRequest(server string, id string, params *GetExecutionAIRequestsParams) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/executions/%s/ai-requests", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.Limit != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "limit", *params.Limit, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - if params.Offset != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "offset", *params.Offset, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetExecutionEmailRequestsRequest generates requests for GetExecutionEmailRequests -func NewGetExecutionEmailRequestsRequest(server string, id string, params *GetExecutionEmailRequestsParams) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/executions/%s/email-requests", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.Limit != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "limit", *params.Limit, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - if params.Offset != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "offset", *params.Offset, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetExecutionLogsRequest generates requests for GetExecutionLogs -func NewGetExecutionLogsRequest(server string, id string, params *GetExecutionLogsParams) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/executions/%s/logs", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.Limit != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "limit", *params.Limit, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - if params.Offset != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "offset", *params.Offset, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewListFunctionsRequest generates requests for ListFunctions -func NewListFunctionsRequest(server string, params *ListFunctionsParams) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.Limit != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "limit", *params.Limit, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - if params.Offset != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "offset", *params.Offset, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewCreateFunctionRequest calls the generic CreateFunction builder with application/json body -func NewCreateFunctionRequest(server string, body CreateFunctionJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewCreateFunctionRequestWithBody(server, "application/json", bodyReader) -} - -// NewCreateFunctionRequestWithBody generates requests for CreateFunction with any type of body -func NewCreateFunctionRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewDeleteFunctionRequest generates requests for DeleteFunction -func NewDeleteFunctionRequest(server string, id string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("DELETE", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetFunctionRequest generates requests for GetFunction -func NewGetFunctionRequest(server string, id string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewUpdateFunctionRequest calls the generic UpdateFunction builder with application/json body -func NewUpdateFunctionRequest(server string, id string, body UpdateFunctionJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewUpdateFunctionRequestWithBody(server, id, "application/json", bodyReader) -} - -// NewUpdateFunctionRequestWithBody generates requests for UpdateFunction with any type of body -func NewUpdateFunctionRequestWithBody(server string, id string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("PUT", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewGetVersionDiffRequest generates requests for GetVersionDiff -func NewGetVersionDiffRequest(server string, id string, v1 int, v2 int) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - var pathParam1 string - - pathParam1, err = runtime.StyleParamWithOptions("simple", false, "v1", v1, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "integer", Format: ""}) - if err != nil { - return nil, err - } - - var pathParam2 string - - pathParam2, err = runtime.StyleParamWithOptions("simple", false, "v2", v2, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "integer", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/diff/%s/%s", pathParam0, pathParam1, pathParam2) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewUpdateEnvVarsRequest calls the generic UpdateEnvVars builder with application/json body -func NewUpdateEnvVarsRequest(server string, id string, body UpdateEnvVarsJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewUpdateEnvVarsRequestWithBody(server, id, "application/json", bodyReader) -} - -// NewUpdateEnvVarsRequestWithBody generates requests for UpdateEnvVars with any type of body -func NewUpdateEnvVarsRequestWithBody(server string, id string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/env", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("PUT", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewListExecutionsRequest generates requests for ListExecutions -func NewListExecutionsRequest(server string, id string, params *ListExecutionsParams) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/executions", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.Limit != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "limit", *params.Limit, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - if params.Offset != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "offset", *params.Offset, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewUpdateKVRequest calls the generic UpdateKV builder with application/json body -func NewUpdateKVRequest(server string, id string, body UpdateKVJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewUpdateKVRequestWithBody(server, id, "application/json", bodyReader) -} - -// NewUpdateKVRequestWithBody generates requests for UpdateKV with any type of body -func NewUpdateKVRequestWithBody(server string, id string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/kv", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewGetNextRunRequest generates requests for GetNextRun -func NewGetNextRunRequest(server string, id string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/next-run", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewListVersionsRequest generates requests for ListVersions -func NewListVersionsRequest(server string, id string, params *ListVersionsParams) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/versions", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.Limit != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "limit", *params.Limit, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - if params.Offset != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "offset", *params.Offset, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "integer", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewDeleteVersionRequest generates requests for DeleteVersion -func NewDeleteVersionRequest(server string, id string, versionId string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - var pathParam1 string - - pathParam1, err = runtime.StyleParamWithOptions("simple", false, "versionId", versionId, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/versions/%s", pathParam0, pathParam1) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("DELETE", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewActivateVersionRequest generates requests for ActivateVersion -func NewActivateVersionRequest(server string, id string, versionId string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - var pathParam1 string - - pathParam1, err = runtime.StyleParamWithOptions("simple", false, "versionId", versionId, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/versions/%s/activate", pathParam0, pathParam1) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetVersionRequest generates requests for GetVersion -func NewGetVersionRequest(server string, id string, version int) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - var pathParam1 string - - pathParam1, err = runtime.StyleParamWithOptions("simple", false, "version", version, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "integer", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/functions/%s/versions/%s", pathParam0, pathParam1) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewListTokensRequest generates requests for ListTokens -func NewListTokensRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/tokens") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewRevokeTokenRequest generates requests for RevokeToken -func NewRevokeTokenRequest(server string, id string) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "id", id, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/api/tokens/%s/revoke", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewExecuteFunctionDeleteRequest generates requests for ExecuteFunctionDelete -func NewExecuteFunctionDeleteRequest(server string, functionId string, params *ExecuteFunctionDeleteParams) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "function_id", functionId, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/fn/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.QueryParameters != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "query parameters", *params.QueryParameters, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "object", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("DELETE", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewExecuteFunctionGetRequest generates requests for ExecuteFunctionGet -func NewExecuteFunctionGetRequest(server string, functionId string, params *ExecuteFunctionGetParams) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "function_id", functionId, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/fn/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.QueryParameters != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "query parameters", *params.QueryParameters, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "object", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewExecuteFunctionPostRequestWithBody generates requests for ExecuteFunctionPost with any type of body -func NewExecuteFunctionPostRequestWithBody(server string, functionId string, params *ExecuteFunctionPostParams, contentType string, body io.Reader) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "function_id", functionId, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/fn/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.QueryParameters != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "query parameters", *params.QueryParameters, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "object", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewExecuteFunctionPutRequestWithBody generates requests for ExecuteFunctionPut with any type of body -func NewExecuteFunctionPutRequestWithBody(server string, functionId string, params *ExecuteFunctionPutParams, contentType string, body io.Reader) (*http.Request, error) { - var err error - - var pathParam0 string - - pathParam0, err = runtime.StyleParamWithOptions("simple", false, "function_id", functionId, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationPath, Type: "string", Format: ""}) - if err != nil { - return nil, err - } - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/fn/%s", pathParam0) - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - if params != nil { - queryValues := queryURL.Query() - - if params.QueryParameters != nil { - - if queryFrag, err := runtime.StyleParamWithOptions("form", true, "query parameters", *params.QueryParameters, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "object", Format: ""}); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - - queryURL.RawQuery = queryValues.Encode() - } - - req, err := http.NewRequest("PUT", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { - for _, r := range c.RequestEditors { - if err := r(ctx, req); err != nil { - return err - } - } - for _, r := range additionalEditors { - if err := r(ctx, req); err != nil { - return err - } - } - return nil -} - -// ClientWithResponses builds on ClientInterface to offer response payloads -type ClientWithResponses struct { - ClientInterface -} - -// NewClientWithResponses creates a new ClientWithResponses, which wraps -// Client with return type handling -func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { - client, err := NewClient(server, opts...) - if err != nil { - return nil, err - } - return &ClientWithResponses{client}, nil -} - -// WithBaseURL overrides the baseURL. -func WithBaseURL(baseURL string) ClientOption { - return func(c *Client) error { - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} - -// ClientWithResponsesInterface is the interface specification for the client with responses above. -type ClientWithResponsesInterface interface { - // DeviceApproveStatusWithResponse request - DeviceApproveStatusWithResponse(ctx context.Context, params *DeviceApproveStatusParams, reqEditors ...RequestEditorFn) (*DeviceApproveStatusResult, error) - - // DeviceApproveWithBodyWithResponse request with any body - DeviceApproveWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeviceApproveResult, error) - - DeviceApproveWithResponse(ctx context.Context, body DeviceApproveJSONRequestBody, reqEditors ...RequestEditorFn) (*DeviceApproveResult, error) - - // DeviceRequestWithResponse request - DeviceRequestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DeviceRequestResult, error) - - // DeviceTokenWithResponse request - DeviceTokenWithResponse(ctx context.Context, params *DeviceTokenParams, reqEditors ...RequestEditorFn) (*DeviceTokenResult, error) - - // LoginWithBodyWithResponse request with any body - LoginWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*LoginResult, error) - - LoginWithResponse(ctx context.Context, body LoginJSONRequestBody, reqEditors ...RequestEditorFn) (*LoginResult, error) - - // LogoutWithResponse request - LogoutWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*LogoutResult, error) - - // GetExecutionWithResponse request - GetExecutionWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*GetExecutionResult, error) - - // GetExecutionAIRequestsWithResponse request - GetExecutionAIRequestsWithResponse(ctx context.Context, id string, params *GetExecutionAIRequestsParams, reqEditors ...RequestEditorFn) (*GetExecutionAIRequestsResult, error) - - // GetExecutionEmailRequestsWithResponse request - GetExecutionEmailRequestsWithResponse(ctx context.Context, id string, params *GetExecutionEmailRequestsParams, reqEditors ...RequestEditorFn) (*GetExecutionEmailRequestsResult, error) - - // GetExecutionLogsWithResponse request - GetExecutionLogsWithResponse(ctx context.Context, id string, params *GetExecutionLogsParams, reqEditors ...RequestEditorFn) (*GetExecutionLogsResult, error) - - // ListFunctionsWithResponse request - ListFunctionsWithResponse(ctx context.Context, params *ListFunctionsParams, reqEditors ...RequestEditorFn) (*ListFunctionsResult, error) - - // CreateFunctionWithBodyWithResponse request with any body - CreateFunctionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateFunctionResult, error) - - CreateFunctionWithResponse(ctx context.Context, body CreateFunctionJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateFunctionResult, error) - - // DeleteFunctionWithResponse request - DeleteFunctionWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*DeleteFunctionResult, error) - - // GetFunctionWithResponse request - GetFunctionWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*GetFunctionResult, error) - - // UpdateFunctionWithBodyWithResponse request with any body - UpdateFunctionWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateFunctionResult, error) - - UpdateFunctionWithResponse(ctx context.Context, id string, body UpdateFunctionJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateFunctionResult, error) - - // GetVersionDiffWithResponse request - GetVersionDiffWithResponse(ctx context.Context, id string, v1 int, v2 int, reqEditors ...RequestEditorFn) (*GetVersionDiffResult, error) - - // UpdateEnvVarsWithBodyWithResponse request with any body - UpdateEnvVarsWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateEnvVarsResult, error) - - UpdateEnvVarsWithResponse(ctx context.Context, id string, body UpdateEnvVarsJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateEnvVarsResult, error) - - // ListExecutionsWithResponse request - ListExecutionsWithResponse(ctx context.Context, id string, params *ListExecutionsParams, reqEditors ...RequestEditorFn) (*ListExecutionsResult, error) - - // UpdateKVWithBodyWithResponse request with any body - UpdateKVWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateKVResult, error) - - UpdateKVWithResponse(ctx context.Context, id string, body UpdateKVJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateKVResult, error) - - // GetNextRunWithResponse request - GetNextRunWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*GetNextRunResult, error) - - // ListVersionsWithResponse request - ListVersionsWithResponse(ctx context.Context, id string, params *ListVersionsParams, reqEditors ...RequestEditorFn) (*ListVersionsResult, error) - - // DeleteVersionWithResponse request - DeleteVersionWithResponse(ctx context.Context, id string, versionId string, reqEditors ...RequestEditorFn) (*DeleteVersionResult, error) - - // ActivateVersionWithResponse request - ActivateVersionWithResponse(ctx context.Context, id string, versionId string, reqEditors ...RequestEditorFn) (*ActivateVersionResult, error) - - // GetVersionWithResponse request - GetVersionWithResponse(ctx context.Context, id string, version int, reqEditors ...RequestEditorFn) (*GetVersionResult, error) - - // ListTokensWithResponse request - ListTokensWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*ListTokensResult, error) - - // RevokeTokenWithResponse request - RevokeTokenWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*RevokeTokenResult, error) - - // ExecuteFunctionDeleteWithResponse request - ExecuteFunctionDeleteWithResponse(ctx context.Context, functionId string, params *ExecuteFunctionDeleteParams, reqEditors ...RequestEditorFn) (*ExecuteFunctionDeleteResult, error) - - // ExecuteFunctionGetWithResponse request - ExecuteFunctionGetWithResponse(ctx context.Context, functionId string, params *ExecuteFunctionGetParams, reqEditors ...RequestEditorFn) (*ExecuteFunctionGetResult, error) - - // ExecuteFunctionPostWithBodyWithResponse request with any body - ExecuteFunctionPostWithBodyWithResponse(ctx context.Context, functionId string, params *ExecuteFunctionPostParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ExecuteFunctionPostResult, error) - - // ExecuteFunctionPutWithBodyWithResponse request with any body - ExecuteFunctionPutWithBodyWithResponse(ctx context.Context, functionId string, params *ExecuteFunctionPutParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ExecuteFunctionPutResult, error) -} - -type DeviceApproveStatusResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *DeviceApproveStatusResponse - JSON401 *ErrorResponse - JSON404 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r DeviceApproveStatusResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r DeviceApproveStatusResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type DeviceApproveResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *struct { - Status *DeviceApprove200Status `json:"status,omitempty"` - } - JSON400 *ErrorResponse - JSON401 *ErrorResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} -type DeviceApprove200Status string - -// Status returns HTTPResponse.Status -func (r DeviceApproveResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r DeviceApproveResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type DeviceRequestResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *DeviceRequestResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r DeviceRequestResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r DeviceRequestResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type DeviceTokenResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *DeviceTokenResponse - JSON400 *ErrorResponse - JSON404 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r DeviceTokenResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r DeviceTokenResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type LoginResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *LoginResponse - JSON400 *LoginResponse - JSON401 *LoginResponse -} - -// Status returns HTTPResponse.Status -func (r LoginResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r LoginResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type LogoutResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *LoginResponse -} - -// Status returns HTTPResponse.Status -func (r LogoutResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r LogoutResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetExecutionResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *Execution - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r GetExecutionResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetExecutionResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetExecutionAIRequestsResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ListAIRequestsResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r GetExecutionAIRequestsResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetExecutionAIRequestsResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetExecutionEmailRequestsResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ListEmailRequestsResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r GetExecutionEmailRequestsResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetExecutionEmailRequestsResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetExecutionLogsResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ExecutionWithLogs - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r GetExecutionLogsResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetExecutionLogsResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ListFunctionsResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ListFunctionsResponse - JSON401 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ListFunctionsResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ListFunctionsResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type CreateFunctionResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *FunctionWithActiveVersion - JSON400 *ErrorResponse - JSON401 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r CreateFunctionResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r CreateFunctionResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type DeleteFunctionResult struct { - Body []byte - HTTPResponse *http.Response - JSON401 *ErrorResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r DeleteFunctionResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r DeleteFunctionResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetFunctionResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *FunctionWithActiveVersion - JSON401 *ErrorResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r GetFunctionResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetFunctionResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type UpdateFunctionResult struct { - Body []byte - HTTPResponse *http.Response - JSON400 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r UpdateFunctionResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r UpdateFunctionResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetVersionDiffResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *VersionDiffResponse - JSON401 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r GetVersionDiffResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetVersionDiffResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type UpdateEnvVarsResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *FunctionVersion - JSON400 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r UpdateEnvVarsResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r UpdateEnvVarsResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ListExecutionsResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ListExecutionsResponse - JSON401 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ListExecutionsResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ListExecutionsResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type UpdateKVResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *FunctionVersion - JSON400 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r UpdateKVResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r UpdateKVResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetNextRunResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *NextRunResponse - JSON401 *ErrorResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r GetNextRunResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetNextRunResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ListVersionsResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ListVersionsResponse - JSON401 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ListVersionsResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ListVersionsResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type DeleteVersionResult struct { - Body []byte - HTTPResponse *http.Response - JSON400 *ErrorResponse - JSON401 *ErrorResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r DeleteVersionResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r DeleteVersionResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ActivateVersionResult struct { - Body []byte - HTTPResponse *http.Response - JSON401 *ErrorResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ActivateVersionResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ActivateVersionResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetVersionResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *FunctionVersion - JSON401 *ErrorResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r GetVersionResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetVersionResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ListTokensResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ListAPITokensResponse - JSON401 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ListTokensResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ListTokensResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type RevokeTokenResult struct { - Body []byte - HTTPResponse *http.Response - JSON200 *struct { - Status *string `json:"status,omitempty"` - } - JSON401 *ErrorResponse - JSON404 *ErrorResponse - JSON500 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r RevokeTokenResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r RevokeTokenResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ExecuteFunctionDeleteResult struct { - Body []byte - HTTPResponse *http.Response - JSON403 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ExecuteFunctionDeleteResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ExecuteFunctionDeleteResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ExecuteFunctionGetResult struct { - Body []byte - HTTPResponse *http.Response - JSON403 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ExecuteFunctionGetResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ExecuteFunctionGetResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ExecuteFunctionPostResult struct { - Body []byte - HTTPResponse *http.Response - JSON403 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ExecuteFunctionPostResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ExecuteFunctionPostResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type ExecuteFunctionPutResult struct { - Body []byte - HTTPResponse *http.Response - JSON403 *ErrorResponse -} - -// Status returns HTTPResponse.Status -func (r ExecuteFunctionPutResult) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r ExecuteFunctionPutResult) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// DeviceApproveStatusWithResponse request returning *DeviceApproveStatusResult -func (c *ClientWithResponses) DeviceApproveStatusWithResponse(ctx context.Context, params *DeviceApproveStatusParams, reqEditors ...RequestEditorFn) (*DeviceApproveStatusResult, error) { - rsp, err := c.DeviceApproveStatus(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseDeviceApproveStatusResult(rsp) -} - -// DeviceApproveWithBodyWithResponse request with arbitrary body returning *DeviceApproveResult -func (c *ClientWithResponses) DeviceApproveWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*DeviceApproveResult, error) { - rsp, err := c.DeviceApproveWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseDeviceApproveResult(rsp) -} - -func (c *ClientWithResponses) DeviceApproveWithResponse(ctx context.Context, body DeviceApproveJSONRequestBody, reqEditors ...RequestEditorFn) (*DeviceApproveResult, error) { - rsp, err := c.DeviceApprove(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseDeviceApproveResult(rsp) -} - -// DeviceRequestWithResponse request returning *DeviceRequestResult -func (c *ClientWithResponses) DeviceRequestWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*DeviceRequestResult, error) { - rsp, err := c.DeviceRequest(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParseDeviceRequestResult(rsp) -} - -// DeviceTokenWithResponse request returning *DeviceTokenResult -func (c *ClientWithResponses) DeviceTokenWithResponse(ctx context.Context, params *DeviceTokenParams, reqEditors ...RequestEditorFn) (*DeviceTokenResult, error) { - rsp, err := c.DeviceToken(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseDeviceTokenResult(rsp) -} - -// LoginWithBodyWithResponse request with arbitrary body returning *LoginResult -func (c *ClientWithResponses) LoginWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*LoginResult, error) { - rsp, err := c.LoginWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseLoginResult(rsp) -} - -func (c *ClientWithResponses) LoginWithResponse(ctx context.Context, body LoginJSONRequestBody, reqEditors ...RequestEditorFn) (*LoginResult, error) { - rsp, err := c.Login(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseLoginResult(rsp) -} - -// LogoutWithResponse request returning *LogoutResult -func (c *ClientWithResponses) LogoutWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*LogoutResult, error) { - rsp, err := c.Logout(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParseLogoutResult(rsp) -} - -// GetExecutionWithResponse request returning *GetExecutionResult -func (c *ClientWithResponses) GetExecutionWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*GetExecutionResult, error) { - rsp, err := c.GetExecution(ctx, id, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetExecutionResult(rsp) -} - -// GetExecutionAIRequestsWithResponse request returning *GetExecutionAIRequestsResult -func (c *ClientWithResponses) GetExecutionAIRequestsWithResponse(ctx context.Context, id string, params *GetExecutionAIRequestsParams, reqEditors ...RequestEditorFn) (*GetExecutionAIRequestsResult, error) { - rsp, err := c.GetExecutionAIRequests(ctx, id, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetExecutionAIRequestsResult(rsp) -} - -// GetExecutionEmailRequestsWithResponse request returning *GetExecutionEmailRequestsResult -func (c *ClientWithResponses) GetExecutionEmailRequestsWithResponse(ctx context.Context, id string, params *GetExecutionEmailRequestsParams, reqEditors ...RequestEditorFn) (*GetExecutionEmailRequestsResult, error) { - rsp, err := c.GetExecutionEmailRequests(ctx, id, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetExecutionEmailRequestsResult(rsp) -} - -// GetExecutionLogsWithResponse request returning *GetExecutionLogsResult -func (c *ClientWithResponses) GetExecutionLogsWithResponse(ctx context.Context, id string, params *GetExecutionLogsParams, reqEditors ...RequestEditorFn) (*GetExecutionLogsResult, error) { - rsp, err := c.GetExecutionLogs(ctx, id, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetExecutionLogsResult(rsp) -} - -// ListFunctionsWithResponse request returning *ListFunctionsResult -func (c *ClientWithResponses) ListFunctionsWithResponse(ctx context.Context, params *ListFunctionsParams, reqEditors ...RequestEditorFn) (*ListFunctionsResult, error) { - rsp, err := c.ListFunctions(ctx, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseListFunctionsResult(rsp) -} - -// CreateFunctionWithBodyWithResponse request with arbitrary body returning *CreateFunctionResult -func (c *ClientWithResponses) CreateFunctionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateFunctionResult, error) { - rsp, err := c.CreateFunctionWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseCreateFunctionResult(rsp) -} - -func (c *ClientWithResponses) CreateFunctionWithResponse(ctx context.Context, body CreateFunctionJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateFunctionResult, error) { - rsp, err := c.CreateFunction(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseCreateFunctionResult(rsp) -} - -// DeleteFunctionWithResponse request returning *DeleteFunctionResult -func (c *ClientWithResponses) DeleteFunctionWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*DeleteFunctionResult, error) { - rsp, err := c.DeleteFunction(ctx, id, reqEditors...) - if err != nil { - return nil, err - } - return ParseDeleteFunctionResult(rsp) -} - -// GetFunctionWithResponse request returning *GetFunctionResult -func (c *ClientWithResponses) GetFunctionWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*GetFunctionResult, error) { - rsp, err := c.GetFunction(ctx, id, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetFunctionResult(rsp) -} - -// UpdateFunctionWithBodyWithResponse request with arbitrary body returning *UpdateFunctionResult -func (c *ClientWithResponses) UpdateFunctionWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateFunctionResult, error) { - rsp, err := c.UpdateFunctionWithBody(ctx, id, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateFunctionResult(rsp) -} - -func (c *ClientWithResponses) UpdateFunctionWithResponse(ctx context.Context, id string, body UpdateFunctionJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateFunctionResult, error) { - rsp, err := c.UpdateFunction(ctx, id, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateFunctionResult(rsp) -} - -// GetVersionDiffWithResponse request returning *GetVersionDiffResult -func (c *ClientWithResponses) GetVersionDiffWithResponse(ctx context.Context, id string, v1 int, v2 int, reqEditors ...RequestEditorFn) (*GetVersionDiffResult, error) { - rsp, err := c.GetVersionDiff(ctx, id, v1, v2, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetVersionDiffResult(rsp) -} - -// UpdateEnvVarsWithBodyWithResponse request with arbitrary body returning *UpdateEnvVarsResult -func (c *ClientWithResponses) UpdateEnvVarsWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateEnvVarsResult, error) { - rsp, err := c.UpdateEnvVarsWithBody(ctx, id, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateEnvVarsResult(rsp) -} - -func (c *ClientWithResponses) UpdateEnvVarsWithResponse(ctx context.Context, id string, body UpdateEnvVarsJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateEnvVarsResult, error) { - rsp, err := c.UpdateEnvVars(ctx, id, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateEnvVarsResult(rsp) -} - -// ListExecutionsWithResponse request returning *ListExecutionsResult -func (c *ClientWithResponses) ListExecutionsWithResponse(ctx context.Context, id string, params *ListExecutionsParams, reqEditors ...RequestEditorFn) (*ListExecutionsResult, error) { - rsp, err := c.ListExecutions(ctx, id, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseListExecutionsResult(rsp) -} - -// UpdateKVWithBodyWithResponse request with arbitrary body returning *UpdateKVResult -func (c *ClientWithResponses) UpdateKVWithBodyWithResponse(ctx context.Context, id string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateKVResult, error) { - rsp, err := c.UpdateKVWithBody(ctx, id, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateKVResult(rsp) -} - -func (c *ClientWithResponses) UpdateKVWithResponse(ctx context.Context, id string, body UpdateKVJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateKVResult, error) { - rsp, err := c.UpdateKV(ctx, id, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseUpdateKVResult(rsp) -} - -// GetNextRunWithResponse request returning *GetNextRunResult -func (c *ClientWithResponses) GetNextRunWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*GetNextRunResult, error) { - rsp, err := c.GetNextRun(ctx, id, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetNextRunResult(rsp) -} - -// ListVersionsWithResponse request returning *ListVersionsResult -func (c *ClientWithResponses) ListVersionsWithResponse(ctx context.Context, id string, params *ListVersionsParams, reqEditors ...RequestEditorFn) (*ListVersionsResult, error) { - rsp, err := c.ListVersions(ctx, id, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseListVersionsResult(rsp) -} - -// DeleteVersionWithResponse request returning *DeleteVersionResult -func (c *ClientWithResponses) DeleteVersionWithResponse(ctx context.Context, id string, versionId string, reqEditors ...RequestEditorFn) (*DeleteVersionResult, error) { - rsp, err := c.DeleteVersion(ctx, id, versionId, reqEditors...) - if err != nil { - return nil, err - } - return ParseDeleteVersionResult(rsp) -} - -// ActivateVersionWithResponse request returning *ActivateVersionResult -func (c *ClientWithResponses) ActivateVersionWithResponse(ctx context.Context, id string, versionId string, reqEditors ...RequestEditorFn) (*ActivateVersionResult, error) { - rsp, err := c.ActivateVersion(ctx, id, versionId, reqEditors...) - if err != nil { - return nil, err - } - return ParseActivateVersionResult(rsp) -} - -// GetVersionWithResponse request returning *GetVersionResult -func (c *ClientWithResponses) GetVersionWithResponse(ctx context.Context, id string, version int, reqEditors ...RequestEditorFn) (*GetVersionResult, error) { - rsp, err := c.GetVersion(ctx, id, version, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetVersionResult(rsp) -} - -// ListTokensWithResponse request returning *ListTokensResult -func (c *ClientWithResponses) ListTokensWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*ListTokensResult, error) { - rsp, err := c.ListTokens(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParseListTokensResult(rsp) -} - -// RevokeTokenWithResponse request returning *RevokeTokenResult -func (c *ClientWithResponses) RevokeTokenWithResponse(ctx context.Context, id string, reqEditors ...RequestEditorFn) (*RevokeTokenResult, error) { - rsp, err := c.RevokeToken(ctx, id, reqEditors...) - if err != nil { - return nil, err - } - return ParseRevokeTokenResult(rsp) -} - -// ExecuteFunctionDeleteWithResponse request returning *ExecuteFunctionDeleteResult -func (c *ClientWithResponses) ExecuteFunctionDeleteWithResponse(ctx context.Context, functionId string, params *ExecuteFunctionDeleteParams, reqEditors ...RequestEditorFn) (*ExecuteFunctionDeleteResult, error) { - rsp, err := c.ExecuteFunctionDelete(ctx, functionId, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseExecuteFunctionDeleteResult(rsp) -} - -// ExecuteFunctionGetWithResponse request returning *ExecuteFunctionGetResult -func (c *ClientWithResponses) ExecuteFunctionGetWithResponse(ctx context.Context, functionId string, params *ExecuteFunctionGetParams, reqEditors ...RequestEditorFn) (*ExecuteFunctionGetResult, error) { - rsp, err := c.ExecuteFunctionGet(ctx, functionId, params, reqEditors...) - if err != nil { - return nil, err - } - return ParseExecuteFunctionGetResult(rsp) -} - -// ExecuteFunctionPostWithBodyWithResponse request with arbitrary body returning *ExecuteFunctionPostResult -func (c *ClientWithResponses) ExecuteFunctionPostWithBodyWithResponse(ctx context.Context, functionId string, params *ExecuteFunctionPostParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ExecuteFunctionPostResult, error) { - rsp, err := c.ExecuteFunctionPostWithBody(ctx, functionId, params, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseExecuteFunctionPostResult(rsp) -} - -// ExecuteFunctionPutWithBodyWithResponse request with arbitrary body returning *ExecuteFunctionPutResult -func (c *ClientWithResponses) ExecuteFunctionPutWithBodyWithResponse(ctx context.Context, functionId string, params *ExecuteFunctionPutParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ExecuteFunctionPutResult, error) { - rsp, err := c.ExecuteFunctionPutWithBody(ctx, functionId, params, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParseExecuteFunctionPutResult(rsp) -} - -// ParseDeviceApproveStatusResult parses an HTTP response from a DeviceApproveStatusWithResponse call -func ParseDeviceApproveStatusResult(rsp *http.Response) (*DeviceApproveStatusResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &DeviceApproveStatusResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest DeviceApproveStatusResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - } - - return response, nil -} - -// ParseDeviceApproveResult parses an HTTP response from a DeviceApproveWithResponse call -func ParseDeviceApproveResult(rsp *http.Response) (*DeviceApproveResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &DeviceApproveResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest struct { - Status *DeviceApprove200Status `json:"status,omitempty"` - } - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseDeviceRequestResult parses an HTTP response from a DeviceRequestWithResponse call -func ParseDeviceRequestResult(rsp *http.Response) (*DeviceRequestResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &DeviceRequestResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest DeviceRequestResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseDeviceTokenResult parses an HTTP response from a DeviceTokenWithResponse call -func ParseDeviceTokenResult(rsp *http.Response) (*DeviceTokenResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &DeviceTokenResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest DeviceTokenResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - } - - return response, nil -} - -// ParseLoginResult parses an HTTP response from a LoginWithResponse call -func ParseLoginResult(rsp *http.Response) (*LoginResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &LoginResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest LoginResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest LoginResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest LoginResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - } - - return response, nil -} - -// ParseLogoutResult parses an HTTP response from a LogoutWithResponse call -func ParseLogoutResult(rsp *http.Response) (*LogoutResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &LogoutResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest LoginResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParseGetExecutionResult parses an HTTP response from a GetExecutionWithResponse call -func ParseGetExecutionResult(rsp *http.Response) (*GetExecutionResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetExecutionResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest Execution - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseGetExecutionAIRequestsResult parses an HTTP response from a GetExecutionAIRequestsWithResponse call -func ParseGetExecutionAIRequestsResult(rsp *http.Response) (*GetExecutionAIRequestsResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetExecutionAIRequestsResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ListAIRequestsResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseGetExecutionEmailRequestsResult parses an HTTP response from a GetExecutionEmailRequestsWithResponse call -func ParseGetExecutionEmailRequestsResult(rsp *http.Response) (*GetExecutionEmailRequestsResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetExecutionEmailRequestsResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ListEmailRequestsResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseGetExecutionLogsResult parses an HTTP response from a GetExecutionLogsWithResponse call -func ParseGetExecutionLogsResult(rsp *http.Response) (*GetExecutionLogsResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetExecutionLogsResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ExecutionWithLogs - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseListFunctionsResult parses an HTTP response from a ListFunctionsWithResponse call -func ParseListFunctionsResult(rsp *http.Response) (*ListFunctionsResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ListFunctionsResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ListFunctionsResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseCreateFunctionResult parses an HTTP response from a CreateFunctionWithResponse call -func ParseCreateFunctionResult(rsp *http.Response) (*CreateFunctionResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &CreateFunctionResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionWithActiveVersion - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseDeleteFunctionResult parses an HTTP response from a DeleteFunctionWithResponse call -func ParseDeleteFunctionResult(rsp *http.Response) (*DeleteFunctionResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &DeleteFunctionResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseGetFunctionResult parses an HTTP response from a GetFunctionWithResponse call -func ParseGetFunctionResult(rsp *http.Response) (*GetFunctionResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetFunctionResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionWithActiveVersion - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseUpdateFunctionResult parses an HTTP response from a UpdateFunctionWithResponse call -func ParseUpdateFunctionResult(rsp *http.Response) (*UpdateFunctionResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &UpdateFunctionResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseGetVersionDiffResult parses an HTTP response from a GetVersionDiffWithResponse call -func ParseGetVersionDiffResult(rsp *http.Response) (*GetVersionDiffResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetVersionDiffResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest VersionDiffResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseUpdateEnvVarsResult parses an HTTP response from a UpdateEnvVarsWithResponse call -func ParseUpdateEnvVarsResult(rsp *http.Response) (*UpdateEnvVarsResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &UpdateEnvVarsResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionVersion - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseListExecutionsResult parses an HTTP response from a ListExecutionsWithResponse call -func ParseListExecutionsResult(rsp *http.Response) (*ListExecutionsResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ListExecutionsResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ListExecutionsResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseUpdateKVResult parses an HTTP response from a UpdateKVWithResponse call -func ParseUpdateKVResult(rsp *http.Response) (*UpdateKVResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &UpdateKVResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionVersion - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseGetNextRunResult parses an HTTP response from a GetNextRunWithResponse call -func ParseGetNextRunResult(rsp *http.Response) (*GetNextRunResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetNextRunResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest NextRunResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseListVersionsResult parses an HTTP response from a ListVersionsWithResponse call -func ParseListVersionsResult(rsp *http.Response) (*ListVersionsResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ListVersionsResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ListVersionsResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseDeleteVersionResult parses an HTTP response from a DeleteVersionWithResponse call -func ParseDeleteVersionResult(rsp *http.Response) (*DeleteVersionResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &DeleteVersionResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseActivateVersionResult parses an HTTP response from a ActivateVersionWithResponse call -func ParseActivateVersionResult(rsp *http.Response) (*ActivateVersionResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ActivateVersionResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseGetVersionResult parses an HTTP response from a GetVersionWithResponse call -func ParseGetVersionResult(rsp *http.Response) (*GetVersionResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetVersionResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionVersion - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseListTokensResult parses an HTTP response from a ListTokensWithResponse call -func ParseListTokensResult(rsp *http.Response) (*ListTokensResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ListTokensResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ListAPITokensResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseRevokeTokenResult parses an HTTP response from a RevokeTokenWithResponse call -func ParseRevokeTokenResult(rsp *http.Response) (*RevokeTokenResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &RevokeTokenResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest struct { - Status *string `json:"status,omitempty"` - } - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON401 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON404 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON500 = &dest - - } - - return response, nil -} - -// ParseExecuteFunctionDeleteResult parses an HTTP response from a ExecuteFunctionDeleteWithResponse call -func ParseExecuteFunctionDeleteResult(rsp *http.Response) (*ExecuteFunctionDeleteResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ExecuteFunctionDeleteResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON403 = &dest - - } - - return response, nil -} - -// ParseExecuteFunctionGetResult parses an HTTP response from a ExecuteFunctionGetWithResponse call -func ParseExecuteFunctionGetResult(rsp *http.Response) (*ExecuteFunctionGetResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ExecuteFunctionGetResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON403 = &dest - - } - - return response, nil -} - -// ParseExecuteFunctionPostResult parses an HTTP response from a ExecuteFunctionPostWithResponse call -func ParseExecuteFunctionPostResult(rsp *http.Response) (*ExecuteFunctionPostResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ExecuteFunctionPostResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON403 = &dest - - } - - return response, nil -} - -// ParseExecuteFunctionPutResult parses an HTTP response from a ExecuteFunctionPutWithResponse call -func ParseExecuteFunctionPutResult(rsp *http.Response) (*ExecuteFunctionPutResult, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &ExecuteFunctionPutResult{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: - var dest ErrorResponse - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON403 = &dest - - } - - return response, nil -} diff --git a/lunar-cli/client/generate.go b/lunar-cli/client/generate.go deleted file mode 100644 index 393320a..0000000 --- a/lunar-cli/client/generate.go +++ /dev/null @@ -1,3 +0,0 @@ -package client - -//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=oapi-codegen.yaml ../../internal/api/docs/openapi.yaml diff --git a/lunar-cli/client/oapi-codegen.yaml b/lunar-cli/client/oapi-codegen.yaml deleted file mode 100644 index 1087653..0000000 --- a/lunar-cli/client/oapi-codegen.yaml +++ /dev/null @@ -1,7 +0,0 @@ -package: client -generate: - client: true - models: true -output: client.gen.go -output-options: - response-type-suffix: Result diff --git a/lunar-cli/cmd/auth.go b/lunar-cli/cmd/auth.go index c6731f5..f352f2f 100644 --- a/lunar-cli/cmd/auth.go +++ b/lunar-cli/cmd/auth.go @@ -1,16 +1,40 @@ package cmd import ( + "bytes" + "context" + "encoding/json" "fmt" + "io" + "net/http" + "net/url" "os/exec" "runtime" "time" - "github.com/dimiro1/lunar/lunar-cli/client" "github.com/dimiro1/lunar/lunar-cli/config" "github.com/spf13/cobra" ) +// Device authorization flow stays REST: it runs before the CLI is +// authenticated and maps poorly to GraphQL (it sets up the very token a +// GraphQL request would need). These two endpoints live under /api/auth/*. + +// deviceRequestResponse mirrors the server's POST /api/auth/device-request body. +type deviceRequestResponse struct { + DeviceCode string `json:"device_code"` + UserCode string `json:"user_code"` + ApprovalURL string `json:"approval_url"` + ExpiresIn int `json:"expires_in"` + Interval int `json:"interval"` +} + +// deviceTokenResponse mirrors the server's GET /api/auth/device-token body. +type deviceTokenResponse struct { + Status string `json:"status"` + Token string `json:"token"` +} + var loginCmd = &cobra.Command{ Use: "login", Short: "Authenticate via device authorization flow", @@ -29,21 +53,16 @@ func init() { } func runLogin(cmd *cobra.Command, args []string) error { - c := mustClient() out := cmd.OutOrStdout() - resp, err := c.DeviceRequestWithResponse(cmd.Context()) + req, err := requestDeviceCode(cmd.Context()) if err != nil { return fmt.Errorf("device request: %w", err) } - if resp.JSON200 == nil { - return fmt.Errorf("device request: %w", apiResponseError(resp.StatusCode(), resp.Body)) - } - req := resp.JSON200 fmt.Fprintf(out, "Your verification code: %s\n", req.UserCode) - fmt.Fprintf(out, "Open this URL to approve: %s\n", req.ApprovalUrl) - openBrowser(req.ApprovalUrl) + fmt.Fprintf(out, "Open this URL to approve: %s\n", req.ApprovalURL) + openBrowser(req.ApprovalURL) fmt.Fprint(out, "Waiting for approval") interval := time.Duration(req.Interval) * time.Second @@ -52,35 +71,31 @@ func runLogin(cmd *cobra.Command, args []string) error { for time.Now().Before(expires) { time.Sleep(interval) - tokenResp, err := c.DeviceTokenWithResponse(cmd.Context(), &client.DeviceTokenParams{ - Code: req.DeviceCode, - }) + tokenResp, err := pollDeviceToken(cmd.Context(), req.DeviceCode) if err != nil { - return fmt.Errorf("polling: %w", err) - } - if tokenResp.JSON200 == nil { fmt.Fprintln(out) - return fmt.Errorf("polling: %w", apiResponseError(tokenResp.StatusCode(), tokenResp.Body)) + return fmt.Errorf("polling: %w", err) } - switch tokenResp.JSON200.Status { + switch tokenResp.Status { case "approved": - if tokenResp.JSON200.Token == nil { + if tokenResp.Token == "" { + fmt.Fprintln(out) return fmt.Errorf("approved but no token returned") } cfg, _ := config.Load() - cfg.Token = *tokenResp.JSON200.Token - if err := config.Save(cfg); err != nil { - return fmt.Errorf("saving token: %w", err) - } - fmt.Fprintln(out, "\nAuthentication successful. Token saved.") - return nil - case "denied": - fmt.Fprintln(out) - return fmt.Errorf("authorization denied") - default: - fmt.Fprint(out, ".") + cfg.Token = tokenResp.Token + if err := config.Save(cfg); err != nil { + return fmt.Errorf("saving token: %w", err) } + fmt.Fprintln(out, "\nAuthentication successful. Token saved.") + return nil + case "denied": + fmt.Fprintln(out) + return fmt.Errorf("authorization denied") + default: + fmt.Fprint(out, ".") + } } fmt.Fprintln(out) return fmt.Errorf("authorization timed out") @@ -99,6 +114,60 @@ func runLogout(cmd *cobra.Command, args []string) error { return nil } +// requestDeviceCode starts a device authorization flow via +// POST /api/auth/device-request. +func requestDeviceCode(ctx context.Context) (*deviceRequestResponse, error) { + if serverURL == "" { + return nil, fmt.Errorf("no server configured (use --server or LUNAR_SERVER)") + } + req, err := http.NewRequestWithContext(ctx, http.MethodPost, serverURL+"/api/auth/device-request", nil) + if err != nil { + return nil, err + } + var resp deviceRequestResponse + if err := doJSON(req, &resp); err != nil { + return nil, err + } + return &resp, nil +} + +// pollDeviceToken checks the status of a pending device authorization via +// GET /api/auth/device-token?code=. +func pollDeviceToken(ctx context.Context, deviceCode string) (*deviceTokenResponse, error) { + endpoint := serverURL + "/api/auth/device-token?code=" + url.QueryEscape(deviceCode) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil) + if err != nil { + return nil, err + } + var resp deviceTokenResponse + if err := doJSON(req, &resp); err != nil { + return nil, err + } + return &resp, nil +} + +// doJSON sends req and decodes a 2xx JSON body into v, turning non-2xx +// responses into an error carrying the server's message. +func doJSON(req *http.Request, v any) error { + res, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + if err != nil { + return err + } + if res.StatusCode < 200 || res.StatusCode >= 300 { + return apiResponseError(res.StatusCode, body) + } + if err := json.Unmarshal(bytes.TrimSpace(body), v); err != nil { + return fmt.Errorf("decoding response: %w", err) + } + return nil +} + var openBrowser = func(url string) { var name string var args []string diff --git a/lunar-cli/cmd/executions.gen.go b/lunar-cli/cmd/executions.gen.go deleted file mode 100644 index 443422e..0000000 --- a/lunar-cli/cmd/executions.gen.go +++ /dev/null @@ -1,175 +0,0 @@ -// Code generated by tools/gen; DO NOT EDIT. - -package cmd - -import ( - "fmt" - - "github.com/dimiro1/lunar/lunar-cli/client" - "github.com/spf13/cobra" -) - -var _ = fmt.Sprintf // suppress unused import - -var executionsCmd = &cobra.Command{ - Use: "executions", - Short: "Function execution history and logs", -} - -func init() { - rootCmd.AddCommand(executionsCmd) -} - -// ─── get ──────────────────────────────────────────────── - -var getExecutionCmd = &cobra.Command{ - Use: "get ", - Short: "Get execution details", - Args: cobra.ExactArgs(1), - RunE: runGetExecution, -} - -func init() { - executionsCmd.AddCommand(getExecutionCmd) -} - -func runGetExecution(cmd *cobra.Command, args []string) error { - c := mustClient() - resp, err := c.GetExecutionWithResponse(cmd.Context(), args[0]) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) -} - -// ─── ai-requests ──────────────────────────────────────────────── - -var getExecutionAIRequestsCmd = &cobra.Command{ - Use: "ai-requests ", - Short: "Get AI requests for an execution", - Args: cobra.ExactArgs(1), - RunE: runGetExecutionAIRequests, -} - -var ( - getExecutionAIRequestsCmdLimit int - getExecutionAIRequestsCmdOffset int -) - -func init() { - executionsCmd.AddCommand(getExecutionAIRequestsCmd) - getExecutionAIRequestsCmd.Flags().IntVar(&getExecutionAIRequestsCmdLimit, "limit", 20, "Maximum number of AI requests to return (default 20, max 100)") - getExecutionAIRequestsCmd.Flags().IntVar(&getExecutionAIRequestsCmdOffset, "offset", 0, "Number of AI requests to skip") -} - -func runGetExecutionAIRequests(cmd *cobra.Command, args []string) error { - c := mustClient() - params := &client.GetExecutionAIRequestsParams{ - Limit: &getExecutionAIRequestsCmdLimit, - Offset: &getExecutionAIRequestsCmdOffset, - } - resp, err := c.GetExecutionAIRequestsWithResponse(cmd.Context(), args[0], params) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) -} - -// ─── email-requests ──────────────────────────────────────────────── - -var getExecutionEmailRequestsCmd = &cobra.Command{ - Use: "email-requests ", - Short: "Get email requests for an execution", - Args: cobra.ExactArgs(1), - RunE: runGetExecutionEmailRequests, -} - -var ( - getExecutionEmailRequestsCmdLimit int - getExecutionEmailRequestsCmdOffset int -) - -func init() { - executionsCmd.AddCommand(getExecutionEmailRequestsCmd) - getExecutionEmailRequestsCmd.Flags().IntVar(&getExecutionEmailRequestsCmdLimit, "limit", 20, "Maximum number of email requests to return (default 20, max 100)") - getExecutionEmailRequestsCmd.Flags().IntVar(&getExecutionEmailRequestsCmdOffset, "offset", 0, "Number of email requests to skip") -} - -func runGetExecutionEmailRequests(cmd *cobra.Command, args []string) error { - c := mustClient() - params := &client.GetExecutionEmailRequestsParams{ - Limit: &getExecutionEmailRequestsCmdLimit, - Offset: &getExecutionEmailRequestsCmdOffset, - } - resp, err := c.GetExecutionEmailRequestsWithResponse(cmd.Context(), args[0], params) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) -} - -// ─── logs ──────────────────────────────────────────────── - -var getExecutionLogsCmd = &cobra.Command{ - Use: "logs ", - Short: "Get execution logs", - Args: cobra.ExactArgs(1), - RunE: runGetExecutionLogs, -} - -var ( - getExecutionLogsCmdLimit int - getExecutionLogsCmdOffset int -) - -func init() { - executionsCmd.AddCommand(getExecutionLogsCmd) - getExecutionLogsCmd.Flags().IntVar(&getExecutionLogsCmdLimit, "limit", 20, "Maximum number of log entries to return (default 20, max 100)") - getExecutionLogsCmd.Flags().IntVar(&getExecutionLogsCmdOffset, "offset", 0, "Number of log entries to skip") -} - -func runGetExecutionLogs(cmd *cobra.Command, args []string) error { - c := mustClient() - params := &client.GetExecutionLogsParams{ - Limit: &getExecutionLogsCmdLimit, - Offset: &getExecutionLogsCmdOffset, - } - resp, err := c.GetExecutionLogsWithResponse(cmd.Context(), args[0], params) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) -} - -// ─── list ──────────────────────────────────────────────── - -var listExecutionsCmd = &cobra.Command{ - Use: "list ", - Short: "List executions of a function", - Args: cobra.ExactArgs(1), - RunE: runListExecutions, -} - -var ( - listExecutionsCmdLimit int - listExecutionsCmdOffset int -) - -func init() { - executionsCmd.AddCommand(listExecutionsCmd) - listExecutionsCmd.Flags().IntVar(&listExecutionsCmdLimit, "limit", 20, "Maximum number of items to return (default 20, max 100)") - listExecutionsCmd.Flags().IntVar(&listExecutionsCmdOffset, "offset", 0, "Number of items to skip") -} - -func runListExecutions(cmd *cobra.Command, args []string) error { - c := mustClient() - params := &client.ListExecutionsParams{ - Limit: &listExecutionsCmdLimit, - Offset: &listExecutionsCmdOffset, - } - resp, err := c.ListExecutionsWithResponse(cmd.Context(), args[0], params) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) -} diff --git a/lunar-cli/cmd/executions.go b/lunar-cli/cmd/executions.go new file mode 100644 index 0000000..f29e714 --- /dev/null +++ b/lunar-cli/cmd/executions.go @@ -0,0 +1,206 @@ +package cmd + +import "github.com/spf13/cobra" + +// executionSummaryFields drops the large event/response JSON for the list view. +const executionSummaryFields = ` + id + function_id: functionId + function_version_id: functionVersionId + status + duration_ms: durationMs + error_message: errorMessage + trigger + created_at: createdAt +` + +// executionFields is the full selection for a single execution. +const executionFields = ` + id + function_id: functionId + function_version_id: functionVersionId + status + duration_ms: durationMs + error_message: errorMessage + event_json: eventJson + response_json: responseJson + trigger + created_at: createdAt +` + +const aiRequestFields = ` + id + execution_id: executionId + provider + model + endpoint + request_json: requestJson + response_json: responseJson + status + error_message: errorMessage + input_tokens: inputTokens + output_tokens: outputTokens + duration_ms: durationMs + created_at: createdAt +` + +const emailRequestFields = ` + id + execution_id: executionId + from + to + subject + has_text: hasText + has_html: hasHtml + request_json: requestJson + response_json: responseJson + status + error_message: errorMessage + email_id: emailId + duration_ms: durationMs + created_at: createdAt +` + +var executionsCmd = &cobra.Command{ + Use: "executions", + Short: "Function execution history and logs", +} + +func init() { + rootCmd.AddCommand(executionsCmd) +} + +// pageFlags registers --limit/--offset on a command and returns pointers to them. +func pageFlags(c *cobra.Command) (*int, *int) { + limit := new(int) + offset := new(int) + c.Flags().IntVar(limit, "limit", 20, "Maximum number of items to return (default 20, max 100)") + c.Flags().IntVar(offset, "offset", 0, "Number of items to skip") + return limit, offset +} + +// ─── list ──────────────────────────────────────────────── + +var listExecutionsCmd = &cobra.Command{ + Use: "list ", + Short: "List executions of a function", + Args: cobra.ExactArgs(1), + RunE: runListExecutions, +} + +var listExecutionsLimit, listExecutionsOffset *int + +func init() { + executionsCmd.AddCommand(listExecutionsCmd) + listExecutionsLimit, listExecutionsOffset = pageFlags(listExecutionsCmd) +} + +func runListExecutions(cmd *cobra.Command, args []string) error { + query := `query ($id: ID!, $limit: Int!, $offset: Int!) { + executions(functionId: $id, limit: $limit, offset: $offset) { + nodes {` + executionSummaryFields + `} + pageInfo { total limit offset } + } + }` + vars := map[string]any{"id": args[0], "limit": *listExecutionsLimit, "offset": *listExecutionsOffset} + return gqlConnection(cmd.Context(), query, vars, "executions", "executions") +} + +// ─── get ──────────────────────────────────────────────── + +var getExecutionCmd = &cobra.Command{ + Use: "get ", + Short: "Get execution details", + Args: cobra.ExactArgs(1), + RunE: runGetExecution, +} + +func init() { + executionsCmd.AddCommand(getExecutionCmd) +} + +func runGetExecution(cmd *cobra.Command, args []string) error { + query := `query ($id: ID!) { execution(id: $id) {` + executionFields + `} }` + return gqlObject(cmd.Context(), query, map[string]any{"id": args[0]}, "execution") +} + +// ─── logs ──────────────────────────────────────────────── + +var getExecutionLogsCmd = &cobra.Command{ + Use: "logs ", + Short: "Get execution logs", + Args: cobra.ExactArgs(1), + RunE: runGetExecutionLogs, +} + +var logsLimit, logsOffset *int + +func init() { + executionsCmd.AddCommand(getExecutionLogsCmd) + logsLimit, logsOffset = pageFlags(getExecutionLogsCmd) +} + +func runGetExecutionLogs(cmd *cobra.Command, args []string) error { + query := `query ($id: ID!, $limit: Int!, $offset: Int!) { + executionLogs(executionId: $id, limit: $limit, offset: $offset) { + nodes { level message created_at: createdAt } + pageInfo { total limit offset } + } + }` + vars := map[string]any{"id": args[0], "limit": *logsLimit, "offset": *logsOffset} + return gqlConnection(cmd.Context(), query, vars, "executionLogs", "logs") +} + +// ─── ai-requests ──────────────────────────────────────────────── + +var getExecutionAIRequestsCmd = &cobra.Command{ + Use: "ai-requests ", + Short: "Get AI requests for an execution", + Args: cobra.ExactArgs(1), + RunE: runGetExecutionAIRequests, +} + +var aiRequestsLimit, aiRequestsOffset *int + +func init() { + executionsCmd.AddCommand(getExecutionAIRequestsCmd) + aiRequestsLimit, aiRequestsOffset = pageFlags(getExecutionAIRequestsCmd) +} + +func runGetExecutionAIRequests(cmd *cobra.Command, args []string) error { + query := `query ($id: ID!, $limit: Int!, $offset: Int!) { + executionAiRequests(executionId: $id, limit: $limit, offset: $offset) { + nodes {` + aiRequestFields + `} + pageInfo { total limit offset } + } + }` + vars := map[string]any{"id": args[0], "limit": *aiRequestsLimit, "offset": *aiRequestsOffset} + return gqlConnection(cmd.Context(), query, vars, "executionAiRequests", "ai_requests") +} + +// ─── email-requests ──────────────────────────────────────────────── + +var getExecutionEmailRequestsCmd = &cobra.Command{ + Use: "email-requests ", + Short: "Get email requests for an execution", + Args: cobra.ExactArgs(1), + RunE: runGetExecutionEmailRequests, +} + +var emailRequestsLimit, emailRequestsOffset *int + +func init() { + executionsCmd.AddCommand(getExecutionEmailRequestsCmd) + emailRequestsLimit, emailRequestsOffset = pageFlags(getExecutionEmailRequestsCmd) +} + +func runGetExecutionEmailRequests(cmd *cobra.Command, args []string) error { + query := `query ($id: ID!, $limit: Int!, $offset: Int!) { + executionEmailRequests(executionId: $id, limit: $limit, offset: $offset) { + nodes {` + emailRequestFields + `} + pageInfo { total limit offset } + } + }` + vars := map[string]any{"id": args[0], "limit": *emailRequestsLimit, "offset": *emailRequestsOffset} + return gqlConnection(cmd.Context(), query, vars, "executionEmailRequests", "email_requests") +} diff --git a/lunar-cli/cmd/functions.gen.go b/lunar-cli/cmd/functions.go similarity index 55% rename from lunar-cli/cmd/functions.gen.go rename to lunar-cli/cmd/functions.go index f7d2f9f..f37380d 100644 --- a/lunar-cli/cmd/functions.gen.go +++ b/lunar-cli/cmd/functions.go @@ -1,5 +1,3 @@ -// Code generated by tools/gen; DO NOT EDIT. - package cmd import ( @@ -8,11 +6,50 @@ import ( "os" "strings" - "github.com/dimiro1/lunar/lunar-cli/client" "github.com/spf13/cobra" ) -var _ = fmt.Sprintf // suppress unused import +// functionFields is the full GraphQL selection for a function, aliased to the +// snake_case shape the CLI output (and existing scripts) expect. +const functionFields = ` + id + name + description + disabled + retention_days: retentionDays + cron_schedule: cronSchedule + cron_status: cronStatus + save_response: saveResponse + created_at: createdAt + updated_at: updatedAt + active_version: activeVersion { + id + function_id: functionId + version + code + created_at: createdAt + created_by: createdBy + is_active: isActive + } + env_vars: envVars + scoped_data: scopedData + global_data: globalData +` + +// functionSummaryFields is the trimmed selection used for the list view: no +// code or env/KV maps, so listing many functions stays cheap. +const functionSummaryFields = ` + id + name + description + disabled + cron_schedule: cronSchedule + cron_status: cronStatus + save_response: saveResponse + created_at: createdAt + updated_at: updatedAt + active_version: activeVersion { version } +` var functionsCmd = &cobra.Command{ Use: "functions", @@ -43,16 +80,14 @@ func init() { } func runListFunctions(cmd *cobra.Command, args []string) error { - c := mustClient() - params := &client.ListFunctionsParams{ - Limit: &listFunctionsCmdLimit, - Offset: &listFunctionsCmdOffset, - } - resp, err := c.ListFunctionsWithResponse(cmd.Context(), params) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `query ($limit: Int!, $offset: Int!) { + functions(limit: $limit, offset: $offset) { + nodes {` + functionSummaryFields + `} + pageInfo { total limit offset } + } + }` + vars := map[string]any{"limit": listFunctionsCmdLimit, "offset": listFunctionsCmdOffset} + return gqlConnection(cmd.Context(), query, vars, "functions", "functions") } // ─── create ──────────────────────────────────────────────── @@ -71,36 +106,26 @@ var ( func init() { functionsCmd.AddCommand(createFunctionCmd) - createFunctionCmd.Flags().StringVar(&createFunctionCmdCode, "code", "", "Lua code for the function (must be non-empty after trimming whitespace)") + createFunctionCmd.Flags().StringVar(&createFunctionCmdCode, "code", "", "Lua code for the function (use \"-\" to read from stdin)") _ = createFunctionCmd.MarkFlagRequired("code") createFunctionCmd.Flags().StringVar(&createFunctionCmdDescription, "description", "", "Optional description") - createFunctionCmd.Flags().StringVar(&createFunctionCmdName, "name", "", "Name for the function (must be non-empty after trimming whitespace)") + createFunctionCmd.Flags().StringVar(&createFunctionCmdName, "name", "", "Name for the function") _ = createFunctionCmd.MarkFlagRequired("name") } func runCreateFunction(cmd *cobra.Command, args []string) error { - c := mustClient() - code := createFunctionCmdCode - if code == "-" { - b, err := io.ReadAll(os.Stdin) - if err != nil { - return fmt.Errorf("reading stdin: %w", err) - } - code = string(b) - } - body := client.CreateFunctionJSONRequestBody{ - Code: code, - Name: createFunctionCmdName, - } - if cmd.Flags().Changed("description") { - v := createFunctionCmdDescription - body.Description = &v - } - resp, err := c.CreateFunctionWithResponse(cmd.Context(), body) + code, err := maybeStdin(createFunctionCmdCode) if err != nil { return err } - return printAPIResponse(resp.StatusCode(), resp.Body) + input := map[string]any{"name": createFunctionCmdName, "code": code} + if cmd.Flags().Changed("description") { + input["description"] = createFunctionCmdDescription + } + query := `mutation ($input: CreateFunctionInput!) { + createFunction(input: $input) {` + functionFields + `} + }` + return gqlObject(cmd.Context(), query, map[string]any{"input": input}, "createFunction") } // ─── get ──────────────────────────────────────────────── @@ -117,12 +142,8 @@ func init() { } func runGetFunction(cmd *cobra.Command, args []string) error { - c := mustClient() - resp, err := c.GetFunctionWithResponse(cmd.Context(), args[0]) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `query ($id: ID!) { function(id: $id) {` + functionFields + `} }` + return gqlObject(cmd.Context(), query, map[string]any{"id": args[0]}, "function") } // ─── update ──────────────────────────────────────────────── @@ -147,63 +168,51 @@ var ( func init() { functionsCmd.AddCommand(updateFunctionCmd) - updateFunctionCmd.Flags().StringVar(&updateFunctionCmdCode, "code", "", "New code (creates a new version, must be non-empty after trimming whitespace)") - updateFunctionCmd.Flags().StringVar(&updateFunctionCmdCronSchedule, "cron-schedule", "", "Cron expression for scheduled execution (standard 5-field format: minute hour day month weekday). Examples: \\\"*/5 * * * *\\\" (every 5 minutes), \\\"0 9 * * 1-5\\\" (weekdays at 9am). Set to empty string to clear the schedule.") - updateFunctionCmd.Flags().StringVar(&updateFunctionCmdCronStatus, "cron-status", "", "Status of the cron schedule. Set to \\\"active\\\" to enable scheduled execution.") + updateFunctionCmd.Flags().StringVar(&updateFunctionCmdCode, "code", "", "New code (creates a new version; use \"-\" to read from stdin)") + updateFunctionCmd.Flags().StringVar(&updateFunctionCmdCronSchedule, "cron-schedule", "", "Cron expression (5-field). Empty string clears the schedule.") + updateFunctionCmd.Flags().StringVar(&updateFunctionCmdCronStatus, "cron-status", "", "Cron schedule status (\"active\" or \"paused\")") updateFunctionCmd.Flags().StringVar(&updateFunctionCmdDescription, "description", "", "New description") - updateFunctionCmd.Flags().BoolVar(&updateFunctionCmdDisabled, "disabled", false, "Set to true to disable the function (preventing execution), false to enable it") - updateFunctionCmd.Flags().StringVar(&updateFunctionCmdName, "name", "", "New name for the function (must be non-empty after trimming whitespace)") - updateFunctionCmd.Flags().IntVar(&updateFunctionCmdRetentionDays, "retention-days", 0, "Number of days to retain execution logs") - updateFunctionCmd.Flags().BoolVar(&updateFunctionCmdSaveResponse, "save-response", false, "Whether to save HTTP responses with executions for debugging") + updateFunctionCmd.Flags().BoolVar(&updateFunctionCmdDisabled, "disabled", false, "Set true to disable the function, false to enable it") + updateFunctionCmd.Flags().StringVar(&updateFunctionCmdName, "name", "", "New name for the function") + updateFunctionCmd.Flags().IntVar(&updateFunctionCmdRetentionDays, "retention-days", 0, "Number of days to retain execution history") + updateFunctionCmd.Flags().BoolVar(&updateFunctionCmdSaveResponse, "save-response", false, "Whether to save HTTP responses with executions") } func runUpdateFunction(cmd *cobra.Command, args []string) error { - c := mustClient() - body := client.UpdateFunctionJSONRequestBody{} + input := map[string]any{} if cmd.Flags().Changed("code") { - codeVal := updateFunctionCmdCode - if codeVal == "-" { - b, err := io.ReadAll(os.Stdin) - if err != nil { - return fmt.Errorf("reading stdin: %w", err) - } - codeVal = string(b) + code, err := maybeStdin(updateFunctionCmdCode) + if err != nil { + return err } - body.Code = &codeVal + input["code"] = code } if cmd.Flags().Changed("cron-schedule") { - v := updateFunctionCmdCronSchedule - body.CronSchedule = &v + input["cronSchedule"] = updateFunctionCmdCronSchedule } if cmd.Flags().Changed("cron-status") { - v := client.UpdateFunctionRequestCronStatus(updateFunctionCmdCronStatus) - body.CronStatus = &v + input["cronStatus"] = updateFunctionCmdCronStatus } if cmd.Flags().Changed("description") { - v := updateFunctionCmdDescription - body.Description = &v + input["description"] = updateFunctionCmdDescription } if cmd.Flags().Changed("disabled") { - v := updateFunctionCmdDisabled - body.Disabled = &v + input["disabled"] = updateFunctionCmdDisabled } if cmd.Flags().Changed("name") { - v := updateFunctionCmdName - body.Name = &v + input["name"] = updateFunctionCmdName } if cmd.Flags().Changed("retention-days") { - v := client.UpdateFunctionRequestRetentionDays(updateFunctionCmdRetentionDays) - body.RetentionDays = &v + input["retentionDays"] = updateFunctionCmdRetentionDays } if cmd.Flags().Changed("save-response") { - v := updateFunctionCmdSaveResponse - body.SaveResponse = &v - } - resp, err := c.UpdateFunctionWithResponse(cmd.Context(), args[0], body) - if err != nil { - return err + input["saveResponse"] = updateFunctionCmdSaveResponse } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `mutation ($id: ID!, $input: UpdateFunctionInput!) { + updateFunction(id: $id, input: $input) {` + functionFields + `} + }` + vars := map[string]any{"id": args[0], "input": input} + return gqlObject(cmd.Context(), query, vars, "updateFunction") } // ─── delete ──────────────────────────────────────────────── @@ -220,12 +229,8 @@ func init() { } func runDeleteFunction(cmd *cobra.Command, args []string) error { - c := mustClient() - resp, err := c.DeleteFunctionWithResponse(cmd.Context(), args[0]) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `mutation ($id: ID!) { deleteFunction(id: $id) }` + return gqlSuccess(cmd.Context(), query, map[string]any{"id": args[0]}, "deleteFunction") } // ─── env ──────────────────────────────────────────────── @@ -237,34 +242,24 @@ var updateEnvVarsCmd = &cobra.Command{ RunE: runUpdateEnvVars, } -var ( - updateEnvVarsCmdEnvVars []string -) +var updateEnvVarsCmdEnvVars []string func init() { functionsCmd.AddCommand(updateEnvVarsCmd) - updateEnvVarsCmd.Flags().StringArrayVar(&updateEnvVarsCmdEnvVars, "env", nil, "Environment variables to set (max 100 variables). Keys must contain only letters, numbers, and underscores (max 100 chars). Values can be up to 10,000 characters.") + updateEnvVarsCmd.Flags().StringArrayVar(&updateEnvVarsCmdEnvVars, "env", nil, "Environment variables to set as KEY=VALUE (repeatable). Replaces the full set.") _ = updateEnvVarsCmd.MarkFlagRequired("env") } func runUpdateEnvVars(cmd *cobra.Command, args []string) error { - c := mustClient() - envMap := make(map[string]string) - for _, kv := range updateEnvVarsCmdEnvVars { - parts := strings.SplitN(kv, "=", 2) - if len(parts) != 2 { - return fmt.Errorf("invalid --env format %q, expected KEY=VALUE", kv) - } - envMap[parts[0]] = parts[1] - } - body := client.UpdateEnvVarsJSONRequestBody{ - EnvVars: envMap, - } - resp, err := c.UpdateEnvVarsWithResponse(cmd.Context(), args[0], body) + envMap, err := parseKeyValues(updateEnvVarsCmdEnvVars, "--env") if err != nil { return err } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `mutation ($id: ID!, $env: Map!) { + setFunctionEnv(id: $id, env: $env) {` + functionFields + `} + }` + vars := map[string]any{"id": args[0], "env": envMap} + return gqlObject(cmd.Context(), query, vars, "setFunctionEnv") } // ─── kv ──────────────────────────────────────────────── @@ -283,31 +278,22 @@ var ( func init() { functionsCmd.AddCommand(updateKVCmd) - updateKVCmd.Flags().BoolVar(&updateKVCmdGlobal, "global", false, "Whether the KV pairs are global or function-scoped") + updateKVCmd.Flags().BoolVar(&updateKVCmdGlobal, "global", false, "Write to the global KV store instead of the function scope") _ = updateKVCmd.MarkFlagRequired("global") - updateKVCmd.Flags().StringArrayVar(&updateKVCmdKv, "kv", nil, "Key-value pairs to set in the function's KV store (max 100 pairs). Keys must contain only letters, numbers, and underscores (max 100 chars). Values can be up to 10,000 characters.") + updateKVCmd.Flags().StringArrayVar(&updateKVCmdKv, "kv", nil, "KV pairs to set as KEY=VALUE (repeatable). Replaces the full set.") _ = updateKVCmd.MarkFlagRequired("kv") } func runUpdateKV(cmd *cobra.Command, args []string) error { - c := mustClient() - kvMap := make(map[string]string) - for _, kv := range updateKVCmdKv { - parts := strings.SplitN(kv, "=", 2) - if len(parts) != 2 { - return fmt.Errorf("invalid --kv format %q, expected KEY=VALUE", kv) - } - kvMap[parts[0]] = parts[1] - } - body := client.UpdateKVJSONRequestBody{ - Global: updateKVCmdGlobal, - Kv: kvMap, - } - resp, err := c.UpdateKVWithResponse(cmd.Context(), args[0], body) + kvMap, err := parseKeyValues(updateKVCmdKv, "--kv") if err != nil { return err } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `mutation ($id: ID!, $kv: Map!, $global: Boolean!) { + setFunctionKv(id: $id, kv: $kv, global: $global) {` + functionFields + `} + }` + vars := map[string]any{"id": args[0], "kv": kvMap, "global": updateKVCmdGlobal} + return gqlObject(cmd.Context(), query, vars, "setFunctionKv") } // ─── next-run ──────────────────────────────────────────────── @@ -324,10 +310,40 @@ func init() { } func runGetNextRun(cmd *cobra.Command, args []string) error { - c := mustClient() - resp, err := c.GetNextRunWithResponse(cmd.Context(), args[0]) + query := `query ($id: ID!) { + nextRun(functionId: $id) { + has_schedule: hasSchedule + cron_schedule: cronSchedule + cron_status: cronStatus + is_paused: isPaused + next_run: nextRun + next_run_human: nextRunHuman + } + }` + return gqlObject(cmd.Context(), query, map[string]any{"id": args[0]}, "nextRun") +} + +// maybeStdin returns the contents of stdin when value is "-", otherwise value. +func maybeStdin(value string) (string, error) { + if value != "-" { + return value, nil + } + b, err := io.ReadAll(os.Stdin) if err != nil { - return err + return "", fmt.Errorf("reading stdin: %w", err) + } + return string(b), nil +} + +// parseKeyValues parses repeated KEY=VALUE flag values into a map. +func parseKeyValues(pairs []string, flag string) (map[string]string, error) { + out := make(map[string]string, len(pairs)) + for _, kv := range pairs { + key, value, ok := strings.Cut(kv, "=") + if !ok { + return nil, fmt.Errorf("invalid %s format %q, expected KEY=VALUE", flag, kv) + } + out[key] = value } - return printAPIResponse(resp.StatusCode(), resp.Body) + return out, nil } diff --git a/lunar-cli/cmd/graphql.go b/lunar-cli/cmd/graphql.go new file mode 100644 index 0000000..bea53a2 --- /dev/null +++ b/lunar-cli/cmd/graphql.go @@ -0,0 +1,118 @@ +package cmd + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" + + graphql "github.com/hasura/go-graphql-client" +) + +// authTransport injects the bearer token into every request. +type authTransport struct { + token string + base http.RoundTripper +} + +func (t authTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if t.token != "" { + req.Header.Set("Authorization", "Bearer "+t.token) + } + return t.base.RoundTrip(req) +} + +// mustGraphQLClient builds a GraphQL client targeting /graphql using the +// server URL and token resolved in root.go's PersistentPreRunE. +func mustGraphQLClient() *graphql.Client { + if serverURL == "" { + fmt.Fprintln(os.Stderr, "error: no server configured (use --server or LUNAR_SERVER)") + os.Exit(1) + } + httpClient := &http.Client{ + Transport: authTransport{token: apiToken, base: http.DefaultTransport}, + } + return graphql.NewClient(serverURL+"/graphql", httpClient) +} + +// execRaw runs a GraphQL operation and decodes the top-level `data` object into +// a map keyed by operation/alias name. GraphQL and HTTP errors (including an +// unauthenticated 401) are returned as a non-nil error. +func execRaw(ctx context.Context, query string, vars map[string]any) (map[string]json.RawMessage, error) { + raw, err := mustGraphQLClient().ExecRaw(ctx, query, vars) + if err != nil { + return nil, err + } + var data map[string]json.RawMessage + if err := json.Unmarshal(raw, &data); err != nil { + return nil, fmt.Errorf("decoding response: %w", err) + } + return data, nil +} + +// gqlObject runs query and prints the single top-level field as an object, +// erroring when it is null (e.g. a missing resource — the GraphQL equivalent of +// the old REST 404). +func gqlObject(ctx context.Context, query string, vars map[string]any, field string) error { + data, err := execRaw(ctx, query, vars) + if err != nil { + return err + } + body := data[field] + if len(body) == 0 || string(body) == "null" { + return fmt.Errorf("not found") + } + return printJSON(body) +} + +// gqlConnection runs query and reshapes the {nodes, pageInfo} connection at +// `field` into the REST-style {: [...], "pagination": {...}} envelope +// the output renderer (and existing scripts) expect. +func gqlConnection(ctx context.Context, query string, vars map[string]any, field, listKey string) error { + data, err := execRaw(ctx, query, vars) + if err != nil { + return err + } + var conn struct { + Nodes json.RawMessage `json:"nodes"` + PageInfo json.RawMessage `json:"pageInfo"` + } + if err := json.Unmarshal(data[field], &conn); err != nil { + return fmt.Errorf("decoding %s: %w", field, err) + } + out, err := json.Marshal(map[string]json.RawMessage{ + listKey: conn.Nodes, + "pagination": conn.PageInfo, + }) + if err != nil { + return err + } + return printJSON(out) +} + +// gqlList runs query and prints the list at `field` as {: [...]}. +func gqlList(ctx context.Context, query string, vars map[string]any, field, listKey string) error { + data, err := execRaw(ctx, query, vars) + if err != nil { + return err + } + out, err := json.Marshal(map[string]json.RawMessage{listKey: data[field]}) + if err != nil { + return err + } + return printJSON(out) +} + +// gqlSuccess runs a mutation whose result is a boolean and prints +// {"success": }. +func gqlSuccess(ctx context.Context, query string, vars map[string]any, field string) error { + data, err := execRaw(ctx, query, vars) + if err != nil { + return err + } + var ok bool + _ = json.Unmarshal(data[field], &ok) + out, _ := json.Marshal(map[string]bool{"success": ok}) + return printJSON(out) +} diff --git a/lunar-cli/cmd/output.go b/lunar-cli/cmd/output.go index 353f1dc..eff8b58 100644 --- a/lunar-cli/cmd/output.go +++ b/lunar-cli/cmd/output.go @@ -92,14 +92,6 @@ var ( rowSepStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("237")) ) -// printOutput dispatches to the appropriate renderer based on --output flag. -func printOutput(data []byte) error { - if outputFormat == "json" { - return printRawJSON(data) - } - return printPretty(data) -} - // printRawJSON pretty-prints JSON to outputWriter. func printRawJSON(data []byte) error { var buf bytes.Buffer diff --git a/lunar-cli/cmd/root.go b/lunar-cli/cmd/root.go index c7e4581..9317dd1 100644 --- a/lunar-cli/cmd/root.go +++ b/lunar-cli/cmd/root.go @@ -2,15 +2,12 @@ package cmd import ( "bytes" - "context" "fmt" "io" - "net/http" "os" "strings" "github.com/caarlos0/env/v11" - "github.com/dimiro1/lunar/lunar-cli/client" "github.com/dimiro1/lunar/lunar-cli/config" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -118,23 +115,6 @@ func init() { rootCmd.PersistentFlags().BoolVar(&showCode, "show-code", false, "Print code fields when displaying functions or versions") } -// mustClient builds an authenticated HTTP client using the resolved server/token. -func mustClient() *client.ClientWithResponses { - c, err := client.NewClientWithResponses(serverURL, - client.WithRequestEditorFn(func(ctx context.Context, req *http.Request) error { - if apiToken != "" { - req.Header.Set("Authorization", "Bearer "+apiToken) - } - return nil - }), - ) - if err != nil { - fmt.Fprintf(os.Stderr, "error creating client: %v\n", err) - os.Exit(1) - } - return c -} - // printJSON renders a JSON response body using the active output format. // When --output is not set it auto-detects: pretty on a terminal, json when piped. func printJSON(data []byte) error { diff --git a/lunar-cli/cmd/tokens.gen.go b/lunar-cli/cmd/tokens.go similarity index 64% rename from lunar-cli/cmd/tokens.gen.go rename to lunar-cli/cmd/tokens.go index 82b50fa..a8097bc 100644 --- a/lunar-cli/cmd/tokens.gen.go +++ b/lunar-cli/cmd/tokens.go @@ -1,14 +1,16 @@ -// Code generated by tools/gen; DO NOT EDIT. - package cmd -import ( - "fmt" - - "github.com/spf13/cobra" -) +import "github.com/spf13/cobra" -var _ = fmt.Sprintf // suppress unused import +// tokenFields is the GraphQL selection for an API token, aliased to the +// snake_case shape the CLI output (and existing scripts) expect. +const tokenFields = ` + id + name + created_at: createdAt + last_used: lastUsed + revoked +` var tokensCmd = &cobra.Command{ Use: "tokens", @@ -32,12 +34,8 @@ func init() { } func runListTokens(cmd *cobra.Command, args []string) error { - c := mustClient() - resp, err := c.ListTokensWithResponse(cmd.Context()) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `query { apiTokens {` + tokenFields + `} }` + return gqlList(cmd.Context(), query, nil, "apiTokens", "tokens") } // ─── revoke ──────────────────────────────────────────────── @@ -54,10 +52,7 @@ func init() { } func runRevokeToken(cmd *cobra.Command, args []string) error { - c := mustClient() - resp, err := c.RevokeTokenWithResponse(cmd.Context(), args[0]) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `mutation ($id: ID!) { revokeApiToken(id: $id) }` + vars := map[string]any{"id": args[0]} + return gqlSuccess(cmd.Context(), query, vars, "revokeApiToken") } diff --git a/lunar-cli/cmd/versions.gen.go b/lunar-cli/cmd/versions.go similarity index 61% rename from lunar-cli/cmd/versions.gen.go rename to lunar-cli/cmd/versions.go index 34f965a..a8d8fdf 100644 --- a/lunar-cli/cmd/versions.gen.go +++ b/lunar-cli/cmd/versions.go @@ -1,16 +1,32 @@ -// Code generated by tools/gen; DO NOT EDIT. - package cmd import ( "fmt" "strconv" - "github.com/dimiro1/lunar/lunar-cli/client" "github.com/spf13/cobra" ) -var _ = fmt.Sprintf // suppress unused import +// versionFields is the full GraphQL selection for a version (includes code). +const versionFields = ` + id + function_id: functionId + version + code + created_at: createdAt + created_by: createdBy + is_active: isActive +` + +// versionSummaryFields drops the code for the list view. +const versionSummaryFields = ` + id + function_id: functionId + version + created_at: createdAt + created_by: createdBy + is_active: isActive +` var versionsCmd = &cobra.Command{ Use: "versions", @@ -21,36 +37,6 @@ func init() { rootCmd.AddCommand(versionsCmd) } -// ─── diff ──────────────────────────────────────────────── - -var getVersionDiffCmd = &cobra.Command{ - Use: "diff ", - Short: "Get diff between two versions", - Args: cobra.ExactArgs(3), - RunE: runGetVersionDiff, -} - -func init() { - versionsCmd.AddCommand(getVersionDiffCmd) -} - -func runGetVersionDiff(cmd *cobra.Command, args []string) error { - c := mustClient() - v1, err := strconv.Atoi(args[1]) - if err != nil { - return fmt.Errorf("invalid v1: %w", err) - } - v2, err := strconv.Atoi(args[2]) - if err != nil { - return fmt.Errorf("invalid v2: %w", err) - } - resp, err := c.GetVersionDiffWithResponse(cmd.Context(), args[0], v1, v2) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) -} - // ─── list ──────────────────────────────────────────────── var listVersionsCmd = &cobra.Command{ @@ -72,38 +58,39 @@ func init() { } func runListVersions(cmd *cobra.Command, args []string) error { - c := mustClient() - params := &client.ListVersionsParams{ - Limit: &listVersionsCmdLimit, - Offset: &listVersionsCmdOffset, - } - resp, err := c.ListVersionsWithResponse(cmd.Context(), args[0], params) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `query ($id: ID!, $limit: Int!, $offset: Int!) { + versions(functionId: $id, limit: $limit, offset: $offset) { + nodes {` + versionSummaryFields + `} + pageInfo { total limit offset } + } + }` + vars := map[string]any{"id": args[0], "limit": listVersionsCmdLimit, "offset": listVersionsCmdOffset} + return gqlConnection(cmd.Context(), query, vars, "versions", "versions") } -// ─── delete ──────────────────────────────────────────────── +// ─── get ──────────────────────────────────────────────── -var deleteVersionCmd = &cobra.Command{ - Use: "delete ", - Short: "Delete a version", +var getVersionCmd = &cobra.Command{ + Use: "get ", + Short: "Get a specific version", Args: cobra.ExactArgs(2), - RunE: runDeleteVersion, + RunE: runGetVersion, } func init() { - versionsCmd.AddCommand(deleteVersionCmd) + versionsCmd.AddCommand(getVersionCmd) } -func runDeleteVersion(cmd *cobra.Command, args []string) error { - c := mustClient() - resp, err := c.DeleteVersionWithResponse(cmd.Context(), args[0], args[1]) +func runGetVersion(cmd *cobra.Command, args []string) error { + version, err := strconv.Atoi(args[1]) if err != nil { - return err + return fmt.Errorf("invalid version: %w", err) } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `query ($id: ID!, $version: Int!) { + version(functionId: $id, version: $version) {` + versionFields + `} + }` + vars := map[string]any{"id": args[0], "version": version} + return gqlObject(cmd.Context(), query, vars, "version") } // ─── activate ──────────────────────────────────────────────── @@ -120,36 +107,63 @@ func init() { } func runActivateVersion(cmd *cobra.Command, args []string) error { - c := mustClient() - resp, err := c.ActivateVersionWithResponse(cmd.Context(), args[0], args[1]) - if err != nil { - return err - } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `mutation ($id: ID!, $versionId: ID!) { + activateVersion(functionId: $id, versionId: $versionId) {` + functionFields + `} + }` + vars := map[string]any{"id": args[0], "versionId": args[1]} + return gqlObject(cmd.Context(), query, vars, "activateVersion") } -// ─── get ──────────────────────────────────────────────── +// ─── delete ──────────────────────────────────────────────── -var getVersionCmd = &cobra.Command{ - Use: "get ", - Short: "Get a specific version", +var deleteVersionCmd = &cobra.Command{ + Use: "delete ", + Short: "Delete a version", Args: cobra.ExactArgs(2), - RunE: runGetVersion, + RunE: runDeleteVersion, } func init() { - versionsCmd.AddCommand(getVersionCmd) + versionsCmd.AddCommand(deleteVersionCmd) } -func runGetVersion(cmd *cobra.Command, args []string) error { - c := mustClient() - version, err := strconv.Atoi(args[1]) +func runDeleteVersion(cmd *cobra.Command, args []string) error { + query := `mutation ($id: ID!, $versionId: ID!) { + deleteVersion(functionId: $id, versionId: $versionId) + }` + vars := map[string]any{"id": args[0], "versionId": args[1]} + return gqlSuccess(cmd.Context(), query, vars, "deleteVersion") +} + +// ─── diff ──────────────────────────────────────────────── + +var getVersionDiffCmd = &cobra.Command{ + Use: "diff ", + Short: "Get diff between two versions", + Args: cobra.ExactArgs(3), + RunE: runGetVersionDiff, +} + +func init() { + versionsCmd.AddCommand(getVersionDiffCmd) +} + +func runGetVersionDiff(cmd *cobra.Command, args []string) error { + v1, err := strconv.Atoi(args[1]) if err != nil { - return fmt.Errorf("invalid version: %w", err) + return fmt.Errorf("invalid v1: %w", err) } - resp, err := c.GetVersionWithResponse(cmd.Context(), args[0], version) + v2, err := strconv.Atoi(args[2]) if err != nil { - return err + return fmt.Errorf("invalid v2: %w", err) } - return printAPIResponse(resp.StatusCode(), resp.Body) + query := `query ($id: ID!, $v1: Int!, $v2: Int!) { + versionDiff(functionId: $id, oldVersion: $v1, newVersion: $v2) { + old_version: oldVersion + new_version: newVersion + diff: lines { line_type: lineType old_line: oldLine new_line: newLine content } + } + }` + vars := map[string]any{"id": args[0], "v1": v1, "v2": v2} + return gqlObject(cmd.Context(), query, vars, "versionDiff") } diff --git a/lunar-cli/generate.go b/lunar-cli/generate.go deleted file mode 100644 index 84f501a..0000000 --- a/lunar-cli/generate.go +++ /dev/null @@ -1,3 +0,0 @@ -package main - -//go:generate go run ./tools/gen --spec=../internal/api/docs/openapi.yaml --out=cmd diff --git a/lunar-cli/go.mod b/lunar-cli/go.mod index 90db2f4..0cffa70 100644 --- a/lunar-cli/go.mod +++ b/lunar-cli/go.mod @@ -6,8 +6,7 @@ require ( github.com/alecthomas/chroma/v2 v2.23.1 github.com/caarlos0/env/v11 v11.4.1 github.com/charmbracelet/lipgloss v1.1.0 - github.com/oapi-codegen/oapi-codegen/v2 v2.6.0 - github.com/oapi-codegen/runtime v1.4.0 + github.com/hasura/go-graphql-client v0.16.0 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.9 golang.org/x/term v0.42.0 @@ -15,39 +14,23 @@ require ( ) require ( - github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/coder/websocket v1.8.14 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect - github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect - github.com/getkin/kin-openapi v0.133.0 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/josharian/intern v1.0.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/muesli/termenv v0.16.0 // indirect - github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect - github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect - github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/speakeasy-api/jsonpath v0.6.0 // indirect - github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect - github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect - github.com/woodsbury/decimal128 v1.3.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/mod v0.33.0 // indirect - golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.43.0 // indirect - golang.org/x/text v0.32.0 // indirect - golang.org/x/tools v0.42.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/lunar-cli/go.sum b/lunar-cli/go.sum index 37b92c4..44cea98 100644 --- a/lunar-cli/go.sum +++ b/lunar-cli/go.sum @@ -1,17 +1,13 @@ -github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= -github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= -github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/caarlos0/env/v11 v11.4.1 h1:fYwH0sWEsBSMPG7t4e/PEfTFzrWrpjyygXyUnWiSwEw= github.com/caarlos0/env/v11 v11.4.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= @@ -26,58 +22,21 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99k github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= +github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= -github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= -github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= -github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= -github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hasura/go-graphql-client v0.16.0 h1:DQLfp+djj4j5NPdJkGYym8J55hpm5etML1zqgco78Qc= +github.com/hasura/go-graphql-client v0.16.0/go.mod h1:z/sO2T0zI+HnPNIevQcs+7xA6/gDOc8hgHMrNBzfL2c= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -86,156 +45,36 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oapi-codegen/oapi-codegen/v2 v2.6.0 h1:4i+F2cvwBFZeplxCssNdLy3MhNzUD87mI3HnayHZkAU= -github.com/oapi-codegen/oapi-codegen/v2 v2.6.0/go.mod h1:eWHeJSohQJIINJZzzQriVynfGsnlQVh0UkN2UYYcw4Q= -github.com/oapi-codegen/runtime v1.4.0 h1:KLOSFOp7UzkbS7Cs1ms6NBEKYr0WmH2wZG0KKbd2er4= -github.com/oapi-codegen/runtime v1.4.0/go.mod h1:5sw5fxCDmnOzKNYmkVNF8d34kyUeejJEY8HNT2WaPec= -github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= -github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= -github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= -github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= -github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8= -github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw= -github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU= -github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= -github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= -github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= -github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= -github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lunar-cli/integration/go.mod b/lunar-cli/integration/go.mod index ce466b2..35afb06 100644 --- a/lunar-cli/integration/go.mod +++ b/lunar-cli/integration/go.mod @@ -9,8 +9,9 @@ require ( ) require ( + github.com/99designs/gqlgen v0.17.90 // indirect + github.com/agnivade/levenshtein v1.2.1 // indirect github.com/alecthomas/chroma/v2 v2.23.1 // indirect - github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/caarlos0/env/v11 v11.4.1 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect @@ -18,31 +19,38 @@ require ( github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/coder/websocket v1.8.14 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/golang-migrate/migrate/v4 v4.19.1 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hasura/go-graphql-client v0.16.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.21 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/muesli/termenv v0.16.0 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect - github.com/oapi-codegen/runtime v1.4.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/resend/resend-go/v3 v3.1.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rs/xid v1.6.0 // indirect github.com/sergi/go-diff v1.4.0 // indirect + github.com/sosodev/duration v1.4.0 // indirect github.com/spf13/cobra v1.10.2 // indirect github.com/spf13/pflag v1.0.9 // indirect + github.com/vektah/gqlparser/v2 v2.5.33 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yuin/gopher-lua v1.1.1 // indirect go.uber.org/dig v1.19.0 // indirect go.uber.org/fx v1.24.0 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.26.0 // indirect + golang.org/x/sync v0.20.0 // indirect golang.org/x/sys v0.43.0 // indirect golang.org/x/term v0.42.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/lunar-cli/integration/go.sum b/lunar-cli/integration/go.sum index 359874a..4988dbb 100644 --- a/lunar-cli/integration/go.sum +++ b/lunar-cli/integration/go.sum @@ -1,17 +1,25 @@ -github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/99designs/gqlgen v0.17.90 h1:wSv6blm/PoplU6QoNw83EcQpNtC0HX3/+44vITJOzpk= +github.com/99designs/gqlgen v0.17.90/go.mod h1:GqYrEwYsqCG8VaOsq2kJUCUKwAE1T+u2i+Nj7NtXiVI= +github.com/PuerkitoBio/goquery v1.12.0 h1:pAcL4g3WRXekcB9AU/y1mbKez2dbY2AajVhtkO8RIBo= +github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YFofScC4q/hIpQ= +github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= +github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= -github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM= +github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= -github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/caarlos0/env/v11 v11.4.1 h1:fYwH0sWEsBSMPG7t4e/PEfTFzrWrpjyygXyUnWiSwEw= github.com/caarlos0/env/v11 v11.4.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= @@ -26,30 +34,40 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99k github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= +github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA= github.com/golang-migrate/migrate/v4 v4.19.1/go.mod h1:CTcgfjxhaUtsLipnLoQRWCrjYXycRz/g5+RWDuYgPrE= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hasura/go-graphql-client v0.16.0 h1:DQLfp+djj4j5NPdJkGYym8J55hpm5etML1zqgco78Qc= +github.com/hasura/go-graphql-client v0.16.0/go.mod h1:z/sO2T0zI+HnPNIevQcs+7xA6/gDOc8hgHMrNBzfL2c= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -58,16 +76,14 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= +github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/oapi-codegen/runtime v1.4.0 h1:KLOSFOp7UzkbS7Cs1ms6NBEKYr0WmH2wZG0KKbd2er4= -github.com/oapi-codegen/runtime v1.4.0/go.mod h1:5sw5fxCDmnOzKNYmkVNF8d34kyUeejJEY8HNT2WaPec= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -80,21 +96,25 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sosodev/duration v1.4.0 h1:35ed0KiVFriGHHzZZJaZLgmTEEICIyt8Sx0RQfj9IjE= +github.com/sosodev/duration v1.4.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/vektah/gqlparser/v2 v2.5.33 h1:lRp8aIeNUNbimf/axZd7ETg24q06hBtPaas+TcvI/7E= +github.com/vektah/gqlparser/v2 v2.5.33/go.mod h1:c1I28gSOVNzlfc4WuDlqU7voQnsqI6OG2amkBAFmgts= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= @@ -114,9 +134,10 @@ golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a h1:ovFr6Z0MNmU7nH8VaX5xqw+05 golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA= golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= @@ -124,8 +145,9 @@ golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/lunar-cli/integration/integration_test.go b/lunar-cli/integration/integration_test.go index 86109de..b2b3e65 100644 --- a/lunar-cli/integration/integration_test.go +++ b/lunar-cli/integration/integration_test.go @@ -51,6 +51,13 @@ func newTestServer() (*httptest.Server, func()) { if err != nil { panic(fmt.Sprintf("open db: %v", err)) } + // A plain ":memory:" database is private to each pooled connection, so + // migrations (and the per-connection PRAGMA below) would apply to one + // connection while other queries hit fresh, empty ones. The GraphQL server + // resolves sibling fields concurrently, which makes the pool hand out those + // extra connections — pinning to a single connection keeps every query on + // the one migrated in-memory database. + db.SetMaxOpenConns(1) if _, err := db.Exec("PRAGMA foreign_keys = ON"); err != nil { panic(fmt.Sprintf("foreign keys: %v", err)) } diff --git a/lunar-cli/tools/gen/main.go b/lunar-cli/tools/gen/main.go deleted file mode 100644 index 668ec55..0000000 --- a/lunar-cli/tools/gen/main.go +++ /dev/null @@ -1,840 +0,0 @@ -// gen generates Cobra command files from an OpenAPI spec. -// Usage: go run ./tools/gen --spec= --out= -package main - -import ( - "bytes" - "flag" - "fmt" - "go/format" - "maps" - "os" - "path/filepath" - "sort" - "strconv" - "strings" - "unicode" - - "gopkg.in/yaml.v3" -) - -// ────────────────────────────────────────────────────────────────────────────── -// OpenAPI data structures (minimal subset) -// ────────────────────────────────────────────────────────────────────────────── - -type Spec struct { - Tags []SpecTag `yaml:"tags"` - Paths map[string]PathItem `yaml:"paths"` - Components Components `yaml:"components"` -} - -type SpecTag struct { - Name string `yaml:"name"` - Description string `yaml:"description"` -} - -type PathItem struct { - Parameters []Parameter `yaml:"parameters"` - Get *Operation `yaml:"get"` - Post *Operation `yaml:"post"` - Put *Operation `yaml:"put"` - Delete *Operation `yaml:"delete"` - Patch *Operation `yaml:"patch"` -} - -type Operation struct { - OperationID string `yaml:"operationId"` - Summary string `yaml:"summary"` - Tags []string `yaml:"tags"` - Parameters []Parameter `yaml:"parameters"` - RequestBody *RequestBody `yaml:"requestBody"` -} - -type Parameter struct { - Name string `yaml:"name"` - In string `yaml:"in"` - Required bool `yaml:"required"` - Description string `yaml:"description"` - Schema Schema `yaml:"schema"` -} - -type RequestBody struct { - Content map[string]MediaType `yaml:"content"` -} - -type MediaType struct { - Schema Schema `yaml:"schema"` -} - -type Schema struct { - Ref string `yaml:"$ref"` - Type string `yaml:"type"` - Nullable bool `yaml:"nullable"` - Properties map[string]Schema `yaml:"properties"` - Required []string `yaml:"required"` - AdditionalProperties *Schema `yaml:"additionalProperties"` - AllOf []Schema `yaml:"allOf"` - Format string `yaml:"format"` - Description string `yaml:"description"` - Default any `yaml:"default"` - Enum []any `yaml:"enum"` -} - -type Components struct { - Schemas map[string]Schema `yaml:"schemas"` -} - -// ────────────────────────────────────────────────────────────────────────────── -// Tag config – tags to generate files for -// ────────────────────────────────────────────────────────────────────────────── - -type tagConfig struct { - fileBase string // output file base name, e.g. "functions" - varName string // Go var/command name, e.g. "functions" - commandUse string // cobra Use string, e.g. "functions" - stripSuffix []string // suffixes stripped from kebab-case operationId -} - -var tagConfigs = map[string]tagConfig{ - "Functions": {fileBase: "functions", varName: "functions", commandUse: "functions", stripSuffix: []string{"functions", "function"}}, - "Versions": {fileBase: "versions", varName: "versions", commandUse: "versions", stripSuffix: []string{"versions", "version"}}, - "Executions": {fileBase: "executions", varName: "executions", commandUse: "executions", stripSuffix: []string{"executions", "execution"}}, - "API Tokens": {fileBase: "tokens", varName: "tokens", commandUse: "tokens", stripSuffix: []string{"tokens", "token"}}, -} - -// tagOrder controls the file generation order. -var tagOrder = []string{"Functions", "Versions", "Executions", "API Tokens"} - -// commandNameOverrides maps operationId to an explicit subcommand name. -var commandNameOverrides = map[string]string{ - "updateEnvVars": "env", - "updateKV": "kv", - "getNextRun": "next-run", - "getVersionDiff": "diff", - "getExecutionLogs": "logs", - "getExecutionAIRequests": "ai-requests", - "getExecutionEmailRequests": "email-requests", -} - -// ────────────────────────────────────────────────────────────────────────────── -// Internal operation model -// ────────────────────────────────────────────────────────────────────────────── - -type fieldInfo struct { - flagName string // kebab-case flag name - goVarSuffix string // PascalCase suffix for var name - goType string // "string", "int", "bool", "[]string" - defaultVal string // Go literal default value - desc string - required bool - isPointer bool // optional → pointer field in body struct - isMap bool // map[string]string body field - goFieldName string // PascalCase name in the Go struct - isCode bool // code field: support "-" for stdin - enumCastType string // non-empty if oapi-codegen uses a custom enum type, e.g. "client.UpdateFunctionRequestCronStatus" -} - -type pathArg struct { - paramName string // original param name, e.g. "id", "version", "versionId" - goType string // "string" or "int" - displayName string // display in Use string, e.g. "", "" -} - -type opInfo struct { - operationID string - commandName string - summary string - goFuncName string // PascalCase operationId, for use with WithResponse - pathArgs []pathArg - queryFields []fieldInfo - bodyFields []fieldInfo - hasBody bool - bodyTypeName string // e.g. "client.CreateFunctionJSONRequestBody" - bodySchemaName string // resolved schema name, e.g. "UpdateFunctionRequest" -} - -// ────────────────────────────────────────────────────────────────────────────── -// Main -// ────────────────────────────────────────────────────────────────────────────── - -func main() { - specPath := flag.String("spec", "", "path to openapi.yaml") - outDir := flag.String("out", "", "output directory for generated .gen.go files") - flag.Parse() - - if *specPath == "" || *outDir == "" { - fmt.Fprintln(os.Stderr, "usage: gen --spec= --out=") - os.Exit(1) - } - - data, err := os.ReadFile(*specPath) - if err != nil { - fatalf("reading spec: %v", err) - } - var spec Spec - if err := yaml.Unmarshal(data, &spec); err != nil { - fatalf("parsing spec: %v", err) - } - - // Collect tag descriptions from the spec. - tagDescs := make(map[string]string) - for _, t := range spec.Tags { - tagDescs[t.Name] = t.Description - } - - // Group operations by tag, in path order (sorted for determinism). - paths := sortedPaths(spec.Paths) - tagOps := make(map[string][]opInfo) - - for _, path := range paths { - item := spec.Paths[path] - // Merge path-level parameters into each operation. - for _, op := range []*Operation{item.Get, item.Post, item.Put, item.Delete, item.Patch} { - if op == nil || op.OperationID == "" { - continue - } - merged := mergeParams(item.Parameters, op.Parameters) - op.Parameters = merged - - // Only process tags we care about. - for _, tag := range op.Tags { - if _, ok := tagConfigs[tag]; !ok { - continue - } - info, err := buildOpInfo(op, path, tag, &spec) - if err != nil { - fatalf("building op %s: %v", op.OperationID, err) - } - tagOps[tag] = append(tagOps[tag], info) - } - } - } - - if err := os.MkdirAll(*outDir, 0755); err != nil { - fatalf("creating output dir: %v", err) - } - - for _, tag := range tagOrder { - ops, ok := tagOps[tag] - if !ok { - continue - } - cfg := tagConfigs[tag] - outFile := filepath.Join(*outDir, cfg.fileBase+".gen.go") - src, err := generateFile(tag, tagDescs[tag], cfg, ops) - if err != nil { - fatalf("generating %s: %v", outFile, err) - } - if err := os.WriteFile(outFile, src, 0644); err != nil { - fatalf("writing %s: %v", outFile, err) - } - fmt.Printf("wrote %s (%d operations)\n", outFile, len(ops)) - } -} - -// ────────────────────────────────────────────────────────────────────────────── -// Operation model builder -// ────────────────────────────────────────────────────────────────────────────── - -func buildOpInfo(op *Operation, path, tag string, spec *Spec) (opInfo, error) { - cfg := tagConfigs[tag] - info := opInfo{ - operationID: op.OperationID, - commandName: deriveCommandName(op.OperationID, cfg), - summary: op.Summary, - goFuncName: toPascal(op.OperationID), - } - - // Path and query params. - for _, p := range op.Parameters { - switch p.In { - case "path": - goType := schemaGoType(p.Schema) - display := "<" + camelToKebab(p.Name) + ">" - info.pathArgs = append(info.pathArgs, pathArg{ - paramName: p.Name, - goType: goType, - displayName: display, - }) - case "query": - f := buildFieldInfo(p.Name, "", p.Schema, p.Required, p.Description) - info.queryFields = append(info.queryFields, f) - } - } - - // Request body. - if op.RequestBody != nil { - info.hasBody = true - info.bodyTypeName = "client." + toPascal(op.OperationID) + "JSONRequestBody" - - mt, ok := op.RequestBody.Content["application/json"] - if !ok { - return info, nil - } - // Extract the schema name from the $ref before resolving. - schemaName := strings.TrimPrefix(mt.Schema.Ref, "#/components/schemas/") - - schema := resolveRef(mt.Schema, spec) - // Merge allOf schemas. - schema = flattenAllOf(schema, spec) - info.bodySchemaName = schemaName - - requiredSet := make(map[string]bool) - for _, r := range schema.Required { - requiredSet[r] = true - } - - // Sort property names for deterministic output. - propNames := make([]string, 0, len(schema.Properties)) - for name := range schema.Properties { - propNames = append(propNames, name) - } - sort.Strings(propNames) - - for _, name := range propNames { - prop := schema.Properties[name] - required := requiredSet[name] - f := buildFieldInfo(name, schemaName, prop, required, prop.Description) - f.isPointer = !required - info.bodyFields = append(info.bodyFields, f) - } - } - - return info, nil -} - -// buildFieldInfo builds a fieldInfo for a single OpenAPI parameter/property. -// schemaName is the parent schema name (e.g. "UpdateFunctionRequest") used to derive -// the oapi-codegen enum type name; pass "" for query/path params. -func buildFieldInfo(name, schemaName string, schema Schema, required bool, desc string) fieldInfo { - f := fieldInfo{ - flagName: camelToKebab(snakeToKebab(name)), - goVarSuffix: snakeToPascal(name), - goFieldName: snakeToPascal(name), - required: required, - desc: escapeQuotes(desc), - } - - // Detect map type. - if schema.Type == "object" && schema.AdditionalProperties != nil { - f.isMap = true - f.goType = "[]string" - f.defaultVal = "nil" - // Use shorter flag name for well-known maps. - if name == "env_vars" { - f.flagName = "env" - } - return f - } - - // Detect code field. - if name == "code" && schema.Type == "string" { - f.isCode = true - } - - switch schema.Type { - case "integer": - f.goType = "int" - if schema.Default != nil { - f.defaultVal = fmt.Sprintf("%v", schema.Default) - } else { - f.defaultVal = "0" - } - // If the schema has enum values, oapi-codegen generates a custom type. - if len(schema.Enum) > 0 && schemaName != "" { - f.enumCastType = "client." + schemaName + f.goVarSuffix - } - case "boolean": - f.goType = "bool" - f.defaultVal = "false" - default: // string, "" - f.goType = "string" - f.defaultVal = `""` - // If the schema has enum values, oapi-codegen generates a custom string type. - if len(schema.Enum) > 0 && schemaName != "" { - f.enumCastType = "client." + schemaName + f.goVarSuffix - } - } - return f -} - -// ────────────────────────────────────────────────────────────────────────────── -// Code generator -// ────────────────────────────────────────────────────────────────────────────── - -func generateFile(tag, tagDesc string, cfg tagConfig, ops []opInfo) ([]byte, error) { - var b bytes.Buffer - - // Determine required imports. - needsStrconv := false - needsIO := false - needsOS := false - needsStrings := false - needsClient := false - for _, op := range ops { - for _, a := range op.pathArgs { - if a.goType == "int" { - needsStrconv = true - } - } - if len(op.queryFields) > 0 || op.hasBody { - needsClient = true - } - for _, f := range op.bodyFields { - if f.isCode { - needsIO = true - needsOS = true - } - if f.isMap { - needsStrings = true - } - } - } - - w(&b, "// Code generated by tools/gen; DO NOT EDIT.\n\n") - w(&b, "package cmd\n\n") - w(&b, "import (\n") - w(&b, "\t\"fmt\"\n") - if needsIO { - w(&b, "\t\"io\"\n") - } - if needsOS { - w(&b, "\t\"os\"\n") - } - if needsStrconv { - w(&b, "\t\"strconv\"\n") - } - if needsStrings { - w(&b, "\t\"strings\"\n") - } - w(&b, "\n") - if needsClient { - w(&b, "\t\"github.com/dimiro1/lunar/lunar-cli/client\"\n") - } - w(&b, "\t\"github.com/spf13/cobra\"\n") - w(&b, ")\n\n") - - // Suppress unused import errors. - w(&b, "var _ = fmt.Sprintf // suppress unused import\n\n") - - // Parent command. - w(&b, "var %sCmd = &cobra.Command{\n", cfg.varName) - w(&b, "\tUse: %q,\n", cfg.commandUse) - w(&b, "\tShort: %q,\n", tagDesc) - w(&b, "}\n\n") - - w(&b, "func init() {\n") - w(&b, "\trootCmd.AddCommand(%sCmd)\n", cfg.varName) - w(&b, "}\n\n") - - // Each operation. - for _, op := range ops { - genOp(&b, cfg, op) - } - - src, err := format.Source(b.Bytes()) - if err != nil { - // Return unformatted for easier debugging. - return b.Bytes(), fmt.Errorf("gofmt: %w (unformatted source written)", err) - } - return src, nil -} - -func genOp(b *bytes.Buffer, cfg tagConfig, op opInfo) { - prefix := op.operationID // e.g. "listFunctions" - - // Build Use string. - var use strings.Builder - use.WriteString(op.commandName) - for _, a := range op.pathArgs { - use.WriteString(" " + a.displayName) - } - - // Command var. - w(b, "// ─── %s ────────────────────────────────────────────────\n\n", op.commandName) - w(b, "var %sCmd = &cobra.Command{\n", prefix) - w(b, "\tUse: %q,\n", use.String()) - w(b, "\tShort: %q,\n", op.summary) - if len(op.pathArgs) > 0 { - w(b, "\tArgs: cobra.ExactArgs(%d),\n", len(op.pathArgs)) - } - w(b, "\tRunE: run%s,\n", op.goFuncName) - w(b, "}\n\n") - - // Flag variable declarations. - allFlags := append(op.queryFields, op.bodyFields...) - if len(allFlags) > 0 { - w(b, "var (\n") - for _, f := range allFlags { - varName := prefix + "Cmd" + f.goVarSuffix - w(b, "\t%s %s\n", varName, f.goType) - } - w(b, ")\n\n") - } - - // init(): register command + flags. - w(b, "func init() {\n") - w(b, "\t%sCmd.AddCommand(%sCmd)\n", cfg.varName, prefix) - for _, f := range op.queryFields { - varName := prefix + "Cmd" + f.goVarSuffix - w(b, "\t%sCmd.Flags().%s(&%s, %q, %s, %q)\n", - prefix, cobraFlagFunc(f.goType), varName, f.flagName, f.defaultVal, f.desc) - } - for _, f := range op.bodyFields { - varName := prefix + "Cmd" + f.goVarSuffix - if f.isMap { - w(b, "\t%sCmd.Flags().StringArrayVar(&%s, %q, nil, %q)\n", - prefix, varName, f.flagName, f.desc) - } else { - w(b, "\t%sCmd.Flags().%s(&%s, %q, %s, %q)\n", - prefix, cobraFlagFunc(f.goType), varName, f.flagName, f.defaultVal, f.desc) - } - if f.required { - w(b, "\t_ = %sCmd.MarkFlagRequired(%q)\n", prefix, f.flagName) - } - } - w(b, "}\n\n") - - // RunE function. - w(b, "func run%s(cmd *cobra.Command, args []string) error {\n", op.goFuncName) - w(b, "\tc := mustClient()\n") - - // Decode integer path args. - for i, a := range op.pathArgs { - if a.goType == "int" { - w(b, "\t%s, err := strconv.Atoi(args[%d])\n", a.paramName, i) - w(b, "\tif err != nil {\n") - w(b, "\t\treturn fmt.Errorf(\"invalid %s: %%w\", err)\n", a.paramName) - w(b, "\t}\n") - } - } - - // Build query params struct if needed. - if len(op.queryFields) > 0 { - paramsType := "client." + op.goFuncName + "Params" - w(b, "\tparams := &%s{\n", paramsType) - for _, f := range op.queryFields { - varName := prefix + "Cmd" + f.goVarSuffix - if f.goType == "int" { - w(b, "\t\t%s: &%s,\n", f.goFieldName, varName) - } else { - w(b, "\t\t%s: &%s,\n", f.goFieldName, varName) - } - } - w(b, "\t}\n") - } - - // Build request body if needed. - if op.hasBody { - genBodyConstruction(b, op, prefix) - } - - // Build client call. - w(b, "\tresp, err := c.%sWithResponse(cmd.Context()", op.goFuncName) - - // Path params. - for i, a := range op.pathArgs { - if a.goType == "int" { - w(b, ", %s", a.paramName) - } else { - w(b, ", args[%d]", i) - } - } - - // Query params struct. - if len(op.queryFields) > 0 { - w(b, ", params") - } - - // Body. - if op.hasBody { - w(b, ", body") - } - - w(b, ")\n") - w(b, "\tif err != nil {\n\t\treturn err\n\t}\n") - w(b, "\treturn printAPIResponse(resp.StatusCode(), resp.Body)\n") - w(b, "}\n\n") -} - -func genBodyConstruction(b *bytes.Buffer, op opInfo, prefix string) { - // Separate map fields from scalar fields. - var mapFields, scalarFields []fieldInfo - for _, f := range op.bodyFields { - if f.isMap { - mapFields = append(mapFields, f) - } else { - scalarFields = append(scalarFields, f) - } - } - - // Generate map parsing. - for _, f := range mapFields { - varName := prefix + "Cmd" + f.goVarSuffix - mapVarName := f.flagName + "Map" - w(b, "\t%s := make(map[string]string)\n", mapVarName) - w(b, "\tfor _, kv := range %s {\n", varName) - w(b, "\t\tparts := strings.SplitN(kv, \"=\", 2)\n") - w(b, "\t\tif len(parts) != 2 {\n") - w(b, "\t\t\treturn fmt.Errorf(\"invalid --%s format %%q, expected KEY=VALUE\", kv)\n", f.flagName) - w(b, "\t\t}\n") - w(b, "\t\t%s[parts[0]] = parts[1]\n", mapVarName) - w(b, "\t}\n") - } - - // Handle code-from-stdin for required code fields. - for _, f := range scalarFields { - if f.isCode && !f.isPointer { - varName := prefix + "Cmd" + f.goVarSuffix - w(b, "\tcode := %s\n", varName) - w(b, "\tif code == \"-\" {\n") - w(b, "\t\tb, err := io.ReadAll(os.Stdin)\n") - w(b, "\t\tif err != nil {\n") - w(b, "\t\t\treturn fmt.Errorf(\"reading stdin: %%w\", err)\n") - w(b, "\t\t}\n") - w(b, "\t\tcode = string(b)\n") - w(b, "\t}\n") - } - } - - // Build body struct literal. - w(b, "\tbody := %s{\n", op.bodyTypeName) - for _, f := range scalarFields { - varName := prefix + "Cmd" + f.goVarSuffix - if f.isPointer { - continue // set below via Changed() - } - if f.isCode { - w(b, "\t\t%s: code,\n", f.goFieldName) - } else { - w(b, "\t\t%s: %s,\n", f.goFieldName, varName) - } - } - for _, f := range mapFields { - mapVarName := f.flagName + "Map" - w(b, "\t\t%s: %s,\n", f.goFieldName, mapVarName) - } - w(b, "\t}\n") - - // Set optional (pointer) fields via Changed(). - for _, f := range scalarFields { - if !f.isPointer { - continue - } - varName := prefix + "Cmd" + f.goVarSuffix - if f.isCode { - // Support stdin for optional code fields too. - w(b, "\tif cmd.Flags().Changed(%q) {\n", f.flagName) - w(b, "\t\tcodeVal := %s\n", varName) - w(b, "\t\tif codeVal == \"-\" {\n") - w(b, "\t\t\tb, err := io.ReadAll(os.Stdin)\n") - w(b, "\t\t\tif err != nil {\n") - w(b, "\t\t\t\treturn fmt.Errorf(\"reading stdin: %%w\", err)\n") - w(b, "\t\t\t}\n") - w(b, "\t\t\tcodeVal = string(b)\n") - w(b, "\t\t}\n") - w(b, "\t\tbody.%s = &codeVal\n", f.goFieldName) - w(b, "\t}\n") - } else if f.enumCastType != "" { - // oapi-codegen uses a custom type for enum fields; cast before taking address. - w(b, "\tif cmd.Flags().Changed(%q) {\n", f.flagName) - w(b, "\t\tv := %s(%s)\n", f.enumCastType, varName) - w(b, "\t\tbody.%s = &v\n", f.goFieldName) - w(b, "\t}\n") - } else { - w(b, "\tif cmd.Flags().Changed(%q) {\n", f.flagName) - w(b, "\t\tv := %s\n", varName) - w(b, "\t\tbody.%s = &v\n", f.goFieldName) - w(b, "\t}\n") - } - } -} - -// ────────────────────────────────────────────────────────────────────────────── -// Helpers -// ────────────────────────────────────────────────────────────────────────────── - -func w(b *bytes.Buffer, format string, args ...any) { - fmt.Fprintf(b, format, args...) -} - -func fatalf(format string, args ...any) { - fmt.Fprintf(os.Stderr, "gen: "+format+"\n", args...) - os.Exit(1) -} - -func sortedPaths(paths map[string]PathItem) []string { - keys := make([]string, 0, len(paths)) - for k := range paths { - keys = append(keys, k) - } - sort.Strings(keys) - return keys -} - -func mergeParams(pathLevel, opLevel []Parameter) []Parameter { - // Op-level params override path-level params with same name+in. - seen := make(map[string]bool) - for _, p := range opLevel { - seen[p.In+":"+p.Name] = true - } - result := append([]Parameter{}, opLevel...) - for _, p := range pathLevel { - if !seen[p.In+":"+p.Name] { - result = append(result, p) - } - } - return result -} - -func resolveRef(s Schema, spec *Spec) Schema { - if s.Ref == "" { - return s - } - // Expect "#/components/schemas/" - name := strings.TrimPrefix(s.Ref, "#/components/schemas/") - if resolved, ok := spec.Components.Schemas[name]; ok { - return resolved - } - return s -} - -func flattenAllOf(s Schema, spec *Spec) Schema { - if len(s.AllOf) == 0 { - return s - } - merged := Schema{ - Properties: make(map[string]Schema), - } - requiredSet := make(map[string]bool) - for _, sub := range s.AllOf { - sub = resolveRef(sub, spec) - sub = flattenAllOf(sub, spec) - maps.Copy(merged.Properties, sub.Properties) - for _, r := range sub.Required { - requiredSet[r] = true - } - } - // Also merge top-level properties (if allOf is combined with properties). - maps.Copy(merged.Properties, s.Properties) - for _, r := range s.Required { - requiredSet[r] = true - } - for r := range requiredSet { - merged.Required = append(merged.Required, r) - } - return merged -} - -func schemaGoType(s Schema) string { - switch s.Type { - case "integer": - return "int" - case "boolean": - return "bool" - default: - return "string" - } -} - -func cobraFlagFunc(goType string) string { - switch goType { - case "int": - return "IntVar" - case "bool": - return "BoolVar" - default: - return "StringVar" - } -} - -func deriveCommandName(operationID string, cfg tagConfig) string { - if name, ok := commandNameOverrides[operationID]; ok { - return name - } - kebab := camelToKebab(operationID) - for _, suffix := range cfg.stripSuffix { - if before, ok := strings.CutSuffix(kebab, "-"+suffix); ok { - return before - } - } - return kebab -} - -// camelToKebab converts "listFunctions" → "list-functions". -func camelToKebab(s string) string { - var b strings.Builder - for i, r := range s { - if unicode.IsUpper(r) && i > 0 { - b.WriteByte('-') - } - b.WriteRune(unicode.ToLower(r)) - } - return b.String() -} - -// snakeToKebab converts "env_vars" → "env-vars". -func snakeToKebab(s string) string { - return strings.ReplaceAll(s, "_", "-") -} - -// snakeToPascal converts "env_vars" → "EnvVars". -func snakeToPascal(s string) string { - parts := strings.Split(s, "_") - var b strings.Builder - for _, p := range parts { - if len(p) == 0 { - continue - } - runes := []rune(p) - b.WriteRune(unicode.ToUpper(runes[0])) - b.WriteString(string(runes[1:])) - } - return b.String() -} - -// toPascal converts "listFunctions" → "ListFunctions". -func toPascal(s string) string { - if s == "" { - return s - } - runes := []rune(s) - runes[0] = unicode.ToUpper(runes[0]) - return string(runes) -} - -func escapeQuotes(s string) string { - s = strings.ReplaceAll(s, `\`, `\\`) - s = strings.ReplaceAll(s, `"`, `\"`) - // Remove newlines from descriptions. - s = strings.ReplaceAll(s, "\n", " ") - s = strings.TrimSpace(s) - return s -} - -// defaultForSchema returns the Go literal default value for a field. -func defaultForSchema(s Schema) string { - if s.Default != nil { - switch v := s.Default.(type) { - case int: - return strconv.Itoa(v) - case float64: - return strconv.Itoa(int(v)) - case bool: - if v { - return "true" - } - return "false" - case string: - return `"` + v + `"` - } - } - switch s.Type { - case "integer": - return "0" - case "boolean": - return "false" - default: - return `""` - } -} diff --git a/lunar-cli/tools/gen/main_test.go b/lunar-cli/tools/gen/main_test.go deleted file mode 100644 index 5d8c8c4..0000000 --- a/lunar-cli/tools/gen/main_test.go +++ /dev/null @@ -1,770 +0,0 @@ -package main - -import ( - "go/format" - "strings" - "testing" -) - -// ── string helpers ──────────────────────────────────────────────────────────── - -func TestCamelToKebab(t *testing.T) { - cases := []struct{ in, want string }{ - {"listFunctions", "list-functions"}, - {"getFunction", "get-function"}, - {"updateEnvVars", "update-env-vars"}, - {"createFunction", "create-function"}, - {"id", "id"}, - {"ID", "i-d"}, - {"getVersionDiff", "get-version-diff"}, - } - for _, c := range cases { - if got := camelToKebab(c.in); got != c.want { - t.Errorf("camelToKebab(%q) = %q, want %q", c.in, got, c.want) - } - } -} - -func TestSnakeToKebab(t *testing.T) { - cases := []struct{ in, want string }{ - {"env_vars", "env-vars"}, - {"cron_status", "cron-status"}, - {"name", "name"}, - {"retention_days", "retention-days"}, - } - for _, c := range cases { - if got := snakeToKebab(c.in); got != c.want { - t.Errorf("snakeToKebab(%q) = %q, want %q", c.in, got, c.want) - } - } -} - -func TestSnakeToPascal(t *testing.T) { - cases := []struct{ in, want string }{ - {"env_vars", "EnvVars"}, - {"cron_status", "CronStatus"}, - {"name", "Name"}, - {"retention_days", "RetentionDays"}, - {"id", "Id"}, - } - for _, c := range cases { - if got := snakeToPascal(c.in); got != c.want { - t.Errorf("snakeToPascal(%q) = %q, want %q", c.in, got, c.want) - } - } -} - -func TestToPascal(t *testing.T) { - cases := []struct{ in, want string }{ - {"listFunctions", "ListFunctions"}, - {"createFunction", "CreateFunction"}, - {"", ""}, - {"a", "A"}, - } - for _, c := range cases { - if got := toPascal(c.in); got != c.want { - t.Errorf("toPascal(%q) = %q, want %q", c.in, got, c.want) - } - } -} - -func TestEscapeQuotes(t *testing.T) { - cases := []struct{ in, want string }{ - {`say "hello"`, `say \"hello\"`}, - {"line1\nline2", "line1 line2"}, - {`back\slash`, `back\\slash`}, - {" trimmed ", "trimmed"}, - } - for _, c := range cases { - if got := escapeQuotes(c.in); got != c.want { - t.Errorf("escapeQuotes(%q) = %q, want %q", c.in, got, c.want) - } - } -} - -// ── deriveCommandName ───────────────────────────────────────────────────────── - -func TestDeriveCommandName_Override(t *testing.T) { - cfg := tagConfigs["Functions"] - cases := []struct{ opID, want string }{ - {"updateEnvVars", "env"}, - {"updateKV", "kv"}, - {"getNextRun", "next-run"}, - } - for _, c := range cases { - if got := deriveCommandName(c.opID, cfg); got != c.want { - t.Errorf("deriveCommandName(%q) = %q, want %q", c.opID, got, c.want) - } - } -} - -func TestDeriveCommandName_StripSuffix(t *testing.T) { - cases := []struct { - tag string - opID string - want string - }{ - {"Functions", "listFunctions", "list"}, - {"Functions", "createFunction", "create"}, - {"Functions", "deleteFunction", "delete"}, - {"Versions", "listVersions", "list"}, - {"Versions", "getVersionDiff", "diff"}, // override - {"Executions", "listExecutions", "list"}, - {"Executions", "getExecution", "get"}, - {"API Tokens", "listTokens", "list"}, - {"API Tokens", "revokeToken", "revoke"}, - } - for _, c := range cases { - cfg := tagConfigs[c.tag] - if got := deriveCommandName(c.opID, cfg); got != c.want { - t.Errorf("deriveCommandName(%q, %q) = %q, want %q", c.opID, c.tag, got, c.want) - } - } -} - -// ── schemaGoType / cobraFlagFunc ────────────────────────────────────────────── - -func TestSchemaGoType(t *testing.T) { - cases := []struct { - schema Schema - want string - }{ - {Schema{Type: "integer"}, "int"}, - {Schema{Type: "boolean"}, "bool"}, - {Schema{Type: "string"}, "string"}, - {Schema{Type: ""}, "string"}, - } - for _, c := range cases { - if got := schemaGoType(c.schema); got != c.want { - t.Errorf("schemaGoType(%q) = %q, want %q", c.schema.Type, got, c.want) - } - } -} - -func TestCobraFlagFunc(t *testing.T) { - cases := []struct{ goType, want string }{ - {"int", "IntVar"}, - {"bool", "BoolVar"}, - {"string", "StringVar"}, - {"[]string", "StringVar"}, // fallback - } - for _, c := range cases { - if got := cobraFlagFunc(c.goType); got != c.want { - t.Errorf("cobraFlagFunc(%q) = %q, want %q", c.goType, got, c.want) - } - } -} - -// ── mergeParams ─────────────────────────────────────────────────────────────── - -func TestMergeParams_OpOverridesPath(t *testing.T) { - pathLevel := []Parameter{ - {Name: "id", In: "path"}, - {Name: "format", In: "query", Description: "path-level"}, - } - opLevel := []Parameter{ - {Name: "format", In: "query", Description: "op-level"}, - } - result := mergeParams(pathLevel, opLevel) - - // Should have both id (from path-level) and format (op-level wins) - if len(result) != 2 { - t.Fatalf("expected 2 params, got %d: %v", len(result), result) - } - // format should be the op-level version - for _, p := range result { - if p.Name == "format" && p.Description != "op-level" { - t.Error("expected op-level format to override path-level") - } - } -} - -func TestMergeParams_PathLevelAdded(t *testing.T) { - pathLevel := []Parameter{{Name: "id", In: "path"}} - opLevel := []Parameter{{Name: "limit", In: "query"}} - result := mergeParams(pathLevel, opLevel) - if len(result) != 2 { - t.Fatalf("expected 2 params, got %d", len(result)) - } -} - -func TestMergeParams_NilInputs(t *testing.T) { - result := mergeParams(nil, nil) - if len(result) != 0 { - t.Errorf("expected empty result, got %v", result) - } -} - -// ── resolveRef ──────────────────────────────────────────────────────────────── - -func TestResolveRef_ResolvesKnownRef(t *testing.T) { - spec := &Spec{ - Components: Components{ - Schemas: map[string]Schema{ - "MySchema": {Type: "object", Properties: map[string]Schema{ - "name": {Type: "string"}, - }}, - }, - }, - } - s := Schema{Ref: "#/components/schemas/MySchema"} - resolved := resolveRef(s, spec) - if resolved.Type != "object" { - t.Errorf("expected object type, got %q", resolved.Type) - } - if _, ok := resolved.Properties["name"]; !ok { - t.Error("expected 'name' property in resolved schema") - } -} - -func TestResolveRef_UnknownRef_ReturnsOriginal(t *testing.T) { - spec := &Spec{Components: Components{Schemas: map[string]Schema{}}} - s := Schema{Ref: "#/components/schemas/Missing"} - resolved := resolveRef(s, spec) - if resolved.Ref != s.Ref { - t.Errorf("expected original schema back, got %+v", resolved) - } -} - -func TestResolveRef_NoRef_ReturnsOriginal(t *testing.T) { - spec := &Spec{} - s := Schema{Type: "string"} - resolved := resolveRef(s, spec) - if resolved.Type != "string" { - t.Errorf("expected string type, got %q", resolved.Type) - } -} - -// ── flattenAllOf ────────────────────────────────────────────────────────────── - -func TestFlattenAllOf_MergesProperties(t *testing.T) { - spec := &Spec{} - s := Schema{ - AllOf: []Schema{ - {Type: "object", Properties: map[string]Schema{"a": {Type: "string"}}}, - {Type: "object", Properties: map[string]Schema{"b": {Type: "integer"}}}, - }, - } - flat := flattenAllOf(s, spec) - if _, ok := flat.Properties["a"]; !ok { - t.Error("expected 'a' property from first allOf member") - } - if _, ok := flat.Properties["b"]; !ok { - t.Error("expected 'b' property from second allOf member") - } -} - -func TestFlattenAllOf_MergesRequired(t *testing.T) { - spec := &Spec{} - s := Schema{ - AllOf: []Schema{ - {Required: []string{"name"}}, - {Required: []string{"code"}}, - }, - } - flat := flattenAllOf(s, spec) - required := make(map[string]bool) - for _, r := range flat.Required { - required[r] = true - } - if !required["name"] { - t.Error("expected 'name' in required") - } - if !required["code"] { - t.Error("expected 'code' in required") - } -} - -func TestFlattenAllOf_NoAllOf_ReturnsOriginal(t *testing.T) { - spec := &Spec{} - s := Schema{Type: "string"} - flat := flattenAllOf(s, spec) - if flat.Type != "string" { - t.Errorf("expected original schema, got %+v", flat) - } -} - -// ── buildFieldInfo ──────────────────────────────────────────────────────────── - -func TestBuildFieldInfo_StringField(t *testing.T) { - f := buildFieldInfo("name", "", Schema{Type: "string"}, true, "the name") - if f.flagName != "name" { - t.Errorf("flagName = %q", f.flagName) - } - if f.goType != "string" { - t.Errorf("goType = %q", f.goType) - } - if f.defaultVal != `""` { - t.Errorf("defaultVal = %q", f.defaultVal) - } - if !f.required { - t.Error("expected required=true") - } - if f.desc != "the name" { - t.Errorf("desc = %q", f.desc) - } -} - -func TestBuildFieldInfo_IntegerField(t *testing.T) { - f := buildFieldInfo("limit", "", Schema{Type: "integer", Default: float64(20)}, false, "max items") - if f.goType != "int" { - t.Errorf("goType = %q, want int", f.goType) - } - if f.defaultVal != "20" { - t.Errorf("defaultVal = %q, want 20", f.defaultVal) - } -} - -func TestBuildFieldInfo_BooleanField(t *testing.T) { - f := buildFieldInfo("disabled", "", Schema{Type: "boolean"}, false, "") - if f.goType != "bool" { - t.Errorf("goType = %q, want bool", f.goType) - } - if f.defaultVal != "false" { - t.Errorf("defaultVal = %q, want false", f.defaultVal) - } -} - -func TestBuildFieldInfo_MapField(t *testing.T) { - valSchema := Schema{Type: "string"} - f := buildFieldInfo("env_vars", "", Schema{ - Type: "object", - AdditionalProperties: &valSchema, - }, false, "env vars") - if !f.isMap { - t.Error("expected isMap=true for object with additionalProperties") - } - if f.goType != "[]string" { - t.Errorf("goType = %q, want []string", f.goType) - } - // env_vars gets a shorter flag name - if f.flagName != "env" { - t.Errorf("flagName = %q, want env", f.flagName) - } -} - -func TestBuildFieldInfo_MapField_KV(t *testing.T) { - valSchema := Schema{Type: "string"} - f := buildFieldInfo("kv", "", Schema{ - Type: "object", - AdditionalProperties: &valSchema, - }, false, "") - if !f.isMap { - t.Error("expected isMap=true") - } - // kv does not get a shortened flag name - if f.flagName != "kv" { - t.Errorf("flagName = %q, want kv", f.flagName) - } -} - -func TestBuildFieldInfo_CodeField(t *testing.T) { - f := buildFieldInfo("code", "", Schema{Type: "string"}, true, "Lua code") - if !f.isCode { - t.Error("expected isCode=true for 'code' string field") - } -} - -func TestBuildFieldInfo_EnumField_SetsEnumCastType(t *testing.T) { - f := buildFieldInfo("cron_status", "UpdateFunctionRequest", - Schema{Type: "string", Enum: []any{"active", "paused"}}, - false, "cron status") - if f.enumCastType == "" { - t.Error("expected enumCastType to be set for enum field with schemaName") - } - if !strings.Contains(f.enumCastType, "UpdateFunctionRequest") { - t.Errorf("enumCastType %q should contain schema name", f.enumCastType) - } -} - -func TestBuildFieldInfo_EnumField_NoSchema_NoEnumCast(t *testing.T) { - // Without a schemaName, no enum cast should be emitted (e.g. query params) - f := buildFieldInfo("status", "", - Schema{Type: "string", Enum: []any{"active", "paused"}}, - false, "") - if f.enumCastType != "" { - t.Errorf("expected empty enumCastType for query param enum, got %q", f.enumCastType) - } -} - -func TestBuildFieldInfo_SnakeCaseFieldName(t *testing.T) { - f := buildFieldInfo("cron_status", "", Schema{Type: "string"}, false, "") - if f.flagName != "cron-status" { - t.Errorf("flagName = %q, want cron-status", f.flagName) - } - if f.goFieldName != "CronStatus" { - t.Errorf("goFieldName = %q, want CronStatus", f.goFieldName) - } -} - -// ── buildOpInfo ─────────────────────────────────────────────────────────────── - -func TestBuildOpInfo_SimpleGet(t *testing.T) { - spec := &Spec{} - op := &Operation{ - OperationID: "getFunction", - Summary: "Get a function", - Tags: []string{"Functions"}, - Parameters: []Parameter{ - {Name: "id", In: "path", Schema: Schema{Type: "string"}}, - }, - } - info, err := buildOpInfo(op, "/api/functions/{id}", "Functions", spec) - if err != nil { - t.Fatal(err) - } - if info.commandName != "get" { - t.Errorf("commandName = %q, want get", info.commandName) - } - if info.goFuncName != "GetFunction" { - t.Errorf("goFuncName = %q, want GetFunction", info.goFuncName) - } - if len(info.pathArgs) != 1 || info.pathArgs[0].paramName != "id" { - t.Errorf("pathArgs = %v", info.pathArgs) - } - if info.hasBody { - t.Error("expected no body for GET") - } -} - -func TestBuildOpInfo_IntegerPathArg(t *testing.T) { - spec := &Spec{} - op := &Operation{ - OperationID: "getVersion", - Tags: []string{"Versions"}, - Parameters: []Parameter{ - {Name: "functionId", In: "path", Schema: Schema{Type: "string"}}, - {Name: "version", In: "path", Schema: Schema{Type: "integer"}}, - }, - } - info, err := buildOpInfo(op, "/api/functions/{functionId}/versions/{version}", "Versions", spec) - if err != nil { - t.Fatal(err) - } - if len(info.pathArgs) != 2 { - t.Fatalf("expected 2 path args, got %d", len(info.pathArgs)) - } - versionArg := info.pathArgs[1] - if versionArg.goType != "int" { - t.Errorf("version pathArg.goType = %q, want int", versionArg.goType) - } -} - -func TestBuildOpInfo_QueryParams(t *testing.T) { - spec := &Spec{} - op := &Operation{ - OperationID: "listFunctions", - Tags: []string{"Functions"}, - Parameters: []Parameter{ - {Name: "limit", In: "query", Schema: Schema{Type: "integer", Default: float64(20)}}, - {Name: "offset", In: "query", Schema: Schema{Type: "integer"}}, - }, - } - info, err := buildOpInfo(op, "/api/functions", "Functions", spec) - if err != nil { - t.Fatal(err) - } - if len(info.queryFields) != 2 { - t.Fatalf("expected 2 query fields, got %d", len(info.queryFields)) - } - if info.queryFields[0].flagName != "limit" { - t.Errorf("queryFields[0].flagName = %q", info.queryFields[0].flagName) - } -} - -func TestBuildOpInfo_RequestBody(t *testing.T) { - spec := &Spec{ - Components: Components{ - Schemas: map[string]Schema{ - "CreateFunctionRequest": { - Type: "object", - Required: []string{"name", "code"}, - Properties: map[string]Schema{ - "name": {Type: "string"}, - "code": {Type: "string"}, - }, - }, - }, - }, - } - op := &Operation{ - OperationID: "createFunction", - Tags: []string{"Functions"}, - RequestBody: &RequestBody{ - Content: map[string]MediaType{ - "application/json": {Schema: Schema{Ref: "#/components/schemas/CreateFunctionRequest"}}, - }, - }, - } - info, err := buildOpInfo(op, "/api/functions", "Functions", spec) - if err != nil { - t.Fatal(err) - } - if !info.hasBody { - t.Error("expected hasBody=true") - } - if info.bodySchemaName != "CreateFunctionRequest" { - t.Errorf("bodySchemaName = %q", info.bodySchemaName) - } - if len(info.bodyFields) != 2 { - t.Fatalf("expected 2 body fields, got %d", len(info.bodyFields)) - } - // Required fields should not be pointers - for _, f := range info.bodyFields { - if f.flagName == "name" && f.isPointer { - t.Error("required field 'name' should not be a pointer") - } - if f.flagName == "code" && f.isPointer { - t.Error("required field 'code' should not be a pointer") - } - } -} - -// ── generateFile ───────────────────────────────────────────────────────────── - -// makeSimpleOp creates a minimal opInfo for code generation tests. -func makeSimpleOp(operationID, commandName, summary string) opInfo { - return opInfo{ - operationID: operationID, - commandName: commandName, - summary: summary, - goFuncName: toPascal(operationID), - } -} - -func TestGenerateFile_ProducesValidGo(t *testing.T) { - cfg := tagConfigs["Functions"] - ops := []opInfo{ - makeSimpleOp("listFunctions", "list", "List all functions"), - } - src, err := generateFile("Functions", "Function management", cfg, ops) - if err != nil { - t.Fatalf("generateFile error: %v\nsource:\n%s", err, src) - } - // Must re-format without error (already formatted, but double-check) - if _, err := format.Source(src); err != nil { - t.Errorf("output is not valid Go: %v\nsource:\n%s", err, src) - } -} - -func TestGenerateFile_ContainsPackageDeclaration(t *testing.T) { - cfg := tagConfigs["Functions"] - src, _ := generateFile("Functions", "desc", cfg, []opInfo{makeSimpleOp("listFunctions", "list", "")}) - if !strings.Contains(string(src), "package cmd") { - t.Error("expected 'package cmd' in generated source") - } -} - -func TestGenerateFile_ContainsGeneratedComment(t *testing.T) { - cfg := tagConfigs["Functions"] - src, _ := generateFile("Functions", "desc", cfg, []opInfo{makeSimpleOp("listFunctions", "list", "")}) - if !strings.Contains(string(src), "DO NOT EDIT") { - t.Error("expected DO NOT EDIT comment in generated source") - } -} - -func TestGenerateFile_ContainsParentCommand(t *testing.T) { - cfg := tagConfigs["Functions"] - src, _ := generateFile("Functions", "desc", cfg, []opInfo{makeSimpleOp("listFunctions", "list", "")}) - s := string(src) - if !strings.Contains(s, "functionsCmd") { - t.Error("expected functionsCmd in generated source") - } - if !strings.Contains(s, `rootCmd.AddCommand(functionsCmd)`) { - t.Error("expected rootCmd.AddCommand(functionsCmd)") - } -} - -func TestGenerateFile_WithPathArg_EmitsExactArgs(t *testing.T) { - cfg := tagConfigs["Functions"] - ops := []opInfo{{ - operationID: "getFunction", - commandName: "get", - summary: "Get a function", - goFuncName: "GetFunction", - pathArgs: []pathArg{{paramName: "id", goType: "string", displayName: ""}}, - }} - src, err := generateFile("Functions", "desc", cfg, ops) - if err != nil { - t.Fatal(err) - } - s := string(src) - if !strings.Contains(s, "cobra.ExactArgs(1)") { - t.Error("expected cobra.ExactArgs(1) for one path arg") - } -} - -func TestGenerateFile_WithIntPathArg_EmitsStrconv(t *testing.T) { - cfg := tagConfigs["Versions"] - ops := []opInfo{{ - operationID: "getVersion", - commandName: "get", - summary: "Get a version", - goFuncName: "GetVersion", - pathArgs: []pathArg{ - {paramName: "functionId", goType: "string", displayName: ""}, - {paramName: "version", goType: "int", displayName: ""}, - }, - }} - src, err := generateFile("Versions", "desc", cfg, ops) - if err != nil { - t.Fatal(err) - } - s := string(src) - if !strings.Contains(s, `"strconv"`) { - t.Error("expected strconv import for int path arg") - } - if !strings.Contains(s, "strconv.Atoi") { - t.Error("expected strconv.Atoi call") - } -} - -func TestGenerateFile_WithQueryFields_EmitsParamsStruct(t *testing.T) { - cfg := tagConfigs["Functions"] - ops := []opInfo{{ - operationID: "listFunctions", - commandName: "list", - summary: "List functions", - goFuncName: "ListFunctions", - queryFields: []fieldInfo{ - {flagName: "limit", goVarSuffix: "Limit", goFieldName: "Limit", goType: "int", defaultVal: "20"}, - {flagName: "offset", goVarSuffix: "Offset", goFieldName: "Offset", goType: "int", defaultVal: "0"}, - }, - }} - src, err := generateFile("Functions", "desc", cfg, ops) - if err != nil { - t.Fatal(err) - } - s := string(src) - if !strings.Contains(s, "client.ListFunctionsParams") { - t.Error("expected Params struct") - } - if !strings.Contains(s, `"github.com/dimiro1/lunar/lunar-cli/client"`) { - t.Error("expected client import") - } -} - -func TestGenerateFile_WithBody_EmitsBodyConstruction(t *testing.T) { - cfg := tagConfigs["Functions"] - ops := []opInfo{{ - operationID: "createFunction", - commandName: "create", - summary: "Create a function", - goFuncName: "CreateFunction", - hasBody: true, - bodyTypeName: "client.CreateFunctionJSONRequestBody", - bodyFields: []fieldInfo{ - {flagName: "name", goVarSuffix: "Name", goFieldName: "Name", goType: "string", defaultVal: `""`, required: true}, - {flagName: "code", goVarSuffix: "Code", goFieldName: "Code", goType: "string", defaultVal: `""`, required: true, isCode: true}, - }, - }} - src, err := generateFile("Functions", "desc", cfg, ops) - if err != nil { - t.Fatal(err) - } - s := string(src) - if !strings.Contains(s, "client.CreateFunctionJSONRequestBody") { - t.Error("expected body type in generated source") - } - if !strings.Contains(s, `io.ReadAll(os.Stdin)`) { - t.Error("expected stdin read for code field") - } - if !strings.Contains(s, `MarkFlagRequired("name")`) { - t.Error("expected MarkFlagRequired for name") - } -} - -func TestGenerateFile_WithMapField_EmitsStringArray(t *testing.T) { - cfg := tagConfigs["Functions"] - ops := []opInfo{{ - operationID: "updateEnvVars", - commandName: "env", - summary: "Update env vars", - goFuncName: "UpdateEnvVars", - hasBody: true, - bodyTypeName: "client.UpdateEnvVarsJSONRequestBody", - pathArgs: []pathArg{{paramName: "id", goType: "string", displayName: ""}}, - bodyFields: []fieldInfo{ - {flagName: "env", goVarSuffix: "EnvVars", goFieldName: "EnvVars", goType: "[]string", defaultVal: "nil", isMap: true}, - }, - }} - src, err := generateFile("Functions", "desc", cfg, ops) - if err != nil { - t.Fatal(err) - } - s := string(src) - if !strings.Contains(s, "StringArrayVar") { - t.Error("expected StringArrayVar for map field") - } - if !strings.Contains(s, "strings.SplitN") { - t.Error("expected strings.SplitN for KEY=VALUE parsing") - } -} - -func TestGenerateFile_WithEnumField_EmitsCast(t *testing.T) { - cfg := tagConfigs["Functions"] - ops := []opInfo{{ - operationID: "updateFunction", - commandName: "update", - summary: "Update a function", - goFuncName: "UpdateFunction", - hasBody: true, - bodyTypeName: "client.UpdateFunctionJSONRequestBody", - bodySchemaName: "UpdateFunctionRequest", - pathArgs: []pathArg{{paramName: "id", goType: "string", displayName: ""}}, - bodyFields: []fieldInfo{ - { - flagName: "cron-status", - goVarSuffix: "CronStatus", - goFieldName: "CronStatus", - goType: "string", - defaultVal: `""`, - isPointer: true, - enumCastType: "client.UpdateFunctionRequestCronStatus", - }, - }, - }} - src, err := generateFile("Functions", "desc", cfg, ops) - if err != nil { - t.Fatal(err) - } - s := string(src) - if !strings.Contains(s, "client.UpdateFunctionRequestCronStatus") { - t.Error("expected enum cast type in generated source") - } -} - -func TestGenerateFile_OptionalField_UsesChangedCheck(t *testing.T) { - cfg := tagConfigs["Functions"] - ops := []opInfo{{ - operationID: "updateFunction", - commandName: "update", - goFuncName: "UpdateFunction", - hasBody: true, - bodyTypeName: "client.UpdateFunctionJSONRequestBody", - pathArgs: []pathArg{{paramName: "id", goType: "string", displayName: ""}}, - bodyFields: []fieldInfo{ - {flagName: "name", goVarSuffix: "Name", goFieldName: "Name", goType: "string", defaultVal: `""`, isPointer: true}, - }, - }} - src, err := generateFile("Functions", "desc", cfg, ops) - if err != nil { - t.Fatal(err) - } - s := string(src) - if !strings.Contains(s, `cmd.Flags().Changed("name")`) { - t.Error("expected Changed() check for optional field") - } -} - -func TestGenerateFile_NoClientImport_WhenNoQueryOrBody(t *testing.T) { - cfg := tagConfigs["API Tokens"] - ops := []opInfo{ - makeSimpleOp("listTokens", "list", "List tokens"), - } - src, _ := generateFile("API Tokens", "desc", cfg, ops) - // No query fields, no body → client import should not be present - if strings.Contains(string(src), `"github.com/dimiro1/lunar/lunar-cli/client"`) { - t.Error("client import should be omitted when no query params or body") - } -} diff --git a/lunar-cli/tools/tools.go b/lunar-cli/tools/tools.go deleted file mode 100644 index 2c96f4b..0000000 --- a/lunar-cli/tools/tools.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build tools - -package tools - -import ( - _ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen" -) diff --git a/mise.toml b/mise.toml index 95df888..d5f73b3 100644 --- a/mise.toml +++ b/mise.toml @@ -40,10 +40,9 @@ run = [ "go build -o ../$BUILD_DIR/$CLI_BINARY_NAME .", ] -[tasks.generate-cli] -description = "Regenerate CLI from openapi.yaml (go generate)" -dir = "lunar-cli" -run = "go generate ./..." +[tasks.generate-graphql] +description = "Regenerate GraphQL code from the schema (gqlgen)" +run = "go generate ./internal/graph/..." # --------------------------------------------------------------------------- # Test @@ -108,16 +107,91 @@ run = "go run ./cmd" description = "Start development mode with air (live reload)" run = "air" +[tasks.seed] +description = "Create a few example functions on a running server (covers create/env/kv)" +depends = ["build-cli"] +run = ''' +set -euo pipefail + +SERVER="${LUNAR_SERVER:-http://localhost:${PORT:-3000}}" +TOKEN="${LUNAR_TOKEN:-${API_KEY:-}}" +if [ -z "$TOKEN" ] && [ -f "${DATA_DIR:-./data}/api_key.txt" ]; then + TOKEN="$(cat "${DATA_DIR:-./data}/api_key.txt")" +fi +if [ -z "$TOKEN" ]; then + echo "No API token found. Set LUNAR_TOKEN or API_KEY, or start the server once" >&2 + echo "so that ${DATA_DIR:-./data}/api_key.txt is generated, then re-run." >&2 + exit 1 +fi +export LUNAR_SERVER="$SERVER" LUNAR_TOKEN="$TOKEN" +CLI="$BUILD_DIR/$CLI_BINARY_NAME" + +# create_fn ; reads Lua from stdin ; prints the new id. +create_fn() { + "$CLI" functions create --name "$1" --description "$2" --code - -o json \ + | sed -n 's/^ "id": "\([^"]*\)".*/\1/p' | head -1 +} + +echo "Seeding $SERVER ..." + +# 1. hello — the simplest possible function. +create_fn hello "Returns a plain-text greeting" >/dev/null <<'LUA' +function handler(ctx, event) + return { statusCode = 200, body = "Hello from Lunar!\n" } +end +LUA + +# 2. echo — reflects the incoming request back as JSON. +create_fn echo "Echoes the request as JSON" >/dev/null <<'LUA' +function handler(ctx, event) + local body, err = json.encode({ + method = event.method, + path = event.relativePath, + query = event.query, + body = event.body, + }) + if err then return { statusCode = 500, body = err } end + return { + statusCode = 200, + headers = { ["Content-Type"] = "application/json" }, + body = body, + } +end +LUA + +# 3. counter — persists a hit count in the KV store; seed an initial value. +COUNTER_ID="$(create_fn counter "Counts requests via the KV store" <<'LUA' +function handler(ctx, event) + local n = tonumber(kv.get("count") or "0") + 1 + kv.set("count", tostring(n)) + return { statusCode = 200, body = "count: " .. n .. "\n" } +end +LUA +)" +"$CLI" functions kv "$COUNTER_ID" --global=false --kv count=100 >/dev/null + +# 4. greet — reads a greeting from an env var; seed the env var. +GREET_ID="$(create_fn greet "Greets using an env var" <<'LUA' +function handler(ctx, event) + local greeting = env.get("GREETING") or "Hello" + local who = event.query["name"] or "world" + return { statusCode = 200, body = greeting .. ", " .. who .. "!\n" } +end +LUA +)" +"$CLI" functions env "$GREET_ID" --env GREETING=Howdy >/dev/null + +echo "Done. Created: hello, echo, counter, greet" +echo "Try: curl $SERVER/fn/$GREET_ID?name=Lunar" +''' + [tasks.docker] description = "Run with Docker Compose" run = "docker compose up" [tasks.clean] description = "Remove build artifacts" -run = [ - "rm -rf $BUILD_DIR", - "rm -f cli/cmd/*.gen.go cli/client/client.gen.go", -] +run = "rm -rf $BUILD_DIR" # --------------------------------------------------------------------------- # Release