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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# Sequel ships no signatures, so this describes the parts rank-king
# calls: one SQLite database, the datasets over it, and the model
# plumbing the four models are built from. Anything called that is
# missing here is a type error rather than a silent `untyped`.
module Sequel
  type row = Hash[Symbol, untyped]

  def self.sqlite: (String path, **untyped options) -> Database

  # Loads an extension into Sequel itself; `:migration` is the one this
  # app asks for, and it is what defines Migrator.
  def self.extension: (*Symbol names) -> void

  # The superclass of a model over a table, as `Sequel::Model(DB[:t])`.
  def self.Model: (Dataset[row] source) -> singleton(Model)

  class Database
    def []: (Symbol table) -> Dataset[row]

    # Raising Rollback inside the block undoes it and returns nil.
    def transaction: [T] () { () -> T } -> T?
  end

  class Rollback < StandardError
  end

  # Generic over what a row comes back as: a hash from a plain dataset,
  # a model instance from a model's association dataset.
  class Dataset[out T]
    def where: (*untyped conditions) -> Dataset[T]

    def exclude: (*untyped conditions) -> Dataset[T]

    # Rows keyed by one column's value.
    def to_hash: (Symbol key) -> Hash[untyped, T]
               | (Symbol key, Symbol value) -> Hash[untyped, untyped]

    def order: (*untyped columns) -> Dataset[T]

    def all: () -> Array[T]

    def first: () -> T?

    # One column of the first row.
    def get: (Symbol column) -> untyped

    def insert: (**untyped values) -> Integer

    # Inserts, replacing the row whose key conflicts.
    def replace: (**untyped values) -> Integer

    def join: (Symbol table, untyped conditions) -> Dataset[T]

    def select: (*Symbol columns) -> Dataset[row]

    def each: () { (T) -> void } -> void

    def delete: () -> Integer
  end

  class Model
    def self.plugin: (Symbol name, *untyped args, **untyped options) -> void

    def self.one_to_many: (Symbol name, **untyped options) -> void

    def self.many_to_one: (Symbol name, **untyped options) -> void

    def self.one_to_one: (Symbol name, **untyped options) -> void

    def self.create: (**untyped values) -> instance

    def self.all: () -> Array[instance]

    def self.where: (*untyped conditions) -> Dataset[instance]


    # The first row matching these columns, created when there is none.
    def self.find_or_create: (**untyped values) -> instance

    # The row with this primary key, or nil.
    def self.[]: (untyped id) -> instance?

    def id: () -> Integer

    # Sets the columns given and saves the row.
    def update: (**untyped values) -> self

    def destroy: () -> self

    # A hook Sequel runs inside destroy, before the row is deleted.
    def before_destroy: () -> void
  end

  # Applies the migrations in a directory that the database has not run
  # yet, and does nothing to one that is already current.
  class Migrator
    def self.run: (Database database, String directory, **untyped options) -> untyped
  end
end