Giter Club home page Giter Club logo

contentful.ex's Introduction

Contentful Elixir SDK

Elixir SDK for the Contentful Content APIs.

Elixir CI Coverage Status Hex.pm License

Contentful provides a content infrastructure for digital teams to power content in websites, apps, and devices. Unlike a CMS, Contentful was built to integrate with the modern software stack. It offers a central hub for structured content, powerful management and delivery APIs, and a customizable web app that enable developers and content creators to ship digital products faster.

API Overview

Contentful Delivery API (CDA)

The official docs can be found here: https://www.contentful.com/developers/docs/references/content-delivery-api/.

The API provides the content for Contenful apps. It's read only and the recommended way to deliver large amounts of content.

Contentful Management API (CMA)

The official docs can be found here: https://www.contentful.com/developers/docs/references/content-management-api/.

The API provides the capability to manage content you have stored with Contentful.

Contentful Preview API (CPA)

The official docs can be found here: https://www.contentful.com/developers/docs/references/content-preview-api/.

The Preview API can be used to access the latest versions and drafts of your content. It maintains compatibility with the Contentful Delivery API.

Installation

  1. Add contentful to your list of dependencies in mix.exs:
  def deps do
    [{:contentful, "~> 0.4.0"}]
  end
  1. Ensure contentful is started before your application:
  def application do
    [applications: [:contentful]]
  end

Usage

For the usage, see the documentation published to hex.

Local documentation

In case you want to compile the docs locally, run:

$ mix docs

# to view, we recommend:
$ cd doc && python -m SimpleHTTPServer # or any other quick way to serve static content locally

then open http://localhost:8000.

Contributing & Development

  1. Fork the repository
  2. Create your feature branch on your fork (git checkout -b my-new-feature)
  3. Make your changes
  4. Run tests (mix test) and static analysis (mix credo --strict)
  5. Commit your changes (git commit -am 'Add some feature')
  6. Push to your branch (git push origin my-new-feature)
  7. Create a Pull Request on this original repository

Notes on setup

This library makes use of the Contentful APIs. It helps to have an account and to setup a secrets file for testing:

$ cat config/secrets.dev.exs
config :contentful, delivery: [
  access_token: "<my_cda_access_token>",
  environment: "master",
  space_id: "<my_space_id>"
]

# for testing
$ cat config/secrets.test.exs
config :contentful, delivery: [
  access_token: "<my_cda_access_token>",
  environment: "testing",
  space_id: "<my_space_id>"
]

We freeze requests by using exVCR, in case you want to rebuild these files, make sure that test assertions match.

contentful.ex's People

Contributors

andrew-bednarz-isobar avatar asaaki avatar aspala avatar cf-userland-allstar[bot] avatar dependabot-preview[bot] avatar dependabot[bot] avatar dlitvakb avatar floriank avatar nicocharlery avatar oldhammade avatar willrochathomas avatar zberkom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

contentful.ex's Issues

Fix typespecs

I added dialyxir in kind of a rush to get typespecs in and then added typespecs all over the place, without paying too much attention to what dialyzer actually complains about.

  • Correct existing typespecs that seems to break
  • Address the findings of dialyzer (run mix dialyxir --format elixir

Upgrade code coverage

  • Push code coverage by tests higher, ideally to something like 85% or above
  • Bonus points for excoveralls integration and displaying the percentage somewhere - has been done in the context of of #27

Impossible to build more complex queries?

Unless I'm missing something, it doesn't appear to be possible to query Entries with things like the equality operator (https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/equality-operator).

I have an existing query using the 0.1.1 version of this gem that I'm trying to port to 0.3.0. It appears that https://github.com/contentful-labs/contentful.ex/blob/bbf75f30fe371cceffaa00e75c31d780f94425dc/lib/contentful_delivery/delivery.ex#L277 will filter out anything else I try to add to the request.

RichText to HTML API

This is a bit of a stretch, but I'm wondering if there have been thoughts of RichText to HTML API? I'd like to avoid storing the JSON format and converting on the client.

One option is to utilize the Node.js library with a shell call, but keeping it native would be amazing.

I'm not opposed to building a native Elixir implementation, as it doesn't look like an excessively difficult format to work with. I just wanted to check to see if this has been thought about at all!

Handle Pagination & Errors Properly

I just implemented this library on a project and ran into a couple issues.

  1. Contentful.Delivery.entries expects ["items"] always to be present in the returned response.
    • If you pass an incorrect access_token or space_id the contentful throws a 401 & 404 respectively. Both of which are not handled and the function throws a KeyError exception.
  2. Contentful.Delivery.entries only does not return the total & skip keys returned by the contentful API, which makes it impossible to do pagination properly.

I'm planning to submit a PR to address both of these issues, if it's something you'd be interested in.

Quicklinks to registry and documentation

Just leaving this quick feature request here (cannot do it myself right now):
Let's add the following links to the README (and package also to the header section, next to description line):

Why should we do this? We already provide links to Contentful's API documentation, but don't give GitHub users quick(er) access to the hex package and documentation pages.

#goodFirstContribution

Links of links don't resolve properly

I have a blog post -> author -> image relationship. When requesting the blog post, both the author and images show up in the includes field in the resposne, but the resolve logic in this library doesn't flatten it out properly, and then image source is lost.

VCR'd Fixture: https://gist.github.com/stavro/fb38c303017549feb07e51f4b7665eb0

Expected: Be able to access the author's image.

Actual: Image is not available after this library parses the response. It is in the response though.

FunctionClauseError: no function clause matching in Contentful.Delivery.Assets.resolve_entity_response/1

The production endpoint seems to be returning a map with the following attributes:

%{
  "fields" => %{
    "file" => %{
      "contentType" => "image/png",
      "details" => %{
        "image" => %{"height" => 2000, "width" => 3000},
        "size" => 7423579
      },
      "fileName" => "foo-bar.png",
      "url" => "//images.ctfassets.net/.../.../.../foo-bar.png"
    },
    "title" => "foo-bar"
  },
  "sys" => %{
    "createdAt" => "2020-01-08T11:44:33.417Z",
    "environment" => %{
      "sys" => %{
        "id" => "master",
        "linkType" => "Environment",
        "type" => "Link"
      }
    },
    "id" => "...",
    "locale" => "en-GB",
    "revision" => 1,
    "space" => %{
      "sys" => %{
        "id" => "...",
        "linkType" => "Space",
        "type" => "Link"
      }
    },
    "type" => "Asset",
    "updatedAt" => "2020-01-08T11:44:33.417Z"
  }
}

But the function expects a minimum of:

%{
  "fields" => %{
    "description" => desc,
    "file" => %{
      "contentType" => content_type,
      "details" => details,
      "fileName" => file_name,
      "url" => url
    },
    "title" => title
  },
  "sys" => %{"id" => id, "revision" => rev}
}

It seems the production endpoint isn't returning a description for the Assets, which causes this function to break. Removing the "description" => desc, line resolves the issue.

Production use

How safe is that library for a production use ?
Are there features that are not covered by other SDK, say ruby or JS, that are not handled by the Elixir client ?

Add dependabot for great success

We have used it on other projects internally at contentful, so we might want to add it here as well to keep dependencies up to date.

Entries not loading relations

Hey Devs,

I have a Blogpost that contains one or more Authors. If I do:
Contentful.Delivery.entries(@space_id, @access_token)

I will get the content with the relations, but with nil:
%{"fields" => %{"author" => [nil, nil], "title" => "The article"

Even if I add the %{"include" => 2} as the search parameter, I will still get a nil. Is there another way to load the relations or am I doing it wrong?

Include and Filters no longer work

I received a tweet to the release of v0.2.0 from @hukl that rightfully askes for the filter and include options originally present in v0.1.1:

# v0.0.1
entries = Contentful.Delivery.entries(space_id, access_token, %{
    "content_type" => "categoryList",
    "include" => 2
})

# v0.2.0
entries = Contentful.Delivery.Entries.fetch_all([], space, "master", access_token)

I carelessly dropped this feature and it needs to be readded in a compatible fashion.

This just does not work on windows

I created the simplest possible get request and it fails.
@space_id MYSPACEID
@access_token MYACCESSTOKEN
entries = Contentful.Delivery.entries(@space_id, @access_token)

# Printing Content Type ID for every entry
Enum.each(entries, fn (entry) -> IO.puts(entry["sys"]["contentType"]["sys"]["id"]) end)

This is a known issue with the Hackney library used by HTTPoison.
I would recommend moving to HTTPotion (which is more portable) or simplehttp.

I am looking at building a simplehttp version.

Here is the stacktrace that was generated:

17:39:20.455 [debug] GET /spaces/MYSPACEID/entries
** (exit) exited in: :gen_fsm.sync_send_all_state_event(#PID<0.157.0>, {:start, 8000}, :infinity)
** (EXIT) an exception was raised:
** (ErlangError) Erlang error: :notsup
(crypto) crypto.erl:317: :crypto.block_encrypt/4
(ssl) ssl_cipher.erl:160: :ssl_cipher.aead_cipher/6
(ssl) ssl_record.erl:396: :ssl_record.cipher_aead/4
(ssl) tls_record.erl:143: :tls_record.encode_plain_text/4
(ssl) tls_connection.erl:357: :tls_connection.encode_handshake/4
(ssl) tls_connection.erl:109: :tls_connection.send_handshake/2
(ssl) ssl_connection.erl:1118: :ssl_connection.client_certify_and_key_exchange/2
(ssl) tls_connection.erl:466: :tls_connection.next_state/4
(stdlib) gen_fsm.erl:257: :gen_fsm.sync_send_all_state_event/3
(ssl) ssl_connection.erl:1656: :ssl_connection.sync_send_all_state_event/2
(ssl) ssl_connection.erl:103: :ssl_connection.handshake/2
(ssl) tls_connection.erl:82: :tls_connection.start_fsm/8
(ssl) ssl_connection.erl:73: :ssl_connection.connect/8
(hackney) d:/dev/Contentful/Tools/contentful_to_neo4j_ex/deps/hackney/src/hackney_connect.erl:247: :hackney_connect.do_connect/5
(hackney) d:/dev/Contentful/Tools/contentful_to_neo4j_ex/deps/hackney/src/hackney_connect.erl:37: :hackney_connect.connect/5
(hackney) d:/dev/Contentful/Tools/contentful_to_neo4j_ex/deps/hackney/src/hackney.erl:316: :hackney.request/5
iex(2)>
17:39:21.164 [error] ** State machine #PID<0.157.0> terminating
** Last message in was {:tcp, #Port<0.6653>,
<<247, 13, 1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 162, 29, 105, 138, 10, 142, 196,
20, 131, 42, 42, 18, 77, 57, 39, 144, 78, 240, 141, 172, 210, 150, 98, 71,
54, 94, 146, 209, 250, 197, 147, 181, 55, 7, 101, 41, ...>>}
** When State == :certify
** Data == [data: [{'StateData',
{:state, :client, {#Reference<0.0.4.1153>, #PID<0.147.0>}, :gen_tcp,
:tls_connection, :tcp, :tcp_closed, :tcp_error, 'cdn.contentful.com', 443,
#Port<0.6653>,
{:ssl_options, :tls, [{3, 3}, {3, 2}, {3, 1}, {3, 0}], :verify_peer,
{&:ssl_verify_hostname.verify_fun/3,
[check_hostname: 'cdn.contentful.com']},
#Function<0.104464233/1 in :hackney_connect.ssl_opts_1/2>, false, false,
:undefined, 99, "", '', "", '', '', '', "", '', :undefined,
:undefined, '
', '',
[<<192, 44>>, <<192, 48>>, <<192, 36>>, <<192, 40>>, <<192, 8>>,
<<192, 46>>, <<192, 50>>, <<192, 38>>, <<192, 42>>, <<0, 163>>,
<<0, 106>>, <<0, 157>>, <<0, ...>>, <<...>>, ...],
#Function<2.27451488/4 in :ssl.handle_options/1>, true, 268435456, true,
true, :undefined, false, :undefined, :undefined, :undefined, :undefined,
true, :undefined, [], ...}, {:socket_options, :binary, :raw, 0, 0, false},
'
', '', '', 36886, '', 57369, :ssl_session_cache,
{:ssl_crl_cache, {{49173, 53268}, []}}, {3, 3}, false, :ecdhe_rsa,
{:undefined, :undefined}, :undefined, :undefined, '
', '', '',
:undefined, '', '', '', 40983, #Reference<0.0.4.1156>, :undefined,
'
', {false, :first}, {#PID<0.147.0>, #Reference<0.0.4.1154>},
#Reference<0.0.4.1158>, {[], []}, false, true, false, false, :undefined,
:undefined, :undefined, ...}}]]
** Reason for termination =
** {:notsup,
[{:crypto, :block_encrypt, 4, [file: 'crypto.erl', line: 317]},
{:ssl_cipher, :aead_cipher, 6, [file: 'ssl_cipher.erl', line: 160]},
{:ssl_record, :cipher_aead, 4, [file: 'ssl_record.erl', line: 396]},
{:tls_record, :encode_plain_text, 4, [file: 'tls_record.erl', line: 143]},
{:tls_connection, :encode_handshake, 4,
[file: 'tls_connection.erl', line: 357]},
{:tls_connection, :send_handshake, 2,
[file: 'tls_connection.erl', line: 109]},
{:ssl_connection, :client_certify_and_key_exchange, 2,
[file: 'ssl_connection.erl', line: 1118]},
{:tls_connection, :next_state, 4, [file: 'tls_connection.erl', line: 466]}]}

Feature Request: Switch to Tesla for HTTP library

If Contentful.ex switched to Tesla, this would enable users to choose which underlying HTTP library to use by defining an Adapter. For example, a team could choose to use Finch (instead of the current HTTPoison) because it is already in use and they want to ensure consistency.

Tesla would also allow teams to include middleware, such as tesla_statsd, to help monitor their request volume.

Evaluate GH actions

After reading over asaaki/cmark.ex#49, I was wondering if integrating CircleCI really is the way to go, as the status seemed broken for forked repositories.

  • Evaluate building via GH actions instead of circle ci.

Hardcoded end point

The endpoint is hard-coded to cdn.contentful.com which only shows entries that have been published. By making it a run-time config, one can set the endpoint to preview.contentful.com and retrieve entries that are in draft state.

Contentful.SysData missing important information

In previous versions, the map that has been replaced with Contentful.SysData contained a number of important fields. These included:

...
  sys: %{
    contentType: %{
      sys: %{
        id: "<content-type-from-model>",  # for example: "author"
        ...
      }
    },
    createdAt: "<created-timestamp>",
    updatedAt: "<updated-timestamp>",
    locale: "<locale-string>",  # eg: "en-GB",
    ...
  }
...

I'd like to update to the latest Contentful version, but my system is reliant on these fields.

Can these fields be returned to the Contentful.Entry/Contentful.Asset or Contentful.SysData structs?

Build fails due to libcrypto error

Apparently, the actions/setup-elixir currently runs into trouble when installing Erlang.

The actions/setup-elixir repo is currently unmaintained (as the Erlang foundation took over). It's recommended to switch to erlef/setup-beam instead,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.