AshOaskit.ResourceIdentifier (AshOasKit v0.2.0)

View Source

Generates JSON:API resource identifier schemas for OpenAPI specifications.

This module provides functions to build resource identifier objects, which are used in relationship linkage data. Resource identifiers contain just the type and id of a resource, optionally with meta.

Resource Identifier Structure

A resource identifier object contains:

  • type - The type of the resource (required)
  • id - The unique identifier of the resource (required)
  • meta - Optional non-standard meta information
{
  "type": "posts",
  "id": "1",
  "meta": {
    "created_at": "2024-01-01T00:00:00Z"
  }
}

Relationship Linkage

Resource identifiers are used in relationship data:

To-One Relationship

{
  "data": {"type": "author", "id": "1"}
}

To-Many Relationship

{
  "data": [
    {"type": "comment", "id": "1"},
    {"type": "comment", "id": "2"}
  ]
}

OpenAPI Version Differences

  • OpenAPI 3.1: Uses type: ["object", "null"] for nullable to-one
  • OpenAPI 3.0: Uses nullable: true for nullable to-one

Usage

# Build a resource identifier schema
AshOaskit.ResourceIdentifier.build_identifier_schema("posts")

# Build a nullable identifier (for optional to-one relationships)
AshOaskit.ResourceIdentifier.build_nullable_identifier_schema("author", version: "3.1")

# Build linkage for to-many relationship
AshOaskit.ResourceIdentifier.build_to_many_linkage_schema("comments")

Summary

Functions

Builds generic resource identifier schemas.

Builds component schemas for resource identifiers.

Builds a resource identifier object schema.

Builds resource linkage data schema for relationship requests.

Builds a nullable resource identifier schema for optional to-one relationships.

Builds a polymorphic identifier schema for relationships that can reference multiple resource types.

Builds a complete relationship object schema with data and links.

Builds a relationships object schema containing multiple relationships.

Builds a to-many relationship linkage schema.

Builds a to-one relationship linkage schema.

Functions

build_generic_identifier_schema(_ \\ [])

@spec build_generic_identifier_schema(keyword()) :: map()

Builds generic resource identifier schemas.

These can be used when the specific resource type isn't known or for polymorphic relationships.

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".

Examples

iex> AshOaskit.ResourceIdentifier.build_generic_identifier_schema()
%{
  type: :object,
  required: ["type", "id"],
  properties: %{
    type: %{type: :string},
    id: %{type: :string},
    meta: %{...}
  }
}

build_identifier_component_schemas(resource_name, opts \\ [])

@spec build_identifier_component_schemas(
  String.t(),
  keyword()
) :: map()

Builds component schemas for resource identifiers.

Generates reusable schema definitions for the components section.

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".
  • :name_prefix - Prefix for schema names. Defaults to "".

Examples

iex> AshOaskit.ResourceIdentifier.build_identifier_component_schemas("Post")
%{
  "PostIdentifier" => %{...},
  "PostRelationshipLinks" => %{...}
}

build_identifier_schema(resource_type, opts \\ [])

@spec build_identifier_schema(
  String.t(),
  keyword()
) :: map()

Builds a resource identifier object schema.

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".
  • :include_meta - Whether to include optional meta field. Defaults to true.

Examples

iex> AshOaskit.ResourceIdentifier.build_identifier_schema("posts")
%{
  type: :object,
  required: ["type", "id"],
  properties: %{
    type: %{type: :string, enum: ["posts"]},
    id: %{type: :string},
    meta: %{type: :object, additionalProperties: true}
  }
}

build_linkage_data_schema(resource_type, opts \\ [])

@spec build_linkage_data_schema(
  String.t(),
  keyword()
) :: map()

Builds resource linkage data schema for relationship requests.

This is used in request bodies when modifying relationships.

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".
  • :cardinality - :to_one or :to_many. Determines single vs array.

Examples

iex> schema =
...>   AshOaskit.ResourceIdentifier.build_linkage_data_schema("comments",
...>     cardinality: :to_many
...>   )
...>
...> schema[:type]
:object
iex> "data" in schema[:required]
true

build_nullable_identifier_schema(resource_type, opts \\ [])

@spec build_nullable_identifier_schema(
  String.t(),
  keyword()
) :: map()

Builds a nullable resource identifier schema for optional to-one relationships.

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".
  • :include_meta - Whether to include optional meta field. Defaults to true.

Examples

iex> schema =
...>   AshOaskit.ResourceIdentifier.build_nullable_identifier_schema("author", version: "3.1")
...>
...> Map.has_key?(schema, :oneOf)
true
iex> length(schema[:oneOf])
2

build_polymorphic_identifier_schema(resource_types, _ \\ [])

@spec build_polymorphic_identifier_schema(
  [String.t()],
  keyword()
) :: map()

Builds a polymorphic identifier schema for relationships that can reference multiple resource types.

Examples

iex> AshOaskit.ResourceIdentifier.build_polymorphic_identifier_schema(["posts", "comments"])
%{
  type: :object,
  required: ["type", "id"],
  properties: %{
    type: %{type: :string, enum: ["posts", "comments"]},
    id: %{type: :string}
  }
}

build_relationship_object_schema(resource_type, opts \\ [])

@spec build_relationship_object_schema(
  String.t(),
  keyword()
) :: map()

Builds a complete relationship object schema with data and links.

The relationship object contains:

  • data - Resource linkage (to-one or to-many)
  • links - Relationship links (self, related)
  • meta - Optional relationship meta

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".
  • :cardinality - :to_one or :to_many. Defaults to :to_one.
  • :include_links - Whether to include links. Defaults to true.
  • :include_meta - Whether to include meta. Defaults to true.

Examples

AshOaskit.ResourceIdentifier.build_relationship_object_schema("author",
  cardinality: :to_one
)
# => %{
#      type: :object,
#      properties: %{
#        data: %{...to_one_linkage...},
#        links: %{...relationship_links...},
#        meta: %{...meta...}
#      }
#    }

build_relationships_object_schema(relationships, opts \\ [])

@spec build_relationships_object_schema(
  [{String.t(), atom()}],
  keyword()
) :: map()

Builds a relationships object schema containing multiple relationships.

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".

Examples

relationships = [
  {"author", :to_one},
  {"comments", :to_many}
]

AshOaskit.ResourceIdentifier.build_relationships_object_schema(relationships)
# => %{
#      type: :object,
#      properties: %{
#        "author" => %{...to_one_relationship...},
#        "comments" => %{...to_many_relationship...}
#      }
#    }

build_to_many_linkage_schema(resource_type, opts \\ [])

@spec build_to_many_linkage_schema(
  String.t(),
  keyword()
) :: map()

Builds a to-many relationship linkage schema.

To-many relationships are represented as arrays of resource identifiers.

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".
  • :include_meta - Whether to include meta in identifiers. Defaults to true.

Examples

AshOaskit.ResourceIdentifier.build_to_many_linkage_schema("comments")
# => %{
#      type: :array,
#      items: %{...resource_identifier...}
#    }

build_to_one_linkage_schema(resource_type, opts \\ [])

@spec build_to_one_linkage_schema(
  String.t(),
  keyword()
) :: map()

Builds a to-one relationship linkage schema.

To-one relationships can be null (when the relationship doesn't exist) or a single resource identifier.

Options

  • :version - OpenAPI version ("3.1" or "3.0"). Defaults to "3.1".
  • :required - Whether the relationship is required. Defaults to false.
  • :include_meta - Whether to include meta in identifiers. Defaults to true.

Examples

AshOaskit.ResourceIdentifier.build_to_one_linkage_schema("author")
# => %{
#      oneOf: [
#        %{type: :null},
#        %{...resource_identifier...}
#      ]
#    }