funicular 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +429 -1
- data/demo/local_notes.html +207 -0
- data/docs/architecture.md +181 -3
- data/docs/local_database.md +1035 -0
- data/lib/funicular/assets/funicular.rb +14 -0
- data/lib/funicular/configuration.rb +65 -0
- data/lib/funicular/epoch_header.rb +69 -0
- data/lib/funicular/epoch_stamping.rb +66 -0
- data/lib/funicular/helpers/picoruby_helper.rb +96 -1
- data/lib/funicular/railtie.rb +30 -0
- data/lib/funicular/schema.rb +45 -12
- data/lib/funicular/session_epoch.rb +110 -0
- data/lib/funicular/ssr/runtime.rb +57 -12
- data/lib/funicular/ssr.rb +25 -0
- data/lib/funicular/testing/node_runner.mjs +19 -0
- data/lib/funicular/testing.rb +47 -0
- data/lib/funicular/vendor/mrbc/VERSION +1 -1
- data/lib/funicular/vendor/mrbc/mrbc.js +69 -115
- data/lib/funicular/vendor/mrbc/mrbc.wasm +0 -0
- data/lib/funicular/vendor/picoruby/VERSION +1 -1
- data/lib/funicular/vendor/picoruby/debug/picoruby.js +170 -120
- data/lib/funicular/vendor/picoruby/debug/picoruby.wasm +0 -0
- data/lib/funicular/vendor/picoruby/dist/picoruby.js +1 -1
- data/lib/funicular/vendor/picoruby/dist/picoruby.wasm +0 -0
- data/lib/funicular/vendor/picoruby-test-node/VERSION +1 -1
- data/lib/funicular/vendor/picoruby-test-node/picoruby.js +2 -7201
- data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm +0 -0
- data/lib/funicular/version.rb +1 -1
- data/lib/funicular.rb +1 -0
- data/lib/tasks/funicular.rake +10 -2
- data/minitest/callback_error_visibility_test.rb +48 -0
- data/minitest/configuration_test.rb +78 -0
- data/minitest/dsl_test.rb +27 -0
- data/minitest/epoch_header_test.rb +149 -0
- data/minitest/epoch_stamping_test.rb +225 -0
- data/minitest/fixtures/funicular_app/components/probe_component.rb +15 -0
- data/minitest/navigation_guard_test.rb +65 -0
- data/minitest/picoruby_helper_test.rb +236 -0
- data/minitest/schema_test.rb +47 -0
- data/minitest/session_epoch_test.rb +122 -0
- data/minitest/ssr_database_test.rb +78 -0
- data/minitest/ssr_reload_test.rb +106 -0
- data/minitest/ssr_test.rb +41 -0
- data/minitest/testing_ensure_compiled_test.rb +52 -0
- data/minitest/validations_test.rb +35 -5
- data/mrbgem.rake +2 -0
- data/mrblib/cable.rb +1 -1
- data/mrblib/component.rb +113 -1
- data/mrblib/db.rb +3116 -0
- data/mrblib/file_upload.rb +17 -7
- data/mrblib/funicular.rb +136 -17
- data/mrblib/http.rb +84 -107
- data/mrblib/model.rb +1178 -23
- data/mrblib/relation.rb +342 -0
- data/mrblib/router.rb +45 -4
- data/mrblib/styles.rb +20 -0
- data/sig/component.rbs +7 -0
- data/sig/db.rbs +328 -0
- data/sig/funicular.rbs +5 -0
- data/sig/http.rbs +8 -21
- data/sig/model.rbs +101 -7
- data/sig/relation.rbs +44 -0
- data/sig/router.rbs +1 -0
- data/sig/styles.rbs +1 -0
- metadata +19 -2
- data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm.map +0 -1
data/sig/db.rbs
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class RecordNotFound < StandardError
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
module DB
|
|
6
|
+
class Error < StandardError
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class NoTableError < Error
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class ReadOnlyTabError < Error
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class ReplicaWriteError < Error
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class SchemaTooNewError < Error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class UnavailableError < Error
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class ConfigError < Error
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
self.@subscriptions: Hash[Integer, [Symbol, String, Proc]]?
|
|
28
|
+
self.@subscription_serial: Integer?
|
|
29
|
+
self.@deferral_depths: Hash[Symbol, Integer]?
|
|
30
|
+
self.@pending_seen: Hash[Symbol, Hash[String, bool]]?
|
|
31
|
+
self.@pending_orders: Hash[Symbol, Array[[Symbol, String]]]?
|
|
32
|
+
self.@tick_events: Hash[String, bool]?
|
|
33
|
+
self.@tick_order: Array[[Symbol, String]]?
|
|
34
|
+
self.@tick_generation: Integer?
|
|
35
|
+
self.@drain_scheduled: bool?
|
|
36
|
+
self.@tick_scheduler: Proc?
|
|
37
|
+
|
|
38
|
+
def self.subscribe: (Symbol role, untyped table) { (Symbol role, String table) -> void } -> Integer
|
|
39
|
+
def self.unsubscribe: (Integer id) -> nil
|
|
40
|
+
def self.notify_changed: (untyped target, ?untyped table) -> nil
|
|
41
|
+
def self.validate_role: (untyped role) -> Symbol
|
|
42
|
+
private def self.deferral_depth: (Symbol role) -> Integer
|
|
43
|
+
private def self.pending_seen: (Symbol role) -> Hash[String, bool]
|
|
44
|
+
private def self.pending_order: (Symbol role) -> Array[[Symbol, String]]
|
|
45
|
+
def self.__begin_deferral: (Symbol role) -> void
|
|
46
|
+
def self.__commit_deferral: (Symbol role) -> void
|
|
47
|
+
def self.__rollback_deferral: (Symbol role) -> void
|
|
48
|
+
private def self.clear_pending: (Symbol role) -> nil
|
|
49
|
+
private def self.enqueue_delivery: (Symbol role, String table) -> nil
|
|
50
|
+
def self.__set_tick_scheduler: (Proc? scheduler) -> Proc?
|
|
51
|
+
private def self.schedule_drain: () -> nil
|
|
52
|
+
def self.__drain_events: () -> nil
|
|
53
|
+
private def self.deliver_event: (Symbol role, String table, ?Integer? generation) -> void
|
|
54
|
+
|
|
55
|
+
class GuardedStatement
|
|
56
|
+
@stmt: untyped
|
|
57
|
+
@guard: GuardedDatabase
|
|
58
|
+
|
|
59
|
+
def initialize: (untyped stmt, GuardedDatabase guard) -> void
|
|
60
|
+
def bind_params: (*untyped bind_vars) -> untyped
|
|
61
|
+
def readonly?: () -> bool
|
|
62
|
+
def columns: () -> untyped
|
|
63
|
+
def close: () -> untyped
|
|
64
|
+
def closed?: () -> bool
|
|
65
|
+
def execute: (*untyped bind_vars) -> Array[untyped]
|
|
66
|
+
def step: () -> untyped
|
|
67
|
+
|
|
68
|
+
private def check_writable: () -> void
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class GuardedResultSet
|
|
72
|
+
@rs: untyped
|
|
73
|
+
@stmt: untyped
|
|
74
|
+
@guard: GuardedDatabase
|
|
75
|
+
|
|
76
|
+
def initialize: (untyped rs, untyped stmt, GuardedDatabase guard) -> void
|
|
77
|
+
def next: () -> untyped
|
|
78
|
+
def each: () { (untyped row) -> void } -> GuardedResultSet
|
|
79
|
+
def to_a: () -> Array[untyped]
|
|
80
|
+
def reset: (*untyped bind_params) -> untyped
|
|
81
|
+
def eof?: () -> bool
|
|
82
|
+
def close: () -> untyped
|
|
83
|
+
def closed?: () -> bool
|
|
84
|
+
def columns: () -> untyped
|
|
85
|
+
def types: () -> untyped
|
|
86
|
+
|
|
87
|
+
private def check_writable: () -> void
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.enforce_read_only: (bool read_only, untyped raw_stmt) -> void
|
|
91
|
+
|
|
92
|
+
class GuardedDatabase
|
|
93
|
+
@db: untyped
|
|
94
|
+
@role: Symbol
|
|
95
|
+
@read_only: bool
|
|
96
|
+
|
|
97
|
+
def initialize: (untyped db, ?Symbol role, ?bool read_only) -> void
|
|
98
|
+
def role: () -> Symbol
|
|
99
|
+
def read_only?: () -> bool
|
|
100
|
+
def __become_read_only: () -> void
|
|
101
|
+
def execute: (String sql, ?Array[untyped] bind_vars) ?{ (untyped row) -> void } -> untyped
|
|
102
|
+
def prepare: (String sql) ?{ (GuardedStatement stmt) -> untyped } -> untyped
|
|
103
|
+
def query: (String sql, ?Array[untyped] bind_vars) ?{ (GuardedResultSet result) -> untyped } -> untyped
|
|
104
|
+
def get_first_row: (String sql, ?Array[untyped] bind_vars) -> untyped
|
|
105
|
+
def get_first_value: (String sql, ?Array[untyped] bind_vars) -> untyped
|
|
106
|
+
def transaction: (?Symbol mode) ?{ (GuardedDatabase proxy) -> untyped } -> untyped
|
|
107
|
+
def commit: () -> bool
|
|
108
|
+
def rollback: () -> bool
|
|
109
|
+
private def __execute_control: (String sql) -> nil
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
TRANSACTION_CONTROL_WORDS: Array[String]
|
|
113
|
+
def self.guard_statement_sql: (untyped sql) -> void
|
|
114
|
+
private def self.statement_head: (untyped sql) -> String
|
|
115
|
+
private def self.pragma_name: (String s, Integer pos) -> String
|
|
116
|
+
private def self.skip_sql_blanks: (String s, Integer i) -> Integer
|
|
117
|
+
private def self.read_sql_word: (String s, Integer i) -> [String, Integer]
|
|
118
|
+
private def self.read_sql_token: (String s, Integer i) -> [String, Integer]
|
|
119
|
+
LOCK_SHIM_JS: String
|
|
120
|
+
self.@durability: Symbol?
|
|
121
|
+
self.@writer_lock_name: String?
|
|
122
|
+
self.@lock_shim_installed: bool?
|
|
123
|
+
|
|
124
|
+
def self.durability: () -> Symbol
|
|
125
|
+
def self.__set_durability: (Symbol state) -> Symbol
|
|
126
|
+
def self.elect_writer: (String lock_name) -> Symbol
|
|
127
|
+
private def self.install_lock_shim: () -> void
|
|
128
|
+
def self.release_writer_lock: () -> bool
|
|
129
|
+
|
|
130
|
+
class Config
|
|
131
|
+
@replica_debounce_ms: Integer
|
|
132
|
+
@local_debounce_ms: Integer
|
|
133
|
+
@request_persistent_storage: bool
|
|
134
|
+
@on_persist_error: Proc?
|
|
135
|
+
@on_boot_error: Proc?
|
|
136
|
+
@on_session_change: Proc?
|
|
137
|
+
|
|
138
|
+
attr_accessor replica_debounce_ms: Integer
|
|
139
|
+
attr_accessor local_debounce_ms: Integer
|
|
140
|
+
attr_accessor request_persistent_storage: bool
|
|
141
|
+
attr_accessor on_persist_error: Proc?
|
|
142
|
+
attr_accessor on_boot_error: Proc?
|
|
143
|
+
attr_accessor on_session_change: Proc?
|
|
144
|
+
|
|
145
|
+
def initialize: () -> void
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
self.@config: Config?
|
|
149
|
+
self.@databases: Hash[Symbol, [untyped, Array[untyped]]]?
|
|
150
|
+
self.@snapshot_identity: String?
|
|
151
|
+
self.@snapshot_store: untyped
|
|
152
|
+
self.@snapshot_store_unavailable: bool?
|
|
153
|
+
self.@persist_timers: Hash[Symbol, untyped]?
|
|
154
|
+
self.@persist_timer_tokens: Hash[Symbol, Integer]?
|
|
155
|
+
self.@persist_deferred: Hash[Symbol, bool]?
|
|
156
|
+
self.@persist_inflight: Integer?
|
|
157
|
+
self.@mutation_generation: Integer?
|
|
158
|
+
self.@visibility_hook_installed: bool?
|
|
159
|
+
|
|
160
|
+
SNAPSHOT_DB_NAME: String
|
|
161
|
+
STORAGE_PERSIST_JS: String
|
|
162
|
+
|
|
163
|
+
def self.config: () -> Config
|
|
164
|
+
def self.configure: () { () -> void } -> nil
|
|
165
|
+
def self.__reset_config: () -> nil
|
|
166
|
+
def self.__register_database: (Symbol role, untyped raw_db, Array[untyped] models) -> nil
|
|
167
|
+
def self.__registered_database: (Symbol role) -> untyped
|
|
168
|
+
def self.__set_snapshot_identity: (String? identity) -> String?
|
|
169
|
+
def self.__set_snapshot_store: (untyped store) -> untyped
|
|
170
|
+
def self.snapshot_store: () -> untyped
|
|
171
|
+
def self.open_snapshot_store: () -> untyped
|
|
172
|
+
private def self.__become_volatile: (untyped error) -> nil
|
|
173
|
+
private def self.report_persist_error: (untyped error) -> nil
|
|
174
|
+
private def self.invoke_persist_error_hook: (untyped error) -> nil
|
|
175
|
+
def self.mutation_generation: () -> Integer
|
|
176
|
+
def self.persist_snapshot: (Symbol role) -> bool
|
|
177
|
+
def self.restore_snapshot: (Symbol role) -> bool
|
|
178
|
+
private def self.schedule_persist: (Symbol role) -> nil
|
|
179
|
+
def self.__persist_timer_fired: (Symbol role, Integer? token) -> nil
|
|
180
|
+
def self.__persist_timer_token: (Symbol role) -> Integer?
|
|
181
|
+
private def self.resume_deferred_persist: (Symbol role) -> nil
|
|
182
|
+
def self.cancel_persist_timers: () -> nil
|
|
183
|
+
private def self.persist_inflight: () -> Integer
|
|
184
|
+
private def self.await_inflight_persists: () -> nil
|
|
185
|
+
def self.flush: () -> bool
|
|
186
|
+
def self.__install_visibility_hook: () -> bool
|
|
187
|
+
def self.__visibility_flush: () -> nil
|
|
188
|
+
def self.request_persistent_storage: () -> Symbol
|
|
189
|
+
def self.stale_generation?: (Integer token) -> bool
|
|
190
|
+
def self.stale_response_error: () -> Error
|
|
191
|
+
|
|
192
|
+
self.@boot_state: Symbol?
|
|
193
|
+
self.@session_epoch: untyped
|
|
194
|
+
self.@page_metadata: Hash[Symbol, untyped]?
|
|
195
|
+
self.@page_metadata_latched: bool?
|
|
196
|
+
self.@local_database_enabled: bool?
|
|
197
|
+
self.@local_database_latched: bool?
|
|
198
|
+
self.@local_handle: GuardedDatabase?
|
|
199
|
+
self.@replica_handle: GuardedDatabase?
|
|
200
|
+
self.@schema_lockdown: untyped
|
|
201
|
+
|
|
202
|
+
def self.boot_state: () -> Symbol
|
|
203
|
+
def self.__set_boot_state: (Symbol state) -> Symbol
|
|
204
|
+
def self.session_epoch: () -> untyped
|
|
205
|
+
PAGE_METADATA_JS: String
|
|
206
|
+
|
|
207
|
+
def self.boot: (?models: Array[untyped]?, ?metadata: Hash[Symbol, untyped]?) -> bool
|
|
208
|
+
def self.__fail_boot: (Array[untyped] errors) -> bool
|
|
209
|
+
def self.__report_boot_errors: (Array[untyped] errors) -> bool
|
|
210
|
+
def self.read_page_metadata: () -> Hash[Symbol, untyped]
|
|
211
|
+
def self.__page_metadata: () -> Hash[Symbol, untyped]
|
|
212
|
+
def self.local_database_enabled?: () -> bool
|
|
213
|
+
def self.__set_local_database_enabled: (untyped value) -> bool
|
|
214
|
+
def self.__ensure_local_database_enabled: (untyped operation) -> bool
|
|
215
|
+
|
|
216
|
+
self.@session_terminated: bool?
|
|
217
|
+
self.@page_epoch_latched: bool?
|
|
218
|
+
|
|
219
|
+
def self.__set_session_epoch: (untyped value) -> untyped
|
|
220
|
+
def self.__latch_page_epoch: () -> untyped
|
|
221
|
+
def self.session_terminated?: () -> bool
|
|
222
|
+
def self.__session_epoch_ok?: (String? header) -> bool
|
|
223
|
+
def self.__terminate_session: (String? header) -> nil
|
|
224
|
+
private def self.__boot_steps: (Array[untyped] models, Hash[Symbol, untyped] metadata) -> nil
|
|
225
|
+
private def self.ensure_boot_not_terminated: () -> nil
|
|
226
|
+
private def self.metadata_value: (Hash[Symbol, untyped]? metadata, Symbol key, untyped default) -> untyped
|
|
227
|
+
private def self.report_boot_error: (Array[untyped] errors) -> nil
|
|
228
|
+
private def self.__install_handles: (untyped local_db, untyped replica_db) -> nil
|
|
229
|
+
def self.local: () -> GuardedDatabase
|
|
230
|
+
def self.replica: () -> GuardedDatabase
|
|
231
|
+
def self.__model_local_db: (untyped model) -> GuardedDatabase
|
|
232
|
+
def self.__model_replica_db: () -> GuardedDatabase?
|
|
233
|
+
private def self.engage_schema_lockdown: (untyped db, untyped error) -> nil
|
|
234
|
+
def self.schema_lockdown: () -> untyped
|
|
235
|
+
private def self.__check_schema_lockdown: (String context) -> nil
|
|
236
|
+
def self.reset_local_table: (untyped model) -> bool
|
|
237
|
+
private def self.revalidate_schema_lockdown: (untyped db) -> nil
|
|
238
|
+
def self.__reset_boot: () -> nil
|
|
239
|
+
def self.wipe: () -> bool
|
|
240
|
+
private def self.tick_generation: () -> Integer
|
|
241
|
+
private def self.clear_tick_events: () -> nil
|
|
242
|
+
private def self.ensure_session_not_terminated: (Symbol operation) -> nil
|
|
243
|
+
private def self.ensure_not_in_transaction: (Symbol role) -> nil
|
|
244
|
+
private def self.wipe_role: (Symbol role) -> nil
|
|
245
|
+
private def self.notify_wiped: (Symbol role) -> nil
|
|
246
|
+
private def self.drop_all_tables: (untyped db) -> nil
|
|
247
|
+
|
|
248
|
+
def self.namespace_identity: (untyped application_id, untyped user_key, bool anonymous) -> String
|
|
249
|
+
def self.resolve_namespace: (application_id: untyped, user_key: untyped, user_key_configured: bool, anonymous_only: bool) -> String
|
|
250
|
+
def self.snapshot_key: (String identity, Symbol role) -> String
|
|
251
|
+
def self.lock_name: (String identity) -> String
|
|
252
|
+
|
|
253
|
+
module Codec
|
|
254
|
+
def self.encode: (Symbol? `type`, untyped value) -> untyped
|
|
255
|
+
def self.decode: (Symbol? `type`, untyped value) -> untyped
|
|
256
|
+
def self.encode_bind: (untyped value) -> untyped
|
|
257
|
+
def self.time_to_iso: (Time time) -> String
|
|
258
|
+
def self.iso_to_time: (String str) -> Time
|
|
259
|
+
def self.civil_from_days: (Integer days) -> Array[Integer]
|
|
260
|
+
def self.days_from_civil: (Integer y, Integer m, Integer d) -> Integer
|
|
261
|
+
def self.days_in_month: (Integer year, Integer mon) -> Integer
|
|
262
|
+
def self.zone_offset: (String str, Integer pos) -> Integer
|
|
263
|
+
def self.digits_at: (String str, Integer pos, Integer len) -> Integer
|
|
264
|
+
def self.sep_at: (String str, Integer pos, Integer code) -> void
|
|
265
|
+
def self.zpad: (Integer n, Integer width) -> String
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
class TableBuilder
|
|
269
|
+
@ops: Array[untyped]
|
|
270
|
+
|
|
271
|
+
attr_reader ops: Array[untyped]
|
|
272
|
+
|
|
273
|
+
def initialize: () -> void
|
|
274
|
+
def string: (untyped name, ?default: untyped, ?null: bool) -> void
|
|
275
|
+
def text: (untyped name, ?default: untyped, ?null: bool) -> void
|
|
276
|
+
def integer: (untyped name, ?default: untyped, ?null: bool) -> void
|
|
277
|
+
def float: (untyped name, ?default: untyped, ?null: bool) -> void
|
|
278
|
+
def boolean: (untyped name, ?default: untyped, ?null: bool) -> void
|
|
279
|
+
def datetime: (untyped name, ?default: untyped, ?null: bool) -> void
|
|
280
|
+
def timestamps: () -> void
|
|
281
|
+
def index: (*untyped columns) -> void
|
|
282
|
+
def remove_index: (*untyped columns) -> void
|
|
283
|
+
def rename: (untyped old_name, untyped new_name) -> void
|
|
284
|
+
def remove: (untyped name) -> void
|
|
285
|
+
def execute: (String sql) -> void
|
|
286
|
+
|
|
287
|
+
private def add_column: (Symbol `type`, untyped name, untyped default, bool null) -> void
|
|
288
|
+
private def identifier_list: (Array[untyped] columns) -> Array[String]
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
SQL_TYPES: Hash[Symbol, String]
|
|
292
|
+
META_TABLE: String
|
|
293
|
+
REPLICA_FINGERPRINT_KEY: String
|
|
294
|
+
self.@reserved_column_names: Array[Symbol]?
|
|
295
|
+
|
|
296
|
+
def self.validate_identifier: (untyped name) -> String
|
|
297
|
+
private def self.guard_reserved_table: (String table) -> String
|
|
298
|
+
private def self.baseline_index: (untyped migrations) -> Integer
|
|
299
|
+
def self.fold_local_columns: (untyped model) -> Hash[String, Symbol]
|
|
300
|
+
private def self.fold_builders: (Array[TableBuilder] builders, untyped migrations, untyped model) -> Hash[String, Symbol]
|
|
301
|
+
def self.apply_local_migrations: (untyped db, untyped model) -> Integer
|
|
302
|
+
def self.rebuild_local_table: (untyped db, untyped model, ?Array[TableBuilder]? builders) -> Integer
|
|
303
|
+
def self.stored_table_version: (untyped db, String table) -> Integer
|
|
304
|
+
def self.store_table_version: (untyped db, String table, Integer version) -> void
|
|
305
|
+
def self.read_meta: (untyped db, String key) -> String?
|
|
306
|
+
def self.store_meta: (untyped db, String key, String value) -> void
|
|
307
|
+
private def self.ensure_meta_table: (untyped db) -> void
|
|
308
|
+
def self.replica_table_ddl: (untyped model) -> String
|
|
309
|
+
def self.canonical_replica_schema: (Array[untyped] models) -> String
|
|
310
|
+
def self.build_replica_tables: (untyped db, Array[untyped] models) -> bool
|
|
311
|
+
private def self.stale_replica_tables: (String? stored) -> Array[String]
|
|
312
|
+
def self.replica_upsert: (untyped db, untyped model, Hash[untyped, untyped] attrs) -> bool
|
|
313
|
+
def self.replica_upsert_all: (untyped db, untyped model, Array[untyped] rows) -> bool
|
|
314
|
+
private def self.replica_upsert_row: (untyped db, untyped model, Hash[untyped, untyped] attrs) -> void
|
|
315
|
+
def self.replica_delete: (untyped db, untyped model, untyped id) -> bool
|
|
316
|
+
private def self.collect_builders: (untyped model) -> Array[TableBuilder]
|
|
317
|
+
private def self.fold_ops: (Hash[String, Symbol] columns, Array[untyped] ops, untyped model) -> void
|
|
318
|
+
private def self.guard_id: (String name, untyped model) -> void
|
|
319
|
+
private def self.guard_reserved_column: (String name, untyped model) -> void
|
|
320
|
+
private def self.apply_blocks: (untyped db, untyped model, Integer from_version, Array[TableBuilder] builders) -> void
|
|
321
|
+
private def self.run_block: (untyped db, String table, TableBuilder builder, bool create_mode) -> void
|
|
322
|
+
private def self.run_alter_op: (untyped db, String table, Array[untyped] op) -> void
|
|
323
|
+
private def self.column_ddl: (Array[untyped] op) -> String
|
|
324
|
+
private def self.default_literal: (Symbol `type`, untyped value) -> String
|
|
325
|
+
private def self.index_name: (String table, Array[String] columns) -> String
|
|
326
|
+
private def self.quoted_list: (Array[String] columns) -> String
|
|
327
|
+
end
|
|
328
|
+
end
|
data/sig/funicular.rbs
CHANGED
|
@@ -8,6 +8,8 @@ module Funicular
|
|
|
8
8
|
def self.env: () -> EnvironmentInquirer
|
|
9
9
|
def self.env=: (EnvironmentInquirer | String environment) -> EnvironmentInquirer?
|
|
10
10
|
def self.router: () -> Router?
|
|
11
|
+
def self.confirm_handler=: ((^(String) -> boolish)? handler) -> (^(String) -> boolish)?
|
|
12
|
+
def self.confirm: (String message) -> bool
|
|
11
13
|
|
|
12
14
|
# SSR / hydration support
|
|
13
15
|
def self.server?: () -> bool
|
|
@@ -17,6 +19,9 @@ module Funicular
|
|
|
17
19
|
def self.first_element_child: (JS::Element container_element) -> JS::Element?
|
|
18
20
|
|
|
19
21
|
def self.load_schemas: (Hash[singleton(Model), String] models) ?{ () -> void } -> void
|
|
22
|
+
def self.__request_schema: (untyped model_class, String schema_name, Array[untyped] errors, Proc settle) -> nil
|
|
23
|
+
def self.__settle_boot_barrier: (Array[untyped] errors) ?{ () -> void } -> nil
|
|
24
|
+
def self.__boot_for_start: () -> bool
|
|
20
25
|
def self.start: (?singleton(Component)? component_class, ?container: String | JS::Element, ?props: Hash[Symbol, untyped], ?hydrate: bool) ?{ (Router router) -> void } -> (Component | Router | nil)
|
|
21
26
|
def self.configure_forms: () ?{ (Hash[Symbol, String]) -> void } -> void
|
|
22
27
|
def self.form_builder_config: () -> Hash[Symbol, String]?
|
data/sig/http.rbs
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
module Funicular
|
|
2
2
|
module HTTP
|
|
3
|
-
CACHE_DB_NAME: String
|
|
4
|
-
CACHE_STORE: String
|
|
5
|
-
|
|
6
|
-
self.@cache: IndexedDB::KVS?
|
|
7
|
-
|
|
8
3
|
class Response
|
|
9
4
|
attr_reader data: untyped
|
|
10
5
|
attr_reader status: Integer
|
|
@@ -15,24 +10,16 @@ module Funicular
|
|
|
15
10
|
def error_message: () -> String?
|
|
16
11
|
end
|
|
17
12
|
|
|
18
|
-
def self.
|
|
19
|
-
def self.
|
|
20
|
-
def self.
|
|
21
|
-
def self.
|
|
22
|
-
def self.
|
|
23
|
-
|
|
24
|
-
def self.get: (String url, ?cache: Integer?) { (Response) -> void } -> void
|
|
25
|
-
def self.post: (String url, ?Hash[untyped, untyped]? body, ?cache: Integer?) { (Response) -> void } -> void
|
|
26
|
-
def self.patch: (String url, ?Hash[untyped, untyped]? body, ?cache: Integer?) { (Response) -> void } -> void
|
|
27
|
-
def self.delete: (String url, ?cache: Integer?) { (Response) -> void } -> void
|
|
28
|
-
def self.put: (String url, ?Hash[untyped, untyped]? body, ?cache: Integer?) { (Response) -> void } -> void
|
|
13
|
+
def self.get: (String url) { (Response) -> void } -> void
|
|
14
|
+
def self.post: (String url, ?Hash[untyped, untyped]? body) { (Response) -> void } -> void
|
|
15
|
+
def self.patch: (String url, ?Hash[untyped, untyped]? body) { (Response) -> void } -> void
|
|
16
|
+
def self.delete: (String url) { (Response) -> void } -> void
|
|
17
|
+
def self.put: (String url, ?Hash[untyped, untyped]? body) { (Response) -> void } -> void
|
|
29
18
|
def self.csrf_token: () -> String?
|
|
30
19
|
|
|
31
|
-
private def self.warn_unsupported_cache: (String verb) -> void
|
|
32
|
-
private def self.now_seconds: () -> Integer
|
|
33
|
-
private def self.cache_hit?: (untyped entry, Integer ttl) -> bool
|
|
34
|
-
private def self.serve_from_cache: (Hash[String, untyped] entry) { (Response) -> void } -> void
|
|
35
20
|
private def self.parse_response_body: (untyped text) -> untyped
|
|
36
|
-
private def self.request: (String method, String url, Hash[untyped, untyped]? body
|
|
21
|
+
private def self.request: (String method, String url, Hash[untyped, untyped]? body) { (Response) -> void } -> void
|
|
22
|
+
private def self.session_changed_response: () -> Response
|
|
23
|
+
private def self.response_epoch: (untyped response) -> String?
|
|
37
24
|
end
|
|
38
25
|
end
|
data/sig/model.rbs
CHANGED
|
@@ -5,24 +5,118 @@ module Funicular
|
|
|
5
5
|
|
|
6
6
|
attr_reader id: untyped
|
|
7
7
|
@changed_attributes: Hash[String, untyped]
|
|
8
|
+
@local_baseline: Hash[String, untyped]?
|
|
9
|
+
@provided_attributes: Hash[String, bool]?
|
|
10
|
+
|
|
11
|
+
self.@registered_models: Array[untyped]?
|
|
12
|
+
self.@storage_kind: Symbol?
|
|
13
|
+
self.@local_migrations: Array[Hash[Symbol, untyped]]?
|
|
14
|
+
self.@collecting_migrations: bool?
|
|
15
|
+
self.@refresh_mode: Symbol?
|
|
16
|
+
self.@table_name: String?
|
|
17
|
+
self.@associations: Hash[Symbol, Hash[Symbol, untyped]]?
|
|
18
|
+
self.@local_columns: Hash[String, Symbol]?
|
|
8
19
|
|
|
9
20
|
def self.schema: () -> Hash[String, Hash[String, untyped]]
|
|
10
21
|
def self.schema=: (Hash[String, Hash[String, untyped]] schema) -> Hash[String, Hash[String, untyped]]
|
|
11
22
|
def self.endpoints: () -> Hash[String, Hash[String, String]]
|
|
12
23
|
def self.endpoints=: (Hash[String, Hash[String, String]] endpoints) -> Hash[String, Hash[String, String]]
|
|
13
24
|
|
|
25
|
+
def self.inherited: (untyped subclass) -> void
|
|
26
|
+
def self.__register_model: (untyped subclass) -> nil
|
|
27
|
+
def self.__registered_models: () -> Array[untyped]
|
|
28
|
+
|
|
14
29
|
def initialize: (?Hash[untyped, untyped] attributes) -> void
|
|
15
30
|
def self.load_schema: (Hash[String, untyped] schema_data) -> void
|
|
16
31
|
def self.register_schema_validations: (untyped validations) -> void
|
|
17
32
|
def self.normalize_validation_options: (Symbol | String kind, untyped opts) -> untyped
|
|
18
33
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def self.
|
|
22
|
-
def self.
|
|
34
|
+
# Local-database declaration DSL (docs/local_database.md). Migrate
|
|
35
|
+
# blocks are recorded at class eval and executed at DB boot.
|
|
36
|
+
def self.storage: (Symbol kind) ?{ () -> void } -> Symbol
|
|
37
|
+
def self.storage_kind: () -> Symbol
|
|
38
|
+
def self.replica?: () -> bool
|
|
39
|
+
def self.ephemeral?: () -> bool
|
|
40
|
+
def self.local?: () -> bool
|
|
41
|
+
def self.migrate: (Integer version, ?reset: bool) { (untyped t) -> void } -> void
|
|
42
|
+
def self.local_migrations: () -> Array[Hash[Symbol, untyped]]?
|
|
43
|
+
def self.validate_local_migrations: () -> void
|
|
44
|
+
def self.refresh: (Symbol mode) -> Symbol
|
|
45
|
+
def self.refresh_mode: () -> Symbol
|
|
46
|
+
|
|
47
|
+
# Associations: declaration-time metadata plus lazily resolved
|
|
48
|
+
# targets. The generated readers are dynamic, like the accessors.
|
|
49
|
+
def self.belongs_to: (Symbol | String name, ?class_name: (String | Symbol)?, ?foreign_key: (String | Symbol)?, **untyped rest) -> nil
|
|
50
|
+
def self.has_many: (Symbol | String name, ?class_name: (String | Symbol)?, ?foreign_key: (String | Symbol)?, **untyped rest) -> nil
|
|
51
|
+
def self.__reject_association_options: (Symbol kind, Symbol | String name, Hash[Symbol, untyped] rest) -> nil
|
|
52
|
+
def self.__register_association: (Symbol key) -> nil
|
|
53
|
+
def self.__assert_association_name_free: (Symbol key) -> nil
|
|
54
|
+
def self.__associations: () -> Hash[Symbol, Hash[Symbol, untyped]]
|
|
55
|
+
def self.__association_target: (Symbol key, String class_name) -> untyped
|
|
56
|
+
def self.__resolve_association_constant: (Symbol key, String class_name) -> untyped
|
|
57
|
+
def self.__unresolvable_association: (Symbol key, String class_name) -> String
|
|
58
|
+
def self.__assert_no_association_conflict: (Array[String] names) -> nil
|
|
59
|
+
|
|
60
|
+
def self.table_name: (?(String | Symbol)? explicit) -> String
|
|
61
|
+
def self.derive_table_name: () -> String
|
|
62
|
+
def self.demodulized_snake_name: () -> String
|
|
63
|
+
def self.__pluralize: (String name) -> String
|
|
64
|
+
def self.__singularize: (String name) -> String
|
|
65
|
+
def self.__camelize: (String name) -> String
|
|
66
|
+
def self.local: () -> Relation
|
|
67
|
+
|
|
68
|
+
# Relation protocol (mrblib/relation.rb)
|
|
69
|
+
def self.local_columns: () -> Hash[String, Symbol]
|
|
70
|
+
def self.derive_replica_columns: () -> Hash[String, Symbol]
|
|
71
|
+
def self.local_db: () -> untyped
|
|
72
|
+
def self.replica_db: () -> untyped
|
|
73
|
+
def self.build_from_local: (Hash[untyped, untyped] attrs) -> Model
|
|
74
|
+
def self.local_table_changed: () -> void
|
|
75
|
+
def self.on_change: () { (Symbol role, String table) -> void } -> Integer
|
|
76
|
+
def self.off_change: (Integer subscription) -> nil
|
|
77
|
+
def self.rest_attribute_type: (String name) -> Symbol?
|
|
78
|
+
def self.__write_through_upsert: (untyped attrs) -> void
|
|
79
|
+
def self.__write_through_upsert_all: (untyped rows) -> void
|
|
80
|
+
def self.__write_through_delete: (untyped id) -> void
|
|
81
|
+
|
|
82
|
+
# Unified callback contract (0.5.0): every REST callback is
|
|
83
|
+
# (result, error). On success `result` is the payload and `error` is
|
|
84
|
+
# nil; on failure `result` is nil. destroy's success payload is `true`.
|
|
85
|
+
# On storage :local models these methods are synchronous instead
|
|
86
|
+
# (bare-class alias): no blocks, direct return values.
|
|
87
|
+
def self.all: (?Hash[untyped, untyped] params) ?{ (Array[Model]? instances, untyped error) -> void } -> untyped
|
|
88
|
+
def self.find: (?untyped id, ?endpoint_name: String, ?model_class: singleton(Model)) ?{ (Model? instance, untyped error) -> void } -> untyped
|
|
89
|
+
def self.create: (?Hash[untyped, untyped] attrs, **untyped kw) ?{ (Model? instance, untyped error) -> void } -> untyped
|
|
90
|
+
def self.destroy: (?untyped id) ?{ (bool? success, untyped error) -> void } -> untyped
|
|
91
|
+
|
|
92
|
+
def update: (?Hash[untyped, untyped]? attrs) ?{ (Model? instance, untyped error) -> void } -> untyped
|
|
93
|
+
def destroy: () ?{ (bool? success, untyped error) -> void } -> untyped
|
|
94
|
+
def reload: () ?{ (Model? instance, untyped error) -> void } -> untyped
|
|
95
|
+
|
|
96
|
+
# storage :local CRUD and the bare-class alias
|
|
97
|
+
def self.define_local_accessors: (Hash[String, Symbol] columns) -> void
|
|
98
|
+
def self.define_local_accessor: (String name, Array[Symbol] existing) -> void
|
|
99
|
+
def self.merge_keyword_attrs: (Hash[untyped, untyped] attrs, Hash[Symbol, untyped] kw) -> Hash[untyped, untyped]
|
|
100
|
+
def self.local_create: (?Hash[untyped, untyped] attrs) -> Model
|
|
101
|
+
def self.reset_local: () -> bool
|
|
102
|
+
def self.local_query: (String method_name) -> Relation
|
|
103
|
+
def self.where: (?Hash[untyped, untyped] | String | nil conditions, *untyped binds) -> Relation
|
|
104
|
+
def self.order: (*untyped args) -> Relation
|
|
105
|
+
def self.limit: (Integer? n) -> Relation
|
|
106
|
+
def self.offset: (Integer? n) -> Relation
|
|
107
|
+
def self.count: () -> Integer
|
|
108
|
+
def self.first: () -> untyped
|
|
109
|
+
def self.exists?: () -> bool
|
|
110
|
+
def self.find_by: (Hash[untyped, untyped] conditions) -> untyped
|
|
111
|
+
def self.delete_all: () -> Integer
|
|
23
112
|
|
|
24
|
-
def
|
|
25
|
-
def
|
|
26
|
-
def
|
|
113
|
+
def new_record?: () -> bool
|
|
114
|
+
def __track_local_change: (String name, untyped value, untyped old) -> void
|
|
115
|
+
def __local_insert: () -> Model
|
|
116
|
+
def __local_update: (Hash[untyped, untyped]? attrs) -> bool
|
|
117
|
+
def __local_destroy: () -> bool
|
|
118
|
+
def __sync_from_row: () -> void
|
|
119
|
+
def __hydrate_local: (Hash[untyped, untyped] attrs) -> void
|
|
120
|
+
def __set_local_baseline: (Hash[untyped, untyped] attrs) -> void
|
|
27
121
|
end
|
|
28
122
|
end
|
data/sig/relation.rbs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Funicular
|
|
2
|
+
class Relation
|
|
3
|
+
@model: untyped
|
|
4
|
+
@where_sql: Array[String]
|
|
5
|
+
@where_binds: Array[untyped]
|
|
6
|
+
@order_sql: Array[String]
|
|
7
|
+
@limit: Integer?
|
|
8
|
+
@offset: Integer?
|
|
9
|
+
|
|
10
|
+
def initialize: (untyped model, ?Array[String] where_sql,
|
|
11
|
+
?Array[untyped] where_binds, ?Array[String] order_sql,
|
|
12
|
+
?Integer? limit, ?Integer? offset) -> void
|
|
13
|
+
|
|
14
|
+
def where: (?Hash[untyped, untyped] | String | nil conditions, *untyped binds) -> Relation
|
|
15
|
+
def order: (*untyped args) -> Relation
|
|
16
|
+
def limit: (Integer? n) -> Relation
|
|
17
|
+
def offset: (Integer? n) -> Relation
|
|
18
|
+
|
|
19
|
+
def to_a: () -> Array[untyped]
|
|
20
|
+
def each: () { (untyped record) -> void } -> Array[untyped]
|
|
21
|
+
def first: () -> untyped
|
|
22
|
+
def count: () -> Integer
|
|
23
|
+
def exists?: () -> bool
|
|
24
|
+
def find: (untyped id) -> untyped
|
|
25
|
+
def find_by: (Hash[untyped, untyped] conditions) -> untyped
|
|
26
|
+
def delete_all: () -> Integer
|
|
27
|
+
def to_sql: () -> String
|
|
28
|
+
def __event_source: () -> [Symbol, String]
|
|
29
|
+
|
|
30
|
+
private def append_condition: (Array[String] w, Array[untyped] b, untyped col, untyped value) -> void
|
|
31
|
+
private def order_term: (untyped col, untyped dir) -> String
|
|
32
|
+
private def validate_column: (untyped col) -> String
|
|
33
|
+
private def quote: (String name) -> String
|
|
34
|
+
private def quoted_table: () -> String
|
|
35
|
+
private def select_sql: () -> String
|
|
36
|
+
private def where_clause: () -> String
|
|
37
|
+
private def order_clause: () -> String
|
|
38
|
+
private def slice_clause: () -> String
|
|
39
|
+
private def slice_arg: (Integer? n, String label) -> Integer?
|
|
40
|
+
private def decode_row: (Array[String] cols, untyped row) -> Hash[String, untyped]
|
|
41
|
+
private def single_value: (String sql) -> untyped
|
|
42
|
+
private def model_label: () -> untyped
|
|
43
|
+
end
|
|
44
|
+
end
|
data/sig/router.rbs
CHANGED
|
@@ -21,6 +21,7 @@ module Funicular
|
|
|
21
21
|
def start: (?hydrate: bool) -> void
|
|
22
22
|
def stop: () -> void
|
|
23
23
|
def navigate: (String path) -> void
|
|
24
|
+
def leave_allowed?: () -> bool
|
|
24
25
|
def current_location_path: () -> String
|
|
25
26
|
|
|
26
27
|
private def add_route_with_method: (Symbol method, String path, singleton(Component) component_class, String? name, ?route_constraints_t? constraints) -> void
|