@omelhorsite/sdk 0.2.0 → 0.4.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.
- package/README.md +112 -130
- package/dist/index.js +4800 -610
- package/dist/types/client.d.ts +60 -3
- package/dist/types/http.d.ts +444 -19
- package/dist/types/index.d.ts +5 -1
- package/dist/types/internal/attachments.d.ts +17 -0
- package/dist/types/internal/helpers.d.ts +9 -0
- package/dist/types/listing.d.ts +90 -0
- package/dist/types/resources/account.d.ts +71 -5
- package/dist/types/resources/admin/authorizedApplications.d.ts +133 -0
- package/dist/types/resources/admin/chests.d.ts +51 -0
- package/dist/types/resources/admin/eventAlerts.d.ts +60 -0
- package/dist/types/resources/admin/identities.d.ts +99 -0
- package/dist/types/resources/admin/index.d.ts +77 -0
- package/dist/types/resources/admin/jobs.d.ts +97 -0
- package/dist/types/resources/admin/myOauthApplications.d.ts +282 -0
- package/dist/types/resources/admin/notepads.d.ts +49 -0
- package/dist/types/resources/admin/oauthApplications.d.ts +309 -0
- package/dist/types/resources/admin/quotas.d.ts +114 -0
- package/dist/types/resources/admin/shortLinks.d.ts +201 -0
- package/dist/types/resources/admin/types.d.ts +222 -0
- package/dist/types/resources/admin/vocalSeparations.d.ts +98 -0
- package/dist/types/resources/admin.d.ts +1841 -0
- package/dist/types/resources/auth/index.d.ts +39 -0
- package/dist/types/resources/auth/passkeys.d.ts +652 -0
- package/dist/types/resources/auth/sessions.d.ts +844 -0
- package/dist/types/resources/chests.d.ts +54 -3
- package/dist/types/resources/content/analysis.d.ts +62 -0
- package/dist/types/resources/content/blogs.d.ts +471 -0
- package/dist/types/resources/content/feedbacks.d.ts +263 -0
- package/dist/types/resources/content/index.d.ts +52 -0
- package/dist/types/resources/content/intel/articles.d.ts +230 -0
- package/dist/types/resources/content/intel/config.d.ts +135 -0
- package/dist/types/resources/content/intel/index.d.ts +53 -0
- package/dist/types/resources/content/intel/items.d.ts +91 -0
- package/dist/types/resources/content/intel/reports.d.ts +108 -0
- package/dist/types/resources/content/intel/scripts.d.ts +152 -0
- package/dist/types/resources/content/intel/sources.d.ts +236 -0
- package/dist/types/resources/content/intel/stats.d.ts +105 -0
- package/dist/types/resources/content/intel/types.d.ts +86 -0
- package/dist/types/resources/content/jokes.d.ts +93 -0
- package/dist/types/resources/content/notifications.d.ts +147 -0
- package/dist/types/resources/content/serviceUsages.d.ts +73 -0
- package/dist/types/resources/content/servicesStatus.d.ts +194 -0
- package/dist/types/resources/content/siteConfig.d.ts +43 -0
- package/dist/types/resources/content/spaceInvaders.d.ts +154 -0
- package/dist/types/resources/content.d.ts +2775 -0
- package/dist/types/resources/dynamicQrs.d.ts +39 -3
- package/dist/types/resources/forms.d.ts +176 -35
- package/dist/types/resources/index.d.ts +19 -8
- package/dist/types/resources/ipLookup.d.ts +20 -4
- package/dist/types/resources/jobs.d.ts +69 -25
- package/dist/types/resources/library/annotations.d.ts +162 -0
- package/dist/types/resources/library/books.d.ts +534 -0
- package/dist/types/resources/library/chat.d.ts +259 -0
- package/dist/types/resources/library/index.d.ts +39 -0
- package/dist/types/resources/library/shelves.d.ts +237 -0
- package/dist/types/resources/library/types.d.ts +120 -0
- package/dist/types/resources/library.d.ts +1433 -0
- package/dist/types/resources/linkTrees.d.ts +142 -30
- package/dist/types/resources/media.d.ts +351 -0
- package/dist/types/resources/movies/addons.d.ts +388 -0
- package/dist/types/resources/movies/collections.d.ts +352 -0
- package/dist/types/resources/movies/index.d.ts +29 -0
- package/dist/types/resources/movies/types.d.ts +50 -0
- package/dist/types/resources/movies/watchProgress.d.ts +277 -0
- package/dist/types/resources/movies.d.ts +1160 -0
- package/dist/types/resources/music/artists.d.ts +1068 -0
- package/dist/types/resources/music/imports.d.ts +941 -0
- package/dist/types/resources/music/index.d.ts +61 -0
- package/dist/types/resources/music/playlists.d.ts +1027 -0
- package/dist/types/resources/music/social.d.ts +1132 -0
- package/dist/types/resources/music/songs.d.ts +1167 -0
- package/dist/types/resources/notepads.d.ts +4 -1
- package/dist/types/resources/quotas.d.ts +7 -1
- package/dist/types/resources/realtime.d.ts +855 -0
- package/dist/types/resources/shortLinks.d.ts +49 -5
- package/dist/types/resources/social/groupChats.d.ts +458 -0
- package/dist/types/resources/social/index.d.ts +19 -0
- package/dist/types/resources/social/messages.d.ts +424 -0
- package/dist/types/resources/social/relationships.d.ts +322 -0
- package/dist/types/resources/social/types.d.ts +37 -0
- package/dist/types/resources/social.d.ts +1348 -0
- package/dist/types/resources/storage/upload.d.ts +158 -11
- package/dist/types/resources/storage.d.ts +111 -27
- package/dist/types/resources/tickets.d.ts +101 -13
- package/dist/types/resources/tools/backgroundRemoval.d.ts +18 -3
- package/dist/types/resources/tools/captions.d.ts +448 -21
- package/dist/types/resources/tools/downloader.d.ts +21 -0
- package/dist/types/resources/tools/index.d.ts +57 -15
- package/dist/types/resources/tools/jumpstyle.d.ts +50 -17
- package/dist/types/resources/tools/transcription.d.ts +35 -13
- package/dist/types/resources/tools/upscale.d.ts +23 -3
- package/dist/types/resources/tools/vocalSeparation.d.ts +30 -13
- package/dist/types/types.d.ts +249 -17
- package/package.json +2 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/** The public status page: live probes and the uptime report. */
|
|
2
|
+
import { Resource } from "../../http";
|
|
3
|
+
import type { RequestOptions, Timestamp } from "../../types";
|
|
4
|
+
/** The three services `GET /services_status` actually probes. */
|
|
5
|
+
export declare const EXTERNAL_SERVICE_SLUGS: readonly ["vocal_separator", "ai", "yt_dlp"];
|
|
6
|
+
/**
|
|
7
|
+
* The eight services that live inside the Rails process and are therefore
|
|
8
|
+
* "up" whenever the healthcheck job runs at all. They appear in
|
|
9
|
+
* {@link ServicesStatusNamespace.uptime} and NOT in
|
|
10
|
+
* {@link ServicesStatusNamespace.current}.
|
|
11
|
+
*/
|
|
12
|
+
export declare const INTERNAL_SERVICE_SLUGS: readonly ["accounts", "notifications", "storage", "socials", "short_links", "ip_lookup", "jokes", "space_invaders"];
|
|
13
|
+
/** Every slug the uptime report covers. */
|
|
14
|
+
export declare const ALL_SERVICE_SLUGS: readonly ["accounts", "notifications", "storage", "socials", "short_links", "ip_lookup", "jokes", "space_invaders", "vocal_separator", "ai", "yt_dlp"];
|
|
15
|
+
/** A service slug. Open, because the registry is a constant somebody will extend. */
|
|
16
|
+
export type ServiceSlug = (typeof ALL_SERVICE_SLUGS)[number] | (string & {});
|
|
17
|
+
/** Live health of one external service. */
|
|
18
|
+
export interface ServiceHealth {
|
|
19
|
+
/** `true` when the probe got a 2xx from the service's `/health`. */
|
|
20
|
+
readonly ok: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* A STRING, and not the HTTP status you might expect from the name.
|
|
23
|
+
*
|
|
24
|
+
* It is `"OK"` when the probe succeeded, and otherwise the failure's
|
|
25
|
+
* identity: either a Ruby exception class (`"Errno::ECONNREFUSED"`,
|
|
26
|
+
* `"Net::OpenTimeout"`, `"SocketError"`), or `"HTTP<code>"` for a
|
|
27
|
+
* non-success response (`"HTTP503"`), or `"MissingURL"` when the service has
|
|
28
|
+
* no URL configured. Show it, do not parse it - the set is whatever Ruby
|
|
29
|
+
* happens to raise.
|
|
30
|
+
*/
|
|
31
|
+
readonly status: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The live status map: one entry per external slug, and nothing else.
|
|
35
|
+
*
|
|
36
|
+
* Keyed by {@link EXTERNAL_SERVICE_SLUGS} only - the internal services do not
|
|
37
|
+
* appear, because there is nothing to ping.
|
|
38
|
+
*/
|
|
39
|
+
export type ServicesStatusMap = Record<string, ServiceHealth>;
|
|
40
|
+
/** One day of a service's history in the uptime report. */
|
|
41
|
+
export interface UptimeDay {
|
|
42
|
+
/** `YYYY-MM-DD`, in the SERVER's timezone - the bucket is `DATE(created_at)`. */
|
|
43
|
+
readonly date: string;
|
|
44
|
+
/**
|
|
45
|
+
* - `"up"` - every ping that day succeeded;
|
|
46
|
+
* - `"degraded"` - some succeeded and some did not;
|
|
47
|
+
* - `"down"` - every ping failed;
|
|
48
|
+
* - `"unknown"` - no pings at all that day (the future half of today, days
|
|
49
|
+
* before the service existed, and any window where the healthcheck job was
|
|
50
|
+
* not running).
|
|
51
|
+
*/
|
|
52
|
+
readonly status: "up" | "degraded" | "down" | "unknown";
|
|
53
|
+
/** Successful pings that day. Roughly 1440 on a fully healthy day. */
|
|
54
|
+
readonly up: number;
|
|
55
|
+
/** Failed pings that day. */
|
|
56
|
+
readonly down: number;
|
|
57
|
+
}
|
|
58
|
+
/** One service's 90-day history. */
|
|
59
|
+
export interface UptimeService {
|
|
60
|
+
readonly slug: ServiceSlug;
|
|
61
|
+
/**
|
|
62
|
+
* Exactly 90 entries, oldest first, with no gaps: a day with no data is
|
|
63
|
+
* present with `status: "unknown"` and zero counts rather than missing.
|
|
64
|
+
* Index 89 is today, and today is partial.
|
|
65
|
+
*/
|
|
66
|
+
readonly days: UptimeDay[];
|
|
67
|
+
/**
|
|
68
|
+
* Successful pings over total pings across the whole window, as a
|
|
69
|
+
* percentage rounded to two decimals. `null` when the service has no pings
|
|
70
|
+
* at all in the window - a brand new slug, or a long outage of the
|
|
71
|
+
* healthcheck job itself. Do not render `null` as `0%`.
|
|
72
|
+
*/
|
|
73
|
+
readonly uptime_pct: number | null;
|
|
74
|
+
}
|
|
75
|
+
/** A note appended to an incident as it progressed. */
|
|
76
|
+
export interface IncidentUpdate {
|
|
77
|
+
/**
|
|
78
|
+
* Free text. Auto-opened incidents post `"investigating"` and `"resolved"`;
|
|
79
|
+
* a hand-written one can say anything.
|
|
80
|
+
*/
|
|
81
|
+
readonly status: string;
|
|
82
|
+
readonly body: string | null;
|
|
83
|
+
readonly created_at: Timestamp;
|
|
84
|
+
}
|
|
85
|
+
/** A public incident on the status page. */
|
|
86
|
+
export interface Incident {
|
|
87
|
+
/** An INTEGER. */
|
|
88
|
+
readonly id: number;
|
|
89
|
+
/** Auto-opened incidents are titled `"<slug> indisponível"`, in Portuguese. */
|
|
90
|
+
readonly title: string;
|
|
91
|
+
readonly body: string | null;
|
|
92
|
+
/** Auto-opened ones are always `"major"`. */
|
|
93
|
+
readonly severity: "minor" | "major" | "critical";
|
|
94
|
+
readonly started_at: Timestamp;
|
|
95
|
+
/** `null` while the incident is open. */
|
|
96
|
+
readonly resolved_at: Timestamp | null;
|
|
97
|
+
/** Affected slugs. Can be empty, and can name a slug not in the registry. */
|
|
98
|
+
readonly services: ServiceSlug[];
|
|
99
|
+
/** Oldest first. */
|
|
100
|
+
readonly updates: IncidentUpdate[];
|
|
101
|
+
}
|
|
102
|
+
/** The whole uptime report. */
|
|
103
|
+
export interface UptimeReport {
|
|
104
|
+
/** First day of the window, `YYYY-MM-DD`. 89 days before `to`. */
|
|
105
|
+
readonly from: string;
|
|
106
|
+
/** Today, `YYYY-MM-DD`. */
|
|
107
|
+
readonly to: string;
|
|
108
|
+
/** One entry per slug in {@link ALL_SERVICE_SLUGS}, in registry order. */
|
|
109
|
+
readonly services: UptimeService[];
|
|
110
|
+
/** The 20 most recent PUBLIC incidents, newest first. Private ones are omitted. */
|
|
111
|
+
readonly incidents: Incident[];
|
|
112
|
+
}
|
|
113
|
+
/** Seconds of server-side caching on {@link ServicesStatusNamespace.uptime}. */
|
|
114
|
+
export declare const UPTIME_CACHE_SECONDS = 60;
|
|
115
|
+
/** Days of history the uptime report covers. */
|
|
116
|
+
export declare const UPTIME_WINDOW_DAYS = 90;
|
|
117
|
+
/**
|
|
118
|
+
* The `services_status` namespace: the public status page.
|
|
119
|
+
*
|
|
120
|
+
* Both routes are anonymous (`allow_unauthenticated_access` with no `only:`),
|
|
121
|
+
* and both are exempt from the visitor-logging after-action because the status
|
|
122
|
+
* widget polls from every page load and would otherwise drown the activity
|
|
123
|
+
* feed.
|
|
124
|
+
*
|
|
125
|
+
* ## The two calls have opposite cost profiles, and the names mislead
|
|
126
|
+
*
|
|
127
|
+
* {@link current} sounds cheap and is the expensive one; {@link uptime} sounds
|
|
128
|
+
* heavy and is served from a cache. Read both method docs before you put
|
|
129
|
+
* either behind a poller.
|
|
130
|
+
*/
|
|
131
|
+
export declare class ServicesStatusNamespace extends Resource {
|
|
132
|
+
/**
|
|
133
|
+
* `GET /services_status` - live health of the three external services.
|
|
134
|
+
*
|
|
135
|
+
* **This is the expensive endpoint in this namespace.** It performs the
|
|
136
|
+
* probes inline, on the request thread, one after another - the controller
|
|
137
|
+
* uses `index_with` with `Object#then`, so there is no concurrency - each
|
|
138
|
+
* with a 2 second connect timeout and a 5 second read timeout. A healthy
|
|
139
|
+
* call is a few tens of milliseconds; a call while all three are unreachable
|
|
140
|
+
* holds a Puma thread for up to about 21 seconds and returns
|
|
141
|
+
* `ok: false` three times.
|
|
142
|
+
*
|
|
143
|
+
* There is NO cache and NO dedicated rate limit, so it sits on the general
|
|
144
|
+
* anonymous budget of 120 requests per minute per IP. Poll it at most once
|
|
145
|
+
* every 30 seconds or so, and give it a client-side `timeoutMs` well above
|
|
146
|
+
* the SDK default if your default is short - a slow answer here is the
|
|
147
|
+
* normal answer during an outage, not a hung request.
|
|
148
|
+
*
|
|
149
|
+
* Only {@link EXTERNAL_SERVICE_SLUGS} appear in the map. The internal slugs
|
|
150
|
+
* are absent because they have nothing to probe; read them out of
|
|
151
|
+
* {@link uptime} instead.
|
|
152
|
+
*/
|
|
153
|
+
current(options?: RequestOptions): Promise<ServicesStatusMap>;
|
|
154
|
+
/**
|
|
155
|
+
* `GET /services_status/uptime` - 90 days of per-day history for all eleven
|
|
156
|
+
* services, plus the 20 most recent public incidents.
|
|
157
|
+
*
|
|
158
|
+
* ## Cost and freshness, honestly
|
|
159
|
+
*
|
|
160
|
+
* This endpoint was flooded (roughly 900 requests a minute from a load
|
|
161
|
+
* generator) and the fix was not a throttle: it was one grouped query plus a
|
|
162
|
+
* cache. It still has no rack-attack bucket of its own.
|
|
163
|
+
*
|
|
164
|
+
* - **Freshness: up to 60 seconds stale.** The whole payload is memoised
|
|
165
|
+
* under the single global cache key `"services_status/uptime"` for
|
|
166
|
+
* {@link UPTIME_CACHE_SECONDS} seconds. The key is not per-caller and not
|
|
167
|
+
* per-parameter (there are no parameters), so every visitor on the site
|
|
168
|
+
* shares one entry. Polling faster than once a minute cannot produce a
|
|
169
|
+
* newer number - it just spends your rate budget re-fetching bytes you
|
|
170
|
+
* already have.
|
|
171
|
+
* - **Cost on a hit: sending the payload.** Eleven services times ninety
|
|
172
|
+
* days is 990 day objects plus the incidents, so this is a
|
|
173
|
+
* double-digit-kilobyte response every time. There is no `ETag` and no
|
|
174
|
+
* `Last-Modified`, so it cannot answer `304` even when nothing changed.
|
|
175
|
+
* - **Cost on a miss: one grouped aggregate** over
|
|
176
|
+
* `service_pings` - `GROUP BY slug, DATE(created_at), status` across the
|
|
177
|
+
* window - which is on the order of a million rows, since the healthcheck
|
|
178
|
+
* job writes one ping per slug per minute. Indexed on
|
|
179
|
+
* `(slug, created_at)`, but it is still the single heaviest query on the
|
|
180
|
+
* public surface, and exactly one request per minute pays it.
|
|
181
|
+
*
|
|
182
|
+
* ## Reading the numbers
|
|
183
|
+
*
|
|
184
|
+
* `up` and `down` are ping counts, not durations: a fully healthy day is
|
|
185
|
+
* about 1440 up and 0 down. The window is 90 days and ping retention is also
|
|
186
|
+
* 90 days, so the OLDEST day in every report is partially pruned and its
|
|
187
|
+
* counts read low - do not compute an SLA off day zero.
|
|
188
|
+
*
|
|
189
|
+
* The eight internal slugs are `"up"` for every minute the Rails process was
|
|
190
|
+
* running the healthcheck job, because that is literally what they measure.
|
|
191
|
+
* They report the job's liveness, not the feature's.
|
|
192
|
+
*/
|
|
193
|
+
uptime(options?: RequestOptions): Promise<UptimeReport>;
|
|
194
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** The public configuration blob. */
|
|
2
|
+
import { Resource } from "../../http";
|
|
3
|
+
import type { RequestOptions } from "../../types";
|
|
4
|
+
/**
|
|
5
|
+
* The public configuration blob. One key today; treat it as open, since this
|
|
6
|
+
* is where any future "the browser needs to know this before signing in"
|
|
7
|
+
* value will land.
|
|
8
|
+
*/
|
|
9
|
+
export interface SiteConfig {
|
|
10
|
+
/**
|
|
11
|
+
* Cloudflare Turnstile site key, for rendering the widget.
|
|
12
|
+
*
|
|
13
|
+
* `null` when the credential is not configured - in development, and in any
|
|
14
|
+
* environment where the key was never set. A `null` here does NOT mean the
|
|
15
|
+
* captcha is disabled server-side: `require_captcha_if_anonymous!` still
|
|
16
|
+
* runs and still rejects an anonymous {@link FeedbacksNamespace.create}, so
|
|
17
|
+
* a client that skips the widget because this was null will see a 400 it
|
|
18
|
+
* cannot explain. Treat `null` as "anonymous submission is unavailable".
|
|
19
|
+
*/
|
|
20
|
+
readonly turnstile_site_key: string | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The `config` namespace: one anonymous GET that bootstraps the client.
|
|
24
|
+
*
|
|
25
|
+
* Deliberately tiny and deliberately public - it is the only thing a client
|
|
26
|
+
* can read before it has any credential at all, and the only reason it exists
|
|
27
|
+
* is that the Turnstile widget needs a site key before the anonymous feedback
|
|
28
|
+
* form can be submitted.
|
|
29
|
+
*/
|
|
30
|
+
export declare class SiteConfigNamespace extends Resource {
|
|
31
|
+
/**
|
|
32
|
+
* `GET /config` - the public configuration blob.
|
|
33
|
+
*
|
|
34
|
+
* Anonymous, no side effects, reads no database. It is not cached
|
|
35
|
+
* server-side and has no `ETag`, so it is a full round trip every time -
|
|
36
|
+
* fetch it once at boot and hold it, do not call it per form.
|
|
37
|
+
*
|
|
38
|
+
* Counts against the general ceiling like everything else (120/min per IP
|
|
39
|
+
* anonymous), and - the trap this file repeats - answers `403` if you attach
|
|
40
|
+
* an OAuth access token to it, because no route here accepts one.
|
|
41
|
+
*/
|
|
42
|
+
get(options?: RequestOptions): Promise<SiteConfig>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/** The Space Invaders leaderboard. */
|
|
2
|
+
import { Resource } from "../../http";
|
|
3
|
+
import type { ListParams } from "../../listing";
|
|
4
|
+
import type { Id, Paginated, RequestOptions, Timestamp } from "../../types";
|
|
5
|
+
/** `GET /space_invaders_games` filters on {@link BASE_FILTER_COLUMNS} only; there is no player filter. */
|
|
6
|
+
export declare const SPACE_INVADERS_GAME_FILTER_COLUMNS: readonly [];
|
|
7
|
+
/** Filters for {@link SpaceInvadersNamespace.list}. */
|
|
8
|
+
export type ListSpaceInvadersGamesParams = ListParams<(typeof SPACE_INVADERS_GAME_FILTER_COLUMNS)[number]>;
|
|
9
|
+
/** Primary key of a leaderboard entry. An INTEGER. */
|
|
10
|
+
export type SpaceInvadersGameId = number;
|
|
11
|
+
/** Points a single kill can be worth. Mirrors `MAX_POINTS_PER_KILL`. */
|
|
12
|
+
export declare const SPACE_INVADERS_MAX_POINTS_PER_KILL = 10;
|
|
13
|
+
/** Kills per second the validator will believe. Mirrors `MAX_KILLS_PER_SECOND`. */
|
|
14
|
+
export declare const SPACE_INVADERS_MAX_KILLS_PER_SECOND = 1;
|
|
15
|
+
/** Longest session the validator accepts, in seconds. 24 hours. */
|
|
16
|
+
export declare const SPACE_INVADERS_MAX_SESSION_SECONDS: number;
|
|
17
|
+
/** Rows the leaderboard returns. Mirrors the `leaderboard` scope's `limit`. */
|
|
18
|
+
export declare const SPACE_INVADERS_LEADERBOARD_SIZE = 100;
|
|
19
|
+
/**
|
|
20
|
+
* One finished game.
|
|
21
|
+
*
|
|
22
|
+
* ## `money` and `time` are STRINGS
|
|
23
|
+
*
|
|
24
|
+
* They are `decimal` columns with no precision or scale, and Rails encodes
|
|
25
|
+
* `BigDecimal` as a JSON string on purpose - a JSON number would be parsed as
|
|
26
|
+
* a float by most clients and silently lose precision. So the wire carries
|
|
27
|
+
* `"1200.0"`, not `1200`. `kills` is an `integer` column right next to them
|
|
28
|
+
* and arrives as a real number.
|
|
29
|
+
*
|
|
30
|
+
* Anything that sorts, sums or compares these must `Number()` them first;
|
|
31
|
+
* `"9.0" > "10.0"` is `true` in JavaScript.
|
|
32
|
+
*/
|
|
33
|
+
export interface SpaceInvadersGame {
|
|
34
|
+
readonly id: SpaceInvadersGameId;
|
|
35
|
+
/** The player. A STRING id. */
|
|
36
|
+
readonly user_id: Id;
|
|
37
|
+
/** Score. A decimal serialised as a STRING - see the interface docs. */
|
|
38
|
+
readonly money: string;
|
|
39
|
+
/** Session length in seconds. Also a decimal serialised as a STRING. */
|
|
40
|
+
readonly time: string;
|
|
41
|
+
/** Enemies killed. An integer, and a real JSON number. */
|
|
42
|
+
readonly kills: number;
|
|
43
|
+
/**
|
|
44
|
+
* When the game ended. Stamped SERVER-side from `Time.current` in a
|
|
45
|
+
* `before_create`, and deliberately not accepted from the request body, so a
|
|
46
|
+
* client cannot back-date or future-date an entry. Sending it is ignored.
|
|
47
|
+
*/
|
|
48
|
+
readonly played_at: Timestamp;
|
|
49
|
+
readonly created_at: Timestamp;
|
|
50
|
+
readonly updated_at: Timestamp;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Arguments for {@link SpaceInvadersNamespace.submit}.
|
|
54
|
+
*
|
|
55
|
+
* All three are required and all three are validated against each other. The
|
|
56
|
+
* bounds mirror `frontend/public/spaceinvaders/config.json` and are documented
|
|
57
|
+
* in the model as what they are: not anti-cheat, just a rejection of scores
|
|
58
|
+
* that are impossible under the game's own rules. The score is
|
|
59
|
+
* client-authoritative, so anybody willing to call this endpoint by hand can
|
|
60
|
+
* post any score inside the bounds.
|
|
61
|
+
*/
|
|
62
|
+
export interface SubmitSpaceInvadersGameInput {
|
|
63
|
+
/**
|
|
64
|
+
* Score. Must be `>= 0` and no greater than
|
|
65
|
+
* `kills * {@link SPACE_INVADERS_MAX_POINTS_PER_KILL}`, or the call is
|
|
66
|
+
* `400 "Money is impossibly high for N kills"`.
|
|
67
|
+
*/
|
|
68
|
+
readonly money: number;
|
|
69
|
+
/**
|
|
70
|
+
* Session length in seconds. Must be `>= 0` and
|
|
71
|
+
* `<= {@link SPACE_INVADERS_MAX_SESSION_SECONDS}`.
|
|
72
|
+
*/
|
|
73
|
+
readonly time: number;
|
|
74
|
+
/**
|
|
75
|
+
* Enemies killed. Must be a non-negative integer and no greater than
|
|
76
|
+
* `ceil(time * {@link SPACE_INVADERS_MAX_KILLS_PER_SECOND})`, or the call is
|
|
77
|
+
* `400 "Kills are impossibly high for a Ns game"`.
|
|
78
|
+
*/
|
|
79
|
+
readonly kills: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The `space_invaders_games` namespace: the leaderboard for the embedded game.
|
|
83
|
+
*
|
|
84
|
+
* The only genuinely public thing here is {@link leaderboard}. Submitting
|
|
85
|
+
* needs a session, and so - oddly - does {@link list}.
|
|
86
|
+
*/
|
|
87
|
+
export declare class SpaceInvadersNamespace extends Resource {
|
|
88
|
+
/**
|
|
89
|
+
* `GET /space_invaders_games/leaderboard` - the top
|
|
90
|
+
* {@link SPACE_INVADERS_LEADERBOARD_SIZE} scores, highest `money` first.
|
|
91
|
+
*
|
|
92
|
+
* Anonymous callers welcome. Not the list DSL: no paging, no filters, no
|
|
93
|
+
* ordering - `order(money: :desc).limit(100)` is the whole query, and it is
|
|
94
|
+
* backed by a descending index on `money`.
|
|
95
|
+
*
|
|
96
|
+
* One row per GAME, not per player: a player who posts three good runs
|
|
97
|
+
* occupies three slots. Deduplicate client-side if you want a per-player
|
|
98
|
+
* board.
|
|
99
|
+
*
|
|
100
|
+
* The rows carry `user_id` and nothing else about the player - no handle, no
|
|
101
|
+
* avatar - so a board with names needs a separate lookup.
|
|
102
|
+
*/
|
|
103
|
+
leaderboard(options?: RequestOptions): Promise<SpaceInvadersGame[]>;
|
|
104
|
+
/**
|
|
105
|
+
* `GET /space_invaders_games` - every game ever recorded, paged.
|
|
106
|
+
*
|
|
107
|
+
* `viewable_by` is `all`, so any signed-in caller enumerates the whole
|
|
108
|
+
* table, everybody's runs included. It needs a session even though
|
|
109
|
+
* {@link leaderboard} does not, which is the wrong way round if you were
|
|
110
|
+
* expecting the listing to be the public one.
|
|
111
|
+
*
|
|
112
|
+
* **You cannot filter by player.** The controller declares only
|
|
113
|
+
* `create_params`, so the search allowlist is the three defaults - `id`,
|
|
114
|
+
* `created_at`, `updated_at`. `exact_search: { user_id: "..." }` is
|
|
115
|
+
* `400 "Unknown exact_search filter: user_id"`. To show one player's
|
|
116
|
+
* history, page and filter client-side, or use `order: "money:desc"` and
|
|
117
|
+
* stop early.
|
|
118
|
+
*
|
|
119
|
+
* No default ordering, so pass one. Sends an `ETag`.
|
|
120
|
+
*/
|
|
121
|
+
list(params?: ListSpaceInvadersGamesParams, options?: RequestOptions): Promise<Paginated<SpaceInvadersGame>>;
|
|
122
|
+
/**
|
|
123
|
+
* `POST /space_invaders_games` - records a finished run. `201`.
|
|
124
|
+
*
|
|
125
|
+
* The player is taken from the session and `played_at` is stamped
|
|
126
|
+
* server-side; neither can be supplied. Any signed-in user may submit.
|
|
127
|
+
*
|
|
128
|
+
* Every submission is a new row, so a retry after a lost response posts the
|
|
129
|
+
* run twice and both appear on the leaderboard. The transport does not
|
|
130
|
+
* replay a `POST` by default, and this is an endpoint where you should not
|
|
131
|
+
* ask it to.
|
|
132
|
+
*
|
|
133
|
+
* There is no per-user rate limit beyond the general 600/min, and no
|
|
134
|
+
* de-duplication: two identical runs are two rows.
|
|
135
|
+
*
|
|
136
|
+
* @throws {OmsApiError} 400 with the validation sentence when the score
|
|
137
|
+
* fails the plausibility bounds - see {@link SubmitSpaceInvadersGameInput};
|
|
138
|
+
* 401 without a session.
|
|
139
|
+
*/
|
|
140
|
+
submit(input: SubmitSpaceInvadersGameInput, options?: RequestOptions): Promise<SpaceInvadersGame>;
|
|
141
|
+
/**
|
|
142
|
+
* `DELETE /space_invaders_games/:id` - removes an entry. `204`.
|
|
143
|
+
*
|
|
144
|
+
* The player who set it, or an admin. Anybody else gets
|
|
145
|
+
* `401 "You are not authorized to destroy this resource"` - and note it is a
|
|
146
|
+
* 401 rather than a 404, because `viewable_by` is `all` and the lookup
|
|
147
|
+
* succeeds before the authorisation check.
|
|
148
|
+
*
|
|
149
|
+
* There is no update route: the resource is declared
|
|
150
|
+
* `only: [:create, :index, :destroy]`, so a score can be deleted but never
|
|
151
|
+
* edited.
|
|
152
|
+
*/
|
|
153
|
+
destroy(id: SpaceInvadersGameId, options?: RequestOptions): Promise<void>;
|
|
154
|
+
}
|