1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Entry is a Data class, whose members the inline parser cannot read, and
# the interfaces every provider and source meets are named here so
# Sources.providers can be typed by them.
module RankKing
  module Sources
    class Entry
      attr_reader key: String
      attr_reader name: String

      def self.new: (key: String, name: String) -> instance
    end

    # A list's source.
    interface _Source
      # The text of the button that opens the sync dialog.
      def label: () -> String

      # What the sync dialog holds: a form that posts to the list's sync.
      def form: (csrf: Method) -> _Component

      # Applies what that form posted.
      def sync: (Hash[String, untyped] params) -> void

      # How one of the list's items shows wherever it is listed or compared.
      def item: (Item item) -> _Component
    end

    # A source that fetches its items, as Sync.call needs it.
    interface _Synced
      # Every item of the list, archived ones included, by the key its
      # entries carry.
      def items_by_key: () -> Hash[String, Item]

      # Called by sync for each entry once its item is saved, to keep
      # whatever the source knows about the item in its own table.
      def saved: (Item item, Entry entry) -> void
    end

    # What a list is made from, holding whatever of the app's config its
    # sources need, named by a list's source_kind.
    interface _Provider
      # The source for a list made from this provider.
      def source: (List list) -> _Source

      # What the provider is called where a list's source is chosen or
      # shown.
      def title: () -> String

      # The provider's own fields on the new-list form, which may post to
      # routes of their own as they are filled in.
      def fields: (csrf: Method) -> _Component

      # Sets a new list up from what those fields posted, raising Invalid,
      # and the list is not made, when they are not enough to go on.
      def create: (List list, Hash[String, untyped] params) -> void

      # Mounts the routes the provider's own fields and dialogs post to,
      # ahead of the app's.
      def routes: (Roda::RodaRequest r) -> void
    end

    # A view component, as a source's form is.
    interface _Component
      def call: () -> String
    end
  end
end