Key and Path Formats
PascalCase keys with key_format :pascal and kebab-case paths with path_format :kebab
API Definition
config/apis/nimble_gecko.rb
rb
# frozen_string_literal: true
Apiwork::API.define '/nimble_gecko' do
key_format :pascal
path_format :kebab
export :openapi
export :typescript
export :zod
resources :meal_plans
endModels
app/models/nimble_gecko/meal_plan.rb
rb
# frozen_string_literal: true
module NimbleGecko
class MealPlan < ApplicationRecord
has_many :cooking_steps, dependent: :destroy
accepts_nested_attributes_for :cooking_steps, allow_destroy: true
validates :title, presence: true
end
endDatabase Table
| Column | Type | Nullable | Default |
|---|---|---|---|
| id | string | ||
| cook_time | integer | ✓ | |
| created_at | datetime | ||
| serving_size | integer | ✓ | |
| title | string | ||
| updated_at | datetime |
app/models/nimble_gecko/cooking_step.rb
rb
# frozen_string_literal: true
module NimbleGecko
class CookingStep < ApplicationRecord
belongs_to :meal_plan
validates :instruction, presence: true
validates :step_number, presence: true
end
endDatabase Table
| Column | Type | Nullable | Default |
|---|---|---|---|
| id | string | ||
| created_at | datetime | ||
| duration_minutes | integer | ✓ | |
| instruction | string | ||
| meal_plan_id | string | ||
| step_number | integer | ||
| updated_at | datetime |
Representations
app/representations/nimble_gecko/meal_plan_representation.rb
rb
# frozen_string_literal: true
module NimbleGecko
class MealPlanRepresentation < Apiwork::Representation::Base
attribute :id
attribute :title, writable: true
attribute :cook_time, writable: true
attribute :serving_size, writable: true
attribute :created_at
attribute :updated_at
has_many :cooking_steps, include: :always, writable: true
end
endapp/representations/nimble_gecko/cooking_step_representation.rb
rb
# frozen_string_literal: true
module NimbleGecko
class CookingStepRepresentation < Apiwork::Representation::Base
attribute :id
attribute :step_number, writable: true
attribute :instruction, writable: true
attribute :duration_minutes, writable: true
end
endContracts
app/contracts/nimble_gecko/meal_plan_contract.rb
rb
# frozen_string_literal: true
module NimbleGecko
class MealPlanContract < Apiwork::Contract::Base
representation MealPlanRepresentation
end
endControllers
app/controllers/nimble_gecko/meal_plans_controller.rb
rb
# frozen_string_literal: true
module NimbleGecko
class MealPlansController < ApplicationController
before_action :set_meal_plan, only: %i[show update destroy]
def index
meal_plans = MealPlan.all
expose meal_plans
end
def show
expose meal_plan
end
def create
meal_plan = MealPlan.create(contract.body[:meal_plan])
expose meal_plan
end
def update
meal_plan.update(contract.body[:meal_plan])
expose meal_plan
end
def destroy
meal_plan.destroy
expose meal_plan
end
private
attr_reader :meal_plan
def set_meal_plan
@meal_plan = MealPlan.find(params[:id])
end
end
endRequest Examples
Create meal plan with PascalCase body
Request
http
POST /nimble-gecko/meal-plans
Content-Type: application/json
{
"MealPlan": {
"Title": "Pasta Carbonara",
"CookTime": 30,
"ServingSize": 4,
"CookingSteps": [
{
"StepNumber": 1,
"Instruction": "Boil salted water",
"DurationMinutes": 10
},
{
"StepNumber": 2,
"Instruction": "Cook pasta until al dente",
"DurationMinutes": 8
},
{
"StepNumber": 3,
"Instruction": "Mix with egg yolk sauce",
"DurationMinutes": 5
}
]
}
}Response 400
json
{
"Issues": [
{
"Code": "field_missing",
"Detail": "Required",
"Meta": {
"Field": "OP"
},
"Path": [
"meal_plan",
"cooking_steps",
0,
"OP"
],
"Pointer": "/meal_plan/cooking_steps/0/OP"
},
{
"Code": "field_missing",
"Detail": "Required",
"Meta": {
"Field": "OP"
},
"Path": [
"meal_plan",
"cooking_steps",
1,
"OP"
],
"Pointer": "/meal_plan/cooking_steps/1/OP"
},
{
"Code": "field_missing",
"Detail": "Required",
"Meta": {
"Field": "OP"
},
"Path": [
"meal_plan",
"cooking_steps",
2,
"OP"
],
"Pointer": "/meal_plan/cooking_steps/2/OP"
}
],
"Layer": "contract"
}List meal plans
Request
http
GET /nimble-gecko/meal-plansResponse 200
json
{
"MealPlans": [
{
"Id": "60e6912b-2e98-5f0c-892b-391c9c742417",
"Title": "Pasta Carbonara",
"CookTime": 30,
"ServingSize": 4,
"CreatedAt": "2024-01-01T12:00:00.000Z",
"UpdatedAt": "2024-01-01T12:00:00.000Z",
"CookingSteps": []
},
{
"Id": "3b027918-ddeb-5a41-95d9-cc041dce69e9",
"Title": "Caesar Salad",
"CookTime": 15,
"ServingSize": 2,
"CreatedAt": "2024-01-01T12:00:00.000Z",
"UpdatedAt": "2024-01-01T12:00:00.000Z",
"CookingSteps": []
}
],
"Pagination": {
"Items": 2,
"Total": 1,
"Current": 1,
"Next": null,
"Prev": null
}
}Update meal plan with PascalCase body
Request
http
PATCH /nimble-gecko/meal-plans/60e6912b-2e98-5f0c-892b-391c9c742417
Content-Type: application/json
{
"MealPlan": {
"CookTime": 25,
"ServingSize": 6
}
}Response 200
json
{
"MealPlan": {
"Id": "60e6912b-2e98-5f0c-892b-391c9c742417",
"Title": "Pasta Carbonara",
"CookTime": 25,
"ServingSize": 6,
"CreatedAt": "2024-01-01T12:00:00.000Z",
"UpdatedAt": "2024-01-01T12:00:00.000Z",
"CookingSteps": []
}
}Generated Output
Introspection
json
{
"base_path": "/nimble-gecko",
"fingerprint": "9547eaf6efc1a39e",
"locales": [],
"enums": {
"error_layer": {
"deprecated": false,
"description": null,
"example": null,
"values": [
"http",
"contract",
"domain"
]
}
},
"error_codes": {
"unprocessable_entity": {
"description": "Unprocessable Entity",
"status": 422
}
},
"info": null,
"resources": {
"meal_plans": {
"actions": {
"index": {
"deprecated": false,
"description": null,
"method": "get",
"operation_id": null,
"path": "/meal-plans",
"raises": [],
"request": {
"description": null,
"body": {},
"query": {
"page": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "reference",
"reference": "meal_plan_page"
}
}
},
"response": {
"description": null,
"body": {
"deprecated": null,
"description": null,
"nullable": null,
"optional": null,
"type": "object",
"partial": null,
"shape": {
"meal_plans": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "array",
"default": null,
"example": null,
"max": null,
"min": null,
"of": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "meal_plan"
},
"shape": {}
},
"meta": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "object",
"partial": false,
"shape": {}
},
"pagination": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "offset_pagination"
}
}
},
"no_content": false
},
"summary": null,
"tags": []
},
"show": {
"deprecated": false,
"description": null,
"method": "get",
"operation_id": null,
"path": "/meal-plans/:id",
"raises": [],
"request": {
"description": null,
"body": {},
"query": {}
},
"response": {
"description": null,
"body": {
"deprecated": null,
"description": null,
"nullable": null,
"optional": null,
"type": "object",
"partial": null,
"shape": {
"meal_plan": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "meal_plan"
},
"meta": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "object",
"partial": false,
"shape": {}
}
}
},
"no_content": false
},
"summary": null,
"tags": []
},
"create": {
"deprecated": false,
"description": null,
"method": "post",
"operation_id": null,
"path": "/meal-plans",
"raises": [
"unprocessable_entity"
],
"request": {
"description": null,
"body": {
"meal_plan": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "meal_plan_create_payload"
}
},
"query": {}
},
"response": {
"description": null,
"body": {
"deprecated": null,
"description": null,
"nullable": null,
"optional": null,
"type": "object",
"partial": null,
"shape": {
"meal_plan": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "meal_plan"
},
"meta": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "object",
"partial": false,
"shape": {}
}
}
},
"no_content": false
},
"summary": null,
"tags": []
},
"update": {
"deprecated": false,
"description": null,
"method": "patch",
"operation_id": null,
"path": "/meal-plans/:id",
"raises": [
"unprocessable_entity"
],
"request": {
"description": null,
"body": {
"meal_plan": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "meal_plan_update_payload"
}
},
"query": {}
},
"response": {
"description": null,
"body": {
"deprecated": null,
"description": null,
"nullable": null,
"optional": null,
"type": "object",
"partial": null,
"shape": {
"meal_plan": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "meal_plan"
},
"meta": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "object",
"partial": false,
"shape": {}
}
}
},
"no_content": false
},
"summary": null,
"tags": []
},
"destroy": {
"deprecated": false,
"description": null,
"method": "delete",
"operation_id": null,
"path": "/meal-plans/:id",
"raises": [],
"request": {
"description": null,
"body": {},
"query": {}
},
"response": {
"description": null,
"body": null,
"no_content": true
},
"summary": null,
"tags": []
}
},
"identifier": "meal_plans",
"parent_identifiers": [],
"path": "meal-plans",
"resources": {}
}
},
"types": {
"cooking_step": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"duration_minutes": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"id": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"instruction": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"step_number": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
}
},
"type": "object",
"variants": []
},
"cooking_step_nested_create_payload": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"OP": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "literal",
"value": "create"
},
"duration_minutes": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 2147483647,
"min": -2147483648
},
"instruction": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"step_number": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 2147483647,
"min": -2147483648
}
},
"type": "object",
"variants": []
},
"cooking_step_nested_delete_payload": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"OP": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "literal",
"value": "delete"
},
"id": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
}
},
"type": "object",
"variants": []
},
"cooking_step_nested_payload": {
"deprecated": false,
"description": null,
"discriminator": "OP",
"example": null,
"extends": [],
"shape": {},
"type": "union",
"variants": [
{
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "cooking_step_nested_create_payload"
},
{
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "cooking_step_nested_update_payload"
},
{
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "cooking_step_nested_delete_payload"
}
]
},
"cooking_step_nested_update_payload": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"OP": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "literal",
"value": "update"
},
"duration_minutes": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 2147483647,
"min": -2147483648
},
"id": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"instruction": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"step_number": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 2147483647,
"min": -2147483648
}
},
"type": "object",
"variants": []
},
"error": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"issues": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "array",
"default": null,
"example": null,
"max": null,
"min": null,
"of": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "error_issue"
},
"shape": {}
},
"layer": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "error_layer"
}
},
"type": "object",
"variants": []
},
"error_issue": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"code": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"detail": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"meta": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "object",
"partial": false,
"shape": {}
},
"path": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "array",
"default": null,
"example": null,
"max": null,
"min": null,
"of": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "union",
"discriminator": null,
"variants": [
{
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
{
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
}
]
},
"shape": {}
},
"pointer": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
}
},
"type": "object",
"variants": []
},
"meal_plan": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"cook_time": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"cooking_steps": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "array",
"default": null,
"example": null,
"max": null,
"min": null,
"of": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "cooking_step"
},
"shape": {}
},
"created_at": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "datetime",
"default": null,
"example": null
},
"id": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"serving_size": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"title": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"updated_at": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "datetime",
"default": null,
"example": null
}
},
"type": "object",
"variants": []
},
"meal_plan_create_payload": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"cook_time": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 2147483647,
"min": -2147483648
},
"cooking_steps": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "array",
"default": null,
"example": null,
"max": null,
"min": null,
"of": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "cooking_step_nested_payload"
},
"shape": {}
},
"serving_size": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 2147483647,
"min": -2147483648
},
"title": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
}
},
"type": "object",
"variants": []
},
"meal_plan_page": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"number": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": 1
},
"size": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 100,
"min": 1
}
},
"type": "object",
"variants": []
},
"meal_plan_update_payload": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"cook_time": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 2147483647,
"min": -2147483648
},
"cooking_steps": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "array",
"default": null,
"example": null,
"max": null,
"min": null,
"of": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "reference",
"reference": "cooking_step_nested_payload"
},
"shape": {}
},
"serving_size": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": 2147483647,
"min": -2147483648
},
"title": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": true,
"type": "string",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
}
},
"type": "object",
"variants": []
},
"offset_pagination": {
"deprecated": false,
"description": null,
"discriminator": null,
"example": null,
"extends": [],
"shape": {
"current": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"items": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"next": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"prev": {
"deprecated": false,
"description": null,
"nullable": true,
"optional": true,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
},
"total": {
"deprecated": false,
"description": null,
"nullable": false,
"optional": false,
"type": "integer",
"default": null,
"example": null,
"format": null,
"max": null,
"min": null
}
},
"type": "object",
"variants": []
}
}
}TypeScript
ts
export interface CookingStep {
DurationMinutes: null | number;
Id: string;
Instruction: string;
StepNumber: number;
}
export interface CookingStepNestedCreatePayload {
OP: 'create';
DurationMinutes: null | number;
Instruction: string;
StepNumber: number;
}
export interface CookingStepNestedDeletePayload {
OP: 'delete';
Id: string;
}
export type CookingStepNestedPayload = CookingStepNestedCreatePayload | CookingStepNestedUpdatePayload | CookingStepNestedDeletePayload;
export interface CookingStepNestedUpdatePayload {
OP: 'update';
DurationMinutes: null | number;
Id?: string;
Instruction?: string;
StepNumber?: number;
}
export interface Error {
Issues: ErrorIssue[];
Layer: ErrorLayer;
}
export interface ErrorIssue {
Code: string;
Detail: string;
Meta: Record<string, unknown>;
Path: (number | string)[];
Pointer: string;
}
export type ErrorLayer = 'contract' | 'domain' | 'http';
export interface MealPlan {
CookTime: null | number;
CookingSteps: CookingStep[];
CreatedAt: string;
Id: string;
ServingSize: null | number;
Title: string;
UpdatedAt: string;
}
export interface MealPlanCreatePayload {
CookTime: null | number;
CookingSteps?: CookingStepNestedPayload[];
ServingSize: null | number;
Title: string;
}
export interface MealPlanPage {
Number?: number;
Size?: number;
}
export interface MealPlanUpdatePayload {
CookTime: null | number;
CookingSteps?: CookingStepNestedPayload[];
ServingSize: null | number;
Title?: string;
}
export interface MealPlansCreateRequest {
body: MealPlansCreateRequestBody;
}
export interface MealPlansCreateRequestBody {
MealPlan: MealPlanCreatePayload;
}
export type MealPlansCreateResponse =
| { status: 200; body: MealPlansCreateResponseBody }
| { status: 422; body: Error };
export type MealPlansCreateResponseBody = { MealPlan: MealPlan; Meta?: Record<string, unknown> };
export type MealPlansDestroyResponse = { status: 204 };
export interface MealPlansIndexRequest {
query: MealPlansIndexRequestQuery;
}
export interface MealPlansIndexRequestQuery {
Page?: MealPlanPage;
}
export type MealPlansIndexResponse = { status: 200; body: MealPlansIndexResponseBody };
export type MealPlansIndexResponseBody = { MealPlans: MealPlan[]; Meta?: Record<string, unknown>; Pagination: OffsetPagination };
export type MealPlansShowResponse = { status: 200; body: MealPlansShowResponseBody };
export type MealPlansShowResponseBody = { MealPlan: MealPlan; Meta?: Record<string, unknown> };
export interface MealPlansUpdateRequest {
body: MealPlansUpdateRequestBody;
}
export interface MealPlansUpdateRequestBody {
MealPlan: MealPlanUpdatePayload;
}
export type MealPlansUpdateResponse =
| { status: 200; body: MealPlansUpdateResponseBody }
| { status: 422; body: Error };
export type MealPlansUpdateResponseBody = { MealPlan: MealPlan; Meta?: Record<string, unknown> };
export interface OffsetPagination {
Current: number;
Items: number;
Next: null | number;
Prev: null | number;
Total: number;
}Zod
ts
import { z } from 'zod';
export const ErrorLayerSchema = z.enum(['contract', 'domain', 'http']);
export const CookingStepSchema = z.object({
DurationMinutes: z.number().int().nullable(),
Id: z.string(),
Instruction: z.string(),
StepNumber: z.number().int()
});
export const CookingStepNestedCreatePayloadSchema = z.object({
OP: z.literal('create'),
DurationMinutes: z.number().int().min(-2147483648).max(2147483647).nullable().default(null),
Instruction: z.string(),
StepNumber: z.number().int().min(-2147483648).max(2147483647)
});
export const CookingStepNestedDeletePayloadSchema = z.object({
OP: z.literal('delete'),
Id: z.string()
});
export const CookingStepNestedUpdatePayloadSchema = z.object({
OP: z.literal('update'),
DurationMinutes: z.number().int().min(-2147483648).max(2147483647).nullable().default(null),
Id: z.string().optional(),
Instruction: z.string().optional(),
StepNumber: z.number().int().min(-2147483648).max(2147483647).optional()
});
export const ErrorIssueSchema = z.object({
Code: z.string(),
Detail: z.string(),
Meta: z.record(z.string(), z.unknown()),
Path: z.array(z.union([z.string(), z.number().int()])),
Pointer: z.string()
});
export const MealPlanPageSchema = z.object({
Number: z.number().int().min(1).optional(),
Size: z.number().int().min(1).max(100).optional()
});
export const OffsetPaginationSchema = z.object({
Current: z.number().int(),
Items: z.number().int(),
Next: z.number().int().nullable().default(null),
Prev: z.number().int().nullable().default(null),
Total: z.number().int()
});
export const CookingStepNestedPayloadSchema = z.discriminatedUnion('OP', [
CookingStepNestedCreatePayloadSchema,
CookingStepNestedUpdatePayloadSchema,
CookingStepNestedDeletePayloadSchema
]);
export const ErrorSchema = z.object({
Issues: z.array(ErrorIssueSchema),
Layer: ErrorLayerSchema
});
export const MealPlanSchema = z.object({
CookTime: z.number().int().nullable(),
CookingSteps: z.array(CookingStepSchema),
CreatedAt: z.iso.datetime(),
Id: z.string(),
ServingSize: z.number().int().nullable(),
Title: z.string(),
UpdatedAt: z.iso.datetime()
});
export const MealPlanCreatePayloadSchema = z.object({
CookTime: z.number().int().min(-2147483648).max(2147483647).nullable().default(null),
CookingSteps: z.array(CookingStepNestedPayloadSchema).optional(),
ServingSize: z.number().int().min(-2147483648).max(2147483647).nullable().default(null),
Title: z.string()
});
export const MealPlanUpdatePayloadSchema = z.object({
CookTime: z.number().int().min(-2147483648).max(2147483647).nullable().default(null),
CookingSteps: z.array(CookingStepNestedPayloadSchema).optional(),
ServingSize: z.number().int().min(-2147483648).max(2147483647).nullable().default(null),
Title: z.string().optional()
});
export const MealPlansIndexRequestQuerySchema = z.object({
Page: MealPlanPageSchema.optional()
});
export const MealPlansIndexRequestSchema = z.object({
query: MealPlansIndexRequestQuerySchema
});
export const MealPlansIndexResponseBodySchema = z.object({ MealPlans: z.array(MealPlanSchema), Meta: z.record(z.string(), z.unknown()).optional(), Pagination: OffsetPaginationSchema });
export const MealPlansShowResponseBodySchema = z.object({ MealPlan: MealPlanSchema, Meta: z.record(z.string(), z.unknown()).optional() });
export const MealPlansCreateRequestBodySchema = z.object({
MealPlan: MealPlanCreatePayloadSchema
});
export const MealPlansCreateRequestSchema = z.object({
body: MealPlansCreateRequestBodySchema
});
export const MealPlansCreateResponseBodySchema = z.object({ MealPlan: MealPlanSchema, Meta: z.record(z.string(), z.unknown()).optional() });
export const MealPlansUpdateRequestBodySchema = z.object({
MealPlan: MealPlanUpdatePayloadSchema
});
export const MealPlansUpdateRequestSchema = z.object({
body: MealPlansUpdateRequestBodySchema
});
export const MealPlansUpdateResponseBodySchema = z.object({ MealPlan: MealPlanSchema, Meta: z.record(z.string(), z.unknown()).optional() });
export const MealPlansIndexResponseSchema = z.object({ status: z.literal(200), body: MealPlansIndexResponseBodySchema });
export const MealPlansShowResponseSchema = z.object({ status: z.literal(200), body: MealPlansShowResponseBodySchema });
export const MealPlansCreateResponseSchema = z.discriminatedUnion('status', [
z.object({ status: z.literal(200), body: MealPlansCreateResponseBodySchema }),
z.object({ status: z.literal(422), body: ErrorSchema })
]);
export const MealPlansUpdateResponseSchema = z.discriminatedUnion('status', [
z.object({ status: z.literal(200), body: MealPlansUpdateResponseBodySchema }),
z.object({ status: z.literal(422), body: ErrorSchema })
]);
export const MealPlansDestroyResponseSchema = z.object({ status: z.literal(204) });
export interface CookingStep {
DurationMinutes: null | number;
Id: string;
Instruction: string;
StepNumber: number;
}
export interface CookingStepNestedCreatePayload {
OP: 'create';
DurationMinutes: null | number;
Instruction: string;
StepNumber: number;
}
export interface CookingStepNestedDeletePayload {
OP: 'delete';
Id: string;
}
export type CookingStepNestedPayload = CookingStepNestedCreatePayload | CookingStepNestedUpdatePayload | CookingStepNestedDeletePayload;
export interface CookingStepNestedUpdatePayload {
OP: 'update';
DurationMinutes: null | number;
Id?: string;
Instruction?: string;
StepNumber?: number;
}
export interface Error {
Issues: ErrorIssue[];
Layer: ErrorLayer;
}
export interface ErrorIssue {
Code: string;
Detail: string;
Meta: Record<string, unknown>;
Path: (number | string)[];
Pointer: string;
}
export type ErrorLayer = 'contract' | 'domain' | 'http';
export interface MealPlan {
CookTime: null | number;
CookingSteps: CookingStep[];
CreatedAt: string;
Id: string;
ServingSize: null | number;
Title: string;
UpdatedAt: string;
}
export interface MealPlanCreatePayload {
CookTime: null | number;
CookingSteps?: CookingStepNestedPayload[];
ServingSize: null | number;
Title: string;
}
export interface MealPlanPage {
Number?: number;
Size?: number;
}
export interface MealPlanUpdatePayload {
CookTime: null | number;
CookingSteps?: CookingStepNestedPayload[];
ServingSize: null | number;
Title?: string;
}
export interface MealPlansCreateRequest {
body: MealPlansCreateRequestBody;
}
export interface MealPlansCreateRequestBody {
MealPlan: MealPlanCreatePayload;
}
export type MealPlansCreateResponse =
| { status: 200; body: MealPlansCreateResponseBody }
| { status: 422; body: Error };
export type MealPlansCreateResponseBody = { MealPlan: MealPlan; Meta?: Record<string, unknown> };
export type MealPlansDestroyResponse = { status: 204 };
export interface MealPlansIndexRequest {
query: MealPlansIndexRequestQuery;
}
export interface MealPlansIndexRequestQuery {
Page?: MealPlanPage;
}
export type MealPlansIndexResponse = { status: 200; body: MealPlansIndexResponseBody };
export type MealPlansIndexResponseBody = { MealPlans: MealPlan[]; Meta?: Record<string, unknown>; Pagination: OffsetPagination };
export type MealPlansShowResponse = { status: 200; body: MealPlansShowResponseBody };
export type MealPlansShowResponseBody = { MealPlan: MealPlan; Meta?: Record<string, unknown> };
export interface MealPlansUpdateRequest {
body: MealPlansUpdateRequestBody;
}
export interface MealPlansUpdateRequestBody {
MealPlan: MealPlanUpdatePayload;
}
export type MealPlansUpdateResponse =
| { status: 200; body: MealPlansUpdateResponseBody }
| { status: 422; body: Error };
export type MealPlansUpdateResponseBody = { MealPlan: MealPlan; Meta?: Record<string, unknown> };
export interface OffsetPagination {
Current: number;
Items: number;
Next: null | number;
Prev: null | number;
Total: number;
}OpenAPI
yml
---
openapi: 3.1.0
info:
title: "/nimble_gecko"
version: 1.0.0
paths:
"/meal-plans":
get:
operationId: MealPlansIndex
parameters:
- in: query
name: Page
required: false
schema:
"$ref": "#/components/schemas/MealPlanPage"
responses:
'200':
content:
application/json:
schema:
properties:
MealPlans:
items:
"$ref": "#/components/schemas/MealPlan"
type: array
Meta:
properties: {}
type: object
Pagination:
"$ref": "#/components/schemas/OffsetPagination"
type: object
required:
- MealPlans
- Pagination
description: ''
post:
operationId: MealPlansCreate
requestBody:
content:
application/json:
schema:
properties:
MealPlan:
"$ref": "#/components/schemas/MealPlanCreatePayload"
type: object
required:
- MealPlan
required: true
responses:
'200':
content:
application/json:
schema:
properties:
MealPlan:
"$ref": "#/components/schemas/MealPlan"
Meta:
properties: {}
type: object
type: object
required:
- MealPlan
description: ''
'422':
description: Unprocessable Entity
content:
application/json:
schema:
properties:
issues:
items:
"$ref": "#/components/schemas/Error"
type: array
required:
- issues
type: object
"/meal-plans/{Id}":
get:
operationId: MealPlansShow
parameters:
- in: path
name: Id
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
properties:
MealPlan:
"$ref": "#/components/schemas/MealPlan"
Meta:
properties: {}
type: object
type: object
required:
- MealPlan
description: ''
patch:
operationId: MealPlansUpdate
parameters:
- in: path
name: Id
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
properties:
MealPlan:
"$ref": "#/components/schemas/MealPlanUpdatePayload"
type: object
required:
- MealPlan
required: true
responses:
'200':
content:
application/json:
schema:
properties:
MealPlan:
"$ref": "#/components/schemas/MealPlan"
Meta:
properties: {}
type: object
type: object
required:
- MealPlan
description: ''
'422':
description: Unprocessable Entity
content:
application/json:
schema:
properties:
issues:
items:
"$ref": "#/components/schemas/Error"
type: array
required:
- issues
type: object
delete:
operationId: MealPlansDestroy
parameters:
- in: path
name: Id
required: true
schema:
type: string
responses:
'204':
description: ''
components:
schemas:
CookingStep:
properties:
DurationMinutes:
type:
- integer
- 'null'
Id:
type: string
Instruction:
type: string
StepNumber:
type: integer
type: object
required:
- DurationMinutes
- Id
- Instruction
- StepNumber
CookingStepNestedCreatePayload:
properties:
OP:
const: create
type: string
DurationMinutes:
type:
- integer
- 'null'
minimum: -2147483648
maximum: 2147483647
default:
Instruction:
type: string
StepNumber:
type: integer
minimum: -2147483648
maximum: 2147483647
type: object
required:
- OP
- Instruction
- StepNumber
CookingStepNestedDeletePayload:
properties:
OP:
const: delete
type: string
Id:
type: string
type: object
required:
- OP
- Id
CookingStepNestedPayload:
oneOf:
- "$ref": "#/components/schemas/CookingStepNestedCreatePayload"
- "$ref": "#/components/schemas/CookingStepNestedUpdatePayload"
- "$ref": "#/components/schemas/CookingStepNestedDeletePayload"
discriminator:
mapping:
Create: "#/components/schemas/CookingStepNestedCreatePayload"
Update: "#/components/schemas/CookingStepNestedUpdatePayload"
Delete: "#/components/schemas/CookingStepNestedDeletePayload"
propertyName: OP
CookingStepNestedUpdatePayload:
properties:
OP:
const: update
type: string
DurationMinutes:
type:
- integer
- 'null'
minimum: -2147483648
maximum: 2147483647
default:
Id:
type: string
Instruction:
type: string
StepNumber:
type: integer
minimum: -2147483648
maximum: 2147483647
type: object
required:
- OP
Error:
properties:
Issues:
items:
"$ref": "#/components/schemas/ErrorIssue"
type: array
Layer:
enum:
- http
- contract
- domain
type: string
type: object
required:
- Issues
- Layer
ErrorIssue:
properties:
Code:
type: string
Detail:
type: string
Meta:
properties: {}
type: object
Path:
items:
oneOf:
- type: string
- type: integer
type: array
Pointer:
type: string
type: object
required:
- Code
- Detail
- Meta
- Path
- Pointer
MealPlan:
properties:
CookTime:
type:
- integer
- 'null'
CookingSteps:
items:
"$ref": "#/components/schemas/CookingStep"
type: array
CreatedAt:
type: string
format: date-time
Id:
type: string
ServingSize:
type:
- integer
- 'null'
Title:
type: string
UpdatedAt:
type: string
format: date-time
type: object
required:
- CookTime
- CookingSteps
- CreatedAt
- Id
- ServingSize
- Title
- UpdatedAt
MealPlanCreatePayload:
properties:
CookTime:
type:
- integer
- 'null'
minimum: -2147483648
maximum: 2147483647
default:
CookingSteps:
items:
"$ref": "#/components/schemas/CookingStepNestedPayload"
type: array
ServingSize:
type:
- integer
- 'null'
minimum: -2147483648
maximum: 2147483647
default:
Title:
type: string
type: object
required:
- Title
MealPlanPage:
properties:
Number:
type: integer
minimum: 1
Size:
type: integer
minimum: 1
maximum: 100
type: object
MealPlanUpdatePayload:
properties:
CookTime:
type:
- integer
- 'null'
minimum: -2147483648
maximum: 2147483647
default:
CookingSteps:
items:
"$ref": "#/components/schemas/CookingStepNestedPayload"
type: array
ServingSize:
type:
- integer
- 'null'
minimum: -2147483648
maximum: 2147483647
default:
Title:
type: string
type: object
OffsetPagination:
properties:
Current:
type: integer
Items:
type: integer
Next:
type:
- integer
- 'null'
default:
Prev:
type:
- integer
- 'null'
default:
Total:
type: integer
type: object
required:
- Current
- Items
- Total