Compare commits

...
Author SHA1 Message Date
bflatastic 3849a18c8e api update 2 2026-06-15 22:23:31 +07:00
bflatastic ce7b180c7e api update 2026-06-15 21:26:33 +07:00
bflatastic 3f5bc6edf8 Webapp: settings modal feature flagged api key section 2026-06-15 21:16:44 +07:00
Brandon Thomas 0de867ad13 upgrade tauri 2.8 -> 2.11 (#1645) 2026-06-14 22:20:29 -04:00
Brandon Thomas a1cb1b2629 enhance database connection pooling (#1644) 2026-06-14 18:09:42 -04:00
BFlat 8da68b009c Desktop create pages redesign: shared generation feed, embedded model selector, gallery folders sidebar (#1635)
## Summary

Reworks the desktop (Tauri) app's Create Image / Create Video pages to
match the webapp,
extracts the webapp's generation gallery into a shared library used by
both apps, embeds the
model selector into every prompt box, adds a folders sidebar + marquee
selection to the gallery
modal, restyles the login/pricing/credits modals to the webapp look, and
turns the Apps page
into the default landing tab.

### Shared generation-list lib

- Extracted the webapp's generation feed into
`@storyteller/ui-generation-list`: list + masonry
grid views, pending/failed/completed rows and cards, thumbnail handling,
gallery/prompt data
hooks, and the shared grid/list view store + toggle. Host-specific
actions (recreate,
make-video, share, download, toasts) inject via render props — webapp
markup unchanged, its
  old files are now thin wrappers.

### Desktop create pages

- Prompt box fixed at the bottom, `max-w-5xl` like the webapp; pages
renamed to
  "Create Image" / "Create Video".
- Generation feed: in-progress/failed from the Tauri task queue, history
from the library API,
rendered as grid or list (toggle in the TopBar next to credits). Typed
Tauri completion events
  push finished media in instantly; the poll reconciles and dedupes.
- Row/card quick actions (recreate, make video, copy link, download)
backed by a shared
  `desktopMediaActions` module extracted from the TopBar gallery wiring.
- Hero + background act as a splash that fades when the feed loads;
bottom gradient behind the
prompt box. Batch generations show "Generating N images" on the single
pending chip.
- Video prompt box now expands vertically as far as the image prompt box
(viewport-relative).

### Embedded model selector

- `ClassyModelSelector` gained `variant="embedded"`: a compact pill that
opens the webapp-style
rich-list popover while keeping the desktop's provider selection.
Embedded on all five
prompt-input pages; floating selectors removed; legacy "10 sec." badges
dropped.

### Gallery modal

- Left sidebar lists the user's folders (drag-and-drop, right-click
management, new-folder
button) and shows on the Folders tab too, highlighting the active
folder's root branch.
- Marquee (drag-rectangle) selection in view mode, with edge
auto-scroll; starts only on blank
  background so it doesn't interfere with drag-to-folder/canvas.

### Restyled modals (desktop)

- Login/signup: webapp 2-column layout (form left, Vimeo showcase
right), no Google button
(Google auth isn't wired for Tauri), `artcraft-icon` logo, eye toggles.
The dismiss button is
removed so login is required; the post-auth Discord + Success onboarding
steps are kept, as is
  the existing Tauri auth flow.
- Pricing + credits: match the webapp visually (unified monochrome plan
cards with
Most Popular / Best Value highlight frames; `#161618` credit-pack cards
with Popular badge).
All billing stays on the existing Tauri `invoke` calls — no billing
logic changed.

### Apps page / navigation

- The Apps page is now the first tab and the default landing tab, with a
Home icon. Restyled to
the webapp home: "What will you craft today?" hero, Create / Edit
sections, gradient-hover
cards sized to their content, full-width scrollbar. The TopBar
quick-menu header reads
  "Create" instead of "Generate".

### Fixes

- Video Editor no longer crashes on the desktop app (`Tooltip must be
used within
TooltipProvider`): the editor shell now mounts its own Radix
`TooltipProvider`. The webapp got
one app-wide via `SidebarProvider`; the Tauri app had none, so panel
tooltips threw.

### Misc

- `getCreatorIconPathForModelId()` added to `@storyteller/model-list`
(model id → creator icon
  path, desktop/webapp aware).
2026-06-13 17:25:40 -04:00
Brandon Thomas e4bc031fbb modernize require_user_session_extended() (#1643) 2026-06-13 17:03:21 -04:00
Brandon Thomas d937a7f78f cleanup require_user_session (#1642) 2026-06-13 05:54:01 -04:00
Brandon Thomas fef96c3835 cleanup usage of require_moderator further (#1641) 2026-06-13 05:26:36 -04:00
Brandon Thomas b9e793098c cleanup session and require_moderator (#1640) 2026-06-13 04:52:35 -04:00
Brandon Thomas 222f3e958d actix crates upgrades (#1638) 2026-06-12 21:47:36 -04:00
Brandon Thomas 4ab06030dc fix cors with PUT methods (#1637) 2026-06-12 20:02:44 -04:00
Brandon Thomas 189c5afc80 updating pricing tests (#1636) 2026-06-12 19:52:58 -04:00
BFlat 2818831a66 Webapp: seed new folders with selection + marquee selection fixes (#1634)
- **New folder keeps selection:** "Add to folder > Create new folder"
now drops
the selected items into the folder on create instead of leaving it empty
  (webapp library + desktop gallery modal)
- **Marquee dead below the fold (main bug):** flex-column scroll parent
shrank
the page root to one viewport; presses lower down missed the handler.
Fixed
  with `shrink-0` so the root spans the full scroll height
- **Edge auto-scroll:** holding a drag near the top/bottom edge scrolls
the list
so you can keep selecting past the viewport in one drag (anchor
compensated for
  scroll; virtualized tiles stay selected)
- **No blue highlight:** `select-none` on the page (inputs opted back
in) blocks
accidental text/image highlighting and stops it competing with the drag
- **Rectangle no longer covers the top bar:** visible marquee box
clamped to the
  gallery viewport; selection hit-testing stays unclamped
2026-06-12 10:48:25 +07:00
Brandon Thomas 8497a8c83a artcraft 0.33 (#1633) 2026-06-11 23:02:35 -04:00
Brandon Thomas 5fff16ee22 cost accounting; credits updates (#1632) 2026-06-11 23:01:30 -04:00
bflatastic 1c3810e5a5 webapp: rounder corners and styling updates for mobile 2026-06-12 05:50:58 +07:00
bflatastic 5206a1d3e5 webapp: less blurry bg more visible promptbox 2026-06-12 05:19:15 +07:00
Tanish Manku 10f8297c1f Fix desktop video generation ignoring selected resolution (#1631)
The desktop video promptbox built the GenerateVideoRequest without ever
setting `resolution`, so generation always omitted it and the backend
fell back to the model's default (720p) — and billed for it. The cost
preview reads the same store value and sends it, so the preview was
correct (e.g. 117 for 480p) while the charge stayed at the 720p price
(240). Populate request.resolution in buildRequest, mapping the store's
legacy display string ("480p"/"720p"/"1080p") to CommonResolution,
guarded on the model exposing resolutionOptions.

Also fix useImageCostEstimate (webapp) omitting `quality` from its
effect deps, which meant the image cost preview didn't refresh when only
the quality option changed.
2026-06-11 14:48:48 -07:00
Brandon Thomas edb771ccfb uncommitted comet api module 2026-06-11 16:47:38 -04:00
Brandon Thomas 5979002f7e new cost tracking fields (#1630) 2026-06-11 16:37:43 -04:00
Brandon Thomas 74e30c4ffb comet api (#1629) 2026-06-11 10:43:32 -04:00
bflatastic 4061f00874 webapp: tailwind config colors update 2026-06-11 21:19:07 +07:00
bflatastic 633003c43b webapp: styling updates and package versions 2026-06-11 21:18:49 +07:00
Brandon Thomas 957db2d07f folders - add video previews / thumbnails (#1628) 2026-06-11 08:50:23 -04:00
Brandon Thomas b82a4e1599 change sorting for media files in folders (#1627) 2026-06-10 23:32:52 -04:00
BFlat bee790b952 feat(library): marquee selection, multi-select UX, mobile polish and … (#1626)
…perf

- Add desktop-style marquee drag selection on the webapp library: drag
on blank space to select covered tiles, click blank space to deselect
all
- Multi-select: clicking anywhere on a tile toggles it (fixes a
double-fire that cancelled the toggle so only the checkbox worked);
selection persists across tabs and folder navigation
- Gallery item menus show "View image" / "View video" / "View 3D" above
Add to Folder; menu panels size to content so labels no longer wrap
- Mobile/touch: no tile dragging or marquee (finger drags scroll),
checkbox and menu buttons always visible (no hover on touch), and the
Add to Folder submenu expands inline as an accordion instead of
overflowing the screen
- Select-mode gallery modal: folder cards hide the options menu and
ignore right-click (picker is browse-only)
- Perf: bulk selection moved to a module store with per-tile
subscriptions so selection changes re-render only flipped tiles, never
the page; marquee rectangle is positioned imperatively with cached tile
rects and commits only when coverage changes; webapp date groups
virtualized via the shared LazyDateGroup for smooth scrolling on large
libraries
- Bulk selection bar extracted to its own component, fixed to the
viewport bottom and centered within the content area
2026-06-11 00:47:42 +07:00
BFlat a2d57e3685 Folders for the library modal (#1309)
- Redesigned the gallery modal with a sidebar replacing the old filter
dropdown - filters now show as a list with item counts
- Added a Folders system - create, rename, and delete folders to
organize assets
- Users can drag items onto folders in the sidebar, including
multi-selected items
- Added "Add to Folder" option in the item right-click menu with a
folder picker submenu
- Added "Add to folder" button in the bulk selection bar with a folder
picker popup
- Clicking a folder in the sidebar opens a folder view with its own
content area and empty state
- Folder names are editable - click the title in the header or
right-click a folder in the sidebar to rename
- Videos are now draggable - previously only images and 3D objects could
be dragged
- Folder data is mocked locally for now - ready for API integration
2026-06-10 22:04:26 +07:00
Brandon Thomas 9104faf806 fix frontend dev scripts (#1625) 2026-06-10 09:28:25 -04:00
Brandon Thomas b011319abd dashboard links (#1624) 2026-06-10 09:03:58 -04:00
Brandon Thomas 1c654bfafa stripe info admin endpoint (#1623) 2026-06-10 08:42:32 -04:00
Brandon Thomas a7c59f7c9b fix test failures (#1622) 2026-06-10 00:52:24 -04:00
Brandon Thomas 780bbbe9cf test fixes (#1621) 2026-06-10 00:37:32 -04:00
Brandon Thomas 6e5cce20fb seedance errors revamp (#1620) 2026-06-09 22:52:03 -04:00
Brandon Thomas b12781056d track platform type (#1619) 2026-06-09 20:19:05 -04:00
Brandon Thomas 70fb0b784f folders - better media files links, last items, etc. in the API (#1618) 2026-06-09 09:48:19 -04:00
Brandon Thomas e9f46b1e87 folders fixes, new endpoint for atomic "move" (#1617) 2026-06-08 19:09:23 -04:00
BFlatandTanish Manku 9caaad5e0d Page video editor: Mount and make public (#1611)
Co-authored-by: Tanish Manku <tanish2k09.dev@gmail.com>
2026-06-08 13:01:51 -07:00
Brandon Thomas 8253e28560 folders (#1616) 2026-06-08 12:09:02 -04:00
bflatastic 7af6e5b867 Webapp: added missing seedance variant name mappings 2026-06-08 22:19:32 +07:00
bflatastic ccdcb01035 fix(webapp): clamp duration to nearest valid value on model switch instead of resetting to min 2026-06-08 21:18:23 +07:00
BFlat e3a8c04878 Webapp: OmniGen outage handling + toast fixes (#1615)
### Outage handling
- Show an error toast when the OmniGen service is unavailable (5xx)
instead of failing silently.
- Distinct messages for the two failure points: couldn't load the model
list vs. couldn't enqueue a generation.
- Model-fetch toast fires once per failed attempt (singleton fetch +
message dedup); generation toast is gated to 5xx so content-policy/4xx
rejections still just show the failed card and 402 still opens the
credits modal.
2026-06-08 20:59:50 +07:00
BFlat 3886253ffa Webapp: prompt-box fixes, in-progress recreate, model-name consistency, sticky settings (#1614)
### Prompt box
- Fix prompt box overflowing past the viewport at some desktop widths
(Generate button hidden) - removed `w-full` so it sizes to the content
area beside the sidebar (create-image + create-video).

### Recreate action
- Add **Recreate** to in-progress jobs in the create-page gallery (grid
+ list) and the task queue - previously only on completed/failed.
- Task queue had no Recreate at all; added it to all three states
(in-progress/completed/failed) for consistency.
- Recreate on the in-progress grid card sits bottom-right inline with
the prompt; in-progress list row reveals it on hover (matching completed
rows).
- Extract shared `useRecreateFromPromptToken` hook; refactor
FailedCard/FailedRow onto it (DRY).

### Model display names
- Consolidate to a single source of truth: webapp `getModelDisplayName`
now delegates to `@storyteller/model-list` (removed the duplicate local
map). Gallery, task queue, and lightbox now agree.
- Fix missing names: `gpt_image_1` (gallery) and Midjourney in the
lightbox - added `midjourney_7` / `midjourney_7_niji` / `midjourney_8`
to the model-list name + creator-icon maps; aligned `veo_2` → "Google
Veo 2".

### Sticky prompt settings across model switches
- Prompt-box settings no longer reset when switching models - the user's
choice persists and is resolved against the new model (kept if
supported, else falls back for display/generation only, without losing
the preference).
- Covers aspect ratio, count, resolution, quality (image) and aspect
ratio, resolution, count, duration, sound (video).
- Add `lib/resolve-model-setting.ts` (`resolveModelOption` /
`resolveModelCount`); `handleModelChange` now only switches the model (+
capability-bound input mode on video).
2026-06-08 19:35:20 +07:00
bflatastic c1b257b7d5 updated download links to v0.32.0 2026-06-06 07:56:31 +07:00
bflatastic b162e2bfc0 webapp: fixes to mobile sheet component on mobile 2026-06-06 07:50:07 +07:00
BFlat 3ea33dabd5 test fix 2: mobile freezing after image modal closed on mobile (#1613) 2026-06-06 07:37:15 +07:00
BFlat aee20db947 test fix: mobile freezing after image modal closed on mobile (#1612) 2026-06-06 07:20:20 +07:00
BFlat 3847a3d39c Revert "Page video editor: Mount and make public" (#1610)
Reverts storytold/artcraft#1606
2026-06-06 06:59:01 +07:00
BFlat 5747212f37 Revert "fix(ci): use pnpm instead of npm in artcraft publish workflows" (#1609)
Reverts storytold/artcraft#1608
2026-06-06 06:58:27 +07:00
Tanish Mankuandbflatastic 04ebe2c965 fix(ci): use pnpm instead of npm in artcraft publish workflows (#1608)
The frontend migrated to pnpm workspaces in #1606, which introduced
"workspace:*" dependencies. npm cannot resolve that protocol, so the
macOS and Windows publish workflows fail at "npm ci" with
EUNSUPPORTEDPROTOCOL, breaking production release builds on main.

Add a pinned pnpm setup step and replace the npm install block with
"pnpm install --frozen-lockfile". Verified the frozen install resolves
cleanly against the committed pnpm-lock.yaml.

---------

Co-authored-by: bflatastic <bombayapirat@gmail.com>
2026-06-06 06:49:16 +07:00
Tanish Mankuandbflatastic d09d44b7e2 Page video editor: Mount and make public (#1606)
Co-authored-by: bflatastic <bombayapirat@gmail.com>
2026-06-05 22:21:55 +07:00
BFlat 8e754b4b8f website: landing buttons and footer cta updates (#1607)
- Renamed the "Supercharge Credits" button to **Use on Web** (globe
icon) in the hero and bottom CTA. Routes subscribers to the webapp
homepage, everyone else to `/pricing`.
- Removed the "Create image / Create video" links from both sections.
- Split Discord + GitHub into a separate "Open source &
community-driven" CTA (subtle container) above the "Ready to craft?"
CTA.
2026-06-05 14:47:30 +07:00
BFlat cbda6b7b1f fix(webapp): prevent iOS caret loss in mobile prompt input (#1605)
MentionTextarea's DOM-sync effect rewrote innerHTML under the live caret
whenever buildHTML's identity changed, detaching the cursor on iOS
Safari mid-typing. Skip the rewrite when focused and the DOM already
matches value, and memoize colorMap in MobilePromptForm to stop the
per-render churn.
2026-06-04 13:05:30 +07:00
Brandon Thomas 186ce24390 fix routing 2026-06-03 23:59:13 -04:00
Brandon Thomas 3401e709bb rename handlers + codegen fix 2026-06-03 10:57:27 -04:00
Brandon Thomas f71d344ff3 admin email changes (#1604) 2026-06-03 10:37:28 -04:00
1153 changed files with 105504 additions and 11145 deletions
+2
View File
@@ -38,6 +38,7 @@ script/socat_dev_database_connect.sh
venv/
# LLM Testing
/external/
/prompts/
/reports/
/requests/
@@ -102,3 +103,4 @@ windows/sqlite/sqlite3.lib
# ArtCraft Windows DLLs
crates/desktop/src-tauri/*.dll
windows_dlls/
@@ -0,0 +1,179 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n f.id as `id: u64`,\n f.token as `token: FolderToken`,\n f.name,\n f.owner_user_token as `owner_user_token: UserToken`,\n f.maybe_parent_folder_token as `maybe_parent_folder_token: FolderToken`,\n f.maybe_last_media_file_token_1 as `maybe_last_media_file_token_1: MediaFileToken`,\n f.maybe_last_media_file_token_2 as `maybe_last_media_file_token_2: MediaFileToken`,\n f.maybe_last_media_file_token_3 as `maybe_last_media_file_token_3: MediaFileToken`,\n f.maybe_last_media_file_token_4 as `maybe_last_media_file_token_4: MediaFileToken`,\n f.maybe_cover_image_custom_media_token as `maybe_cover_image_custom_media_token: MediaFileToken`,\n f.maybe_color_code,\n f.has_star as `has_star: bool`,\n f.created_at,\n f.updated_at,\n (\n f.maybe_parent_folder_token IS NOT NULL\n AND (p.token IS NULL OR p.maybe_deleted_at IS NOT NULL)\n ) as `is_orphaned: bool`\nFROM folders f\nLEFT JOIN folders p\n ON p.token = f.maybe_parent_folder_token\nWHERE f.owner_user_token = ?\n AND f.maybe_deleted_at IS NULL\nORDER BY f.id DESC\nLIMIT ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 2,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 3,
"name": "owner_user_token: UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_parent_folder_token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "maybe_last_media_file_token_1: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "maybe_last_media_file_token_2: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_last_media_file_token_3: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_last_media_file_token_4: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 9,
"name": "maybe_cover_image_custom_media_token: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_color_code",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 11,
"name": "has_star: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 12,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 13,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 14,
"name": "is_orphaned: bool",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | BINARY",
"char_set": 63,
"max_size": 1
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false,
false
]
},
"hash": "05a880a2ece0236f57fe1c40100cba0c0cdcad2ebee0fecb88f9043ac7b82d8c"
}
@@ -120,7 +120,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 3
"max_size": 11
}
},
{
@@ -60,7 +60,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -70,7 +70,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -0,0 +1,179 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n f.id as `id: u64`,\n f.token as `token: FolderToken`,\n f.name,\n f.owner_user_token as `owner_user_token: UserToken`,\n f.maybe_parent_folder_token as `maybe_parent_folder_token: FolderToken`,\n f.maybe_last_media_file_token_1 as `maybe_last_media_file_token_1: MediaFileToken`,\n f.maybe_last_media_file_token_2 as `maybe_last_media_file_token_2: MediaFileToken`,\n f.maybe_last_media_file_token_3 as `maybe_last_media_file_token_3: MediaFileToken`,\n f.maybe_last_media_file_token_4 as `maybe_last_media_file_token_4: MediaFileToken`,\n f.maybe_cover_image_custom_media_token as `maybe_cover_image_custom_media_token: MediaFileToken`,\n f.maybe_color_code,\n f.has_star as `has_star: bool`,\n f.created_at,\n f.updated_at,\n (\n f.maybe_parent_folder_token IS NOT NULL\n AND (p.token IS NULL OR p.maybe_deleted_at IS NOT NULL)\n ) as `is_orphaned: bool`\nFROM folders f\nLEFT JOIN folders p\n ON p.token = f.maybe_parent_folder_token\nWHERE f.token = ?\n AND f.owner_user_token = ?\n AND f.maybe_deleted_at IS NULL\nLIMIT 1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 2,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 3,
"name": "owner_user_token: UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_parent_folder_token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "maybe_last_media_file_token_1: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "maybe_last_media_file_token_2: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_last_media_file_token_3: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_last_media_file_token_4: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 9,
"name": "maybe_cover_image_custom_media_token: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_color_code",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 11,
"name": "has_star: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 12,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 13,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 14,
"name": "is_orphaned: bool",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | BINARY",
"char_set": 63,
"max_size": 1
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false,
false
]
},
"hash": "0c918aacf4ce34e1e03d2f9af49dd3138cadf59a28d0917726135ed5f34cba5e"
}
@@ -210,7 +210,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -220,7 +220,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nINSERT INTO user_email_changes\nSET\n user_token = ?,\n old_email = ?,\n new_email = ?,\n ip_address = ?,\n maybe_changed_by_user_token = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 5
},
"nullable": []
},
"hash": "1359fb54af12d78251fe435b063771984ee00d74a71b5d29e9df267991f38522"
}
@@ -30,7 +30,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 3
"max_size": 11
}
},
{
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE folders\nSET maybe_cover_image_custom_media_token = ?\nWHERE token = ?\n AND owner_user_token = ?\n AND maybe_deleted_at IS NULL\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "197e4fb3822b095cbbf8127493dad91c9254b7c242b8921a8c2df9f5a0e77424"
}
@@ -1,6 +1,6 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n jobs.maybe_external_third_party_id as `request_id`,\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n jobs.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_wallet_ledger_entry_token as `maybe_wallet_ledger_entry_token: tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken`\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\n AND jobs.status NOT IN ('complete_success', 'complete_failure')\n AND jobs.maybe_external_third_party_id IS NOT NULL\n\nLIMIT 25000\n ",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n jobs.maybe_external_third_party_id as `request_id`,\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n jobs.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_wallet_ledger_entry_token as `maybe_wallet_ledger_entry_token: tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken`,\n jobs.platform_type as `maybe_platform_type: enums::common::platform_type::PlatformType`\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\n AND jobs.status NOT IN ('complete_success', 'complete_failure')\n AND jobs.maybe_external_third_party_id IS NOT NULL\n\nLIMIT 25000\n ",
"describe": {
"columns": [
{
@@ -82,6 +82,16 @@
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_platform_type: enums::common::platform_type::PlatformType",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
}
],
"parameters": {
@@ -95,8 +105,9 @@
false,
false,
true,
true,
true
]
},
"hash": "1ddb2207db50e2dbfb37d26c006bffe2d8f5fb011855d5a86d01f395c36df759"
"hash": "1a0b60602debe525529f50566fc545f1cb4b77005f423a10464652be7fbfa839"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE folders\nSET has_star = ?\nWHERE token = ?\n AND owner_user_token = ?\n AND maybe_deleted_at IS NULL\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "24716cfdb77eee365bd605a40cecb02b3a27a90725dbe96e3865545d14839ab8"
}
@@ -180,7 +180,7 @@
"type": "LongLong",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 20
}
},
{
@@ -40,7 +40,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -50,7 +50,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -50,7 +50,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -60,7 +60,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -210,7 +210,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -220,7 +220,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -1,6 +1,6 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n\n jobs.status as `status: enums::common::job_status_plus::JobStatusPlus`,\n\n jobs.maybe_external_third_party as `external_third_party: enums::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty`,\n jobs.maybe_external_third_party_id as `external_third_party_id`,\n\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_debug_log_event_token as `maybe_debug_log_event_token: tokens::tokens::non_unique::debug_logs_event_token::DebugLogEventToken`,\n\n jobs.created_at,\n jobs.updated_at\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\nAND jobs.maybe_external_third_party_id = ?\n ",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n\n jobs.status as `status: enums::common::job_status_plus::JobStatusPlus`,\n\n jobs.maybe_external_third_party as `external_third_party: enums::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty`,\n jobs.maybe_external_third_party_id as `external_third_party_id`,\n\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_debug_log_event_token as `maybe_debug_log_event_token: tokens::tokens::non_unique::debug_logs_event_token::DebugLogEventToken`,\n\n jobs.platform_type as `maybe_platform_type: enums::common::platform_type::PlatformType`,\n\n jobs.created_at,\n jobs.updated_at\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\nAND jobs.maybe_external_third_party_id = ?\n ",
"describe": {
"columns": [
{
@@ -95,6 +95,16 @@
},
{
"ordinal": 9,
"name": "maybe_platform_type: enums::common::platform_type::PlatformType",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 10,
"name": "created_at",
"type_info": {
"type": "Timestamp",
@@ -104,7 +114,7 @@
}
},
{
"ordinal": 10,
"ordinal": 11,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
@@ -127,9 +137,10 @@
false,
true,
true,
true,
false,
false
]
},
"hash": "31d85cc0013f29e6db2d272ee6e709cca79b46496a2c222960f1a1419175f00b"
"hash": "38a1d7b676bb0987fc191bbc8bdeadf6174a19358dff40d9772b9d5824145bbc"
}
@@ -1,6 +1,6 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n\n jobs.status as `status: enums::common::job_status_plus::JobStatusPlus`,\n \n jobs.maybe_external_third_party as `external_third_party: enums::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty`,\n jobs.maybe_external_third_party_id as `external_third_party_id`,\n\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n \n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_debug_log_event_token as `maybe_debug_log_event_token: tokens::tokens::non_unique::debug_logs_event_token::DebugLogEventToken`,\n\n jobs.created_at,\n jobs.updated_at\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\nAND jobs.maybe_external_third_party_id = ?\n ",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n\n jobs.status as `status: enums::common::job_status_plus::JobStatusPlus`,\n \n jobs.maybe_external_third_party as `external_third_party: enums::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty`,\n jobs.maybe_external_third_party_id as `external_third_party_id`,\n\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n \n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_debug_log_event_token as `maybe_debug_log_event_token: tokens::tokens::non_unique::debug_logs_event_token::DebugLogEventToken`,\n\n jobs.platform_type as `maybe_platform_type: enums::common::platform_type::PlatformType`,\n\n jobs.created_at,\n jobs.updated_at\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\nAND jobs.maybe_external_third_party_id = ?\n ",
"describe": {
"columns": [
{
@@ -95,6 +95,16 @@
},
{
"ordinal": 9,
"name": "maybe_platform_type: enums::common::platform_type::PlatformType",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 10,
"name": "created_at",
"type_info": {
"type": "Timestamp",
@@ -104,7 +114,7 @@
}
},
{
"ordinal": 10,
"ordinal": 11,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
@@ -127,9 +137,10 @@
false,
true,
true,
true,
false,
false
]
},
"hash": "2c98621c08055374fd09502c94ac40bb01d23fcea3f844cceea7446a5c0cb4dc"
"hash": "3a846909a725eb776b4a4637dc64dcaf1ed70ad8891f9d012c7f3cdcb16a613e"
}
@@ -40,7 +40,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -50,7 +50,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -0,0 +1,36 @@
{
"db_name": "MySQL",
"query": "\nSELECT DISTINCT\n subscription_namespace as `subscription_namespace: enums::common::payments_namespace::PaymentsNamespace`,\n maybe_stripe_customer_id as `stripe_customer_id!`\n\nFROM user_subscriptions\n\nWHERE\n user_token = ?\n AND maybe_stripe_customer_id IS NOT NULL\n AND deleted_at IS NULL\nORDER BY subscription_namespace ASC, maybe_stripe_customer_id ASC\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "subscription_namespace: enums::common::payments_namespace::PaymentsNamespace",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "stripe_customer_id!",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 1020
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
true
]
},
"hash": "516db34b6a642a2f7d7107f186905a79ad694c3c86f3078efc77bcaae7f39f3d"
}
@@ -180,7 +180,7 @@
"type": "LongLong",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 20
}
},
{
@@ -0,0 +1,58 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n maybe_creator_user_token as `maybe_creator_user_token: UserToken`,\n media_class as `media_class: MediaFileClass`,\n media_type as `media_type: MediaFileType`,\n maybe_cover_image_media_file_token as `maybe_cover_image_media_file_token: MediaFileToken`\nFROM media_files\nWHERE token = ?\n AND user_deleted_at IS NULL\n AND mod_deleted_at IS NULL\nLIMIT 1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "maybe_creator_user_token: UserToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "media_class: MediaFileClass",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 2,
"name": "media_type: MediaFileType",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 3,
"name": "maybe_cover_image_media_file_token: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false,
false,
true
]
},
"hash": "5606a694c872d868ab3b35f4b3685f86f2b27ad16e741c8b1bf997b613f1b803"
}
@@ -0,0 +1,157 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n uec.id as `id: u64`,\n uec.old_email,\n uec.new_email,\n uec.ip_address,\n uec.created_at,\n\n u_subject.token as `user_token: tokens::tokens::users::UserToken`,\n u_subject.username as user_username,\n u_subject.display_name as user_display_name,\n u_subject.email_gravatar_hash as user_gravatar_hash,\n\n u_changer.token as `maybe_changed_by_user_token?: tokens::tokens::users::UserToken`,\n u_changer.username as `maybe_changed_by_user_username?`,\n u_changer.display_name as `maybe_changed_by_user_display_name?`,\n u_changer.email_gravatar_hash as `maybe_changed_by_user_gravatar_hash?`\n\nFROM user_email_changes AS uec\nJOIN users AS u_subject\n ON uec.user_token = u_subject.token\nLEFT JOIN users AS u_changer\n ON uec.maybe_changed_by_user_token = u_changer.token\nWHERE uec.user_token = ?\n AND uec.id < ?\nORDER BY uec.id DESC\nLIMIT ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "old_email",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 2,
"name": "new_email",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 3,
"name": "ip_address",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 160
}
},
{
"ordinal": 4,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 5,
"name": "user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "user_username",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 7,
"name": "user_display_name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 8,
"name": "user_gravatar_hash",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 9,
"name": "maybe_changed_by_user_token?: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_changed_by_user_username?",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 11,
"name": "maybe_changed_by_user_display_name?",
"type_info": {
"type": "VarString",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 12,
"name": "maybe_changed_by_user_gravatar_hash?",
"type_info": {
"type": "String",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
}
],
"parameters": {
"Right": 3
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true
]
},
"hash": "5611678b6c168208ea4da9ef0e3071758c9bb8d89b54e2d3f0fc84bd0a6c915f"
}
@@ -30,7 +30,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 3
"max_size": 11
}
},
{
@@ -190,7 +190,7 @@
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -30,7 +30,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 3
"max_size": 11
}
}
],
@@ -1,12 +1,12 @@
{
"db_name": "MySQL",
"query": "\nINSERT INTO generic_inference_jobs\nSET\n token = ?,\n uuid_idempotency_token = ?,\n\n job_type = ?,\n\n maybe_external_third_party = ?,\n maybe_external_third_party_id = ?,\n\n product_category = ?,\n inference_category = ?,\n\n maybe_model_type = ?,\n maybe_model_token = ?,\n\n maybe_input_source_token = ?,\n maybe_input_source_token_type = ?,\n\n maybe_download_url = ?,\n maybe_cover_image_media_file_token = ?,\n\n maybe_prompt_token = ?,\n maybe_wallet_ledger_entry_token = ?,\n\n maybe_raw_inference_text = ?,\n\n maybe_inference_args = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n creator_set_visibility = ?,\n\n priority_level = ?,\n is_keepalive_required = ?,\n max_duration_seconds = ?,\n is_debug_request = ?,\n\n maybe_routing_tag = ?,\n\n maybe_debug_log_event_token = ?,\n\n frontend_failure_category = ?,\n failure_reason = ?,\n\n status = ?\n ",
"query": "\nINSERT INTO generic_inference_jobs\nSET\n token = ?,\n uuid_idempotency_token = ?,\n\n job_type = ?,\n\n maybe_external_third_party = ?,\n maybe_external_third_party_id = ?,\n\n product_category = ?,\n inference_category = ?,\n\n maybe_model_type = ?,\n maybe_model_token = ?,\n\n maybe_input_source_token = ?,\n maybe_input_source_token_type = ?,\n\n maybe_download_url = ?,\n maybe_cover_image_media_file_token = ?,\n\n maybe_prompt_token = ?,\n maybe_wallet_ledger_entry_token = ?,\n\n maybe_raw_inference_text = ?,\n\n maybe_inference_args = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n creator_set_visibility = ?,\n\n platform_type = ?,\n\n maybe_external_third_party_cost_credits = ?,\n maybe_external_third_party_cost_usd_cents = ?,\n maybe_system_cost_credits = ?,\n maybe_system_cost_usd_cents = ?,\n\n priority_level = ?,\n is_keepalive_required = ?,\n max_duration_seconds = ?,\n is_debug_request = ?,\n\n maybe_routing_tag = ?,\n\n maybe_debug_log_event_token = ?,\n\n frontend_failure_category = ?,\n failure_reason = ?,\n\n status = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 30
"Right": 35
},
"nullable": []
},
"hash": "161febbb30cf6c669a813fe036d405ef428422297440abd240482a6aae51f6f9"
"hash": "5c67c3dd7f8bb6771c6b058a8cf6ffcc66b2be2bea41bd988070713173982dab"
}
@@ -1,6 +1,6 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n jobs.maybe_external_third_party_id as `operation_id`,\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n jobs.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_wallet_ledger_entry_token as `maybe_wallet_ledger_entry_token: tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken`\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\n AND jobs.status NOT IN ('complete_success', 'complete_failure')\n AND jobs.maybe_external_third_party_id IS NOT NULL\n\nLIMIT 25000\n ",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n jobs.maybe_external_third_party_id as `operation_id`,\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n jobs.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_wallet_ledger_entry_token as `maybe_wallet_ledger_entry_token: tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken`,\n jobs.platform_type as `maybe_platform_type: enums::common::platform_type::PlatformType`\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\n AND jobs.status NOT IN ('complete_success', 'complete_failure')\n AND jobs.maybe_external_third_party_id IS NOT NULL\n\nLIMIT 25000\n ",
"describe": {
"columns": [
{
@@ -82,6 +82,16 @@
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_platform_type: enums::common::platform_type::PlatformType",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
}
],
"parameters": {
@@ -95,8 +105,9 @@
false,
false,
true,
true,
true
]
},
"hash": "d56a26a7300495fac9741e77e390f16402e2273dbab9a15d7c17eb1f0da7a1b1"
"hash": "5f24aeb12e5a78ffedd1c772c594b668188aaaf01f315a1c41c75610fdfc1b32"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE folders\nSET maybe_color_code = ?\nWHERE token = ?\n AND owner_user_token = ?\n AND maybe_deleted_at IS NULL\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "6a0e3f012795068a56a0dfaf567d066dc157bb06c736c1c4314b18c8e0356127"
}
@@ -160,7 +160,7 @@
"type": "LongLong",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 20
}
},
{
@@ -60,7 +60,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -70,7 +70,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -0,0 +1,25 @@
{
"db_name": "MySQL",
"query": "\nWITH RECURSIVE ancestor_chain (token, parent_token, depth) AS (\n SELECT token, maybe_parent_folder_token, 0\n FROM folders\n WHERE token = ?\n AND owner_user_token = ?\n AND maybe_deleted_at IS NULL\n UNION ALL\n SELECT f.token, f.maybe_parent_folder_token, ac.depth + 1\n FROM folders f\n INNER JOIN ancestor_chain ac\n ON f.token = ac.parent_token\n WHERE f.owner_user_token = ?\n AND f.maybe_deleted_at IS NULL\n AND ac.depth < ?\n)\nSELECT token as `token!: FolderToken`\nFROM ancestor_chain\nWHERE depth > 0\nORDER BY depth ASC\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "token!: FolderToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
}
],
"parameters": {
"Right": 4
},
"nullable": [
true
]
},
"hash": "780891e8294b78cc0e5a05a8b5a8949a763bcb8c5d6526a621234020b154bdc9"
}
@@ -150,7 +150,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 3
"max_size": 11
}
},
{
@@ -160,7 +160,7 @@
"type": "LongLong",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 20
}
},
{
@@ -0,0 +1,267 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n mf.id as `media_file_id: u64`,\n fmf.created_at as `added_to_folder_at: DateTime<Utc>`,\n\n mf.token as `media_file_token: MediaFileToken`,\n mf.media_class as `media_class: MediaFileClass`,\n mf.media_type as `media_type: MediaFileType`,\n\n mf.maybe_batch_token as `maybe_batch_token: BatchGenerationToken`,\n\n mf.public_bucket_directory_hash,\n mf.maybe_public_bucket_prefix,\n mf.maybe_public_bucket_extension,\n\n cover.public_bucket_directory_hash as `maybe_cover_public_bucket_directory_hash?`,\n cover.maybe_public_bucket_prefix as `maybe_cover_public_bucket_prefix?`,\n cover.maybe_public_bucket_extension as `maybe_cover_public_bucket_extension?`,\n\n mf.creator_set_visibility as `creator_set_visibility: Visibility`,\n mf.is_user_upload as `is_user_upload: bool`,\n mf.is_intermediate_system_file as `is_intermediate_system_file: bool`,\n\n mf.maybe_title,\n mf.maybe_prompt_token as `maybe_prompt_token: PromptToken`,\n mf.maybe_origin_filename,\n\n mf.maybe_duration_millis,\n mf.maybe_frame_width,\n mf.maybe_frame_height,\n\n mf.created_at,\n mf.updated_at\nFROM folder_media_files fmf\nJOIN media_files mf\n ON mf.token = fmf.media_file_token\nLEFT JOIN media_files cover\n ON cover.token = mf.maybe_cover_image_media_file_token\nWHERE fmf.folder_token = ?\n AND mf.user_deleted_at IS NULL\n AND mf.mod_deleted_at IS NULL\nORDER BY mf.id DESC\nLIMIT ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "media_file_id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "added_to_folder_at: DateTime<Utc>",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 2,
"name": "media_file_token: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 3,
"name": "media_class: MediaFileClass",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 4,
"name": "media_type: MediaFileType",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 5,
"name": "maybe_batch_token: BatchGenerationToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "public_bucket_directory_hash",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_public_bucket_prefix",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 8,
"name": "maybe_public_bucket_extension",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 9,
"name": "maybe_cover_public_bucket_directory_hash?",
"type_info": {
"type": "VarString",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_cover_public_bucket_prefix?",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 11,
"name": "maybe_cover_public_bucket_extension?",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 12,
"name": "creator_set_visibility: Visibility",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 28
}
},
{
"ordinal": 13,
"name": "is_user_upload: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL | MULTIPLE_KEY",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 14,
"name": "is_intermediate_system_file: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL | MULTIPLE_KEY",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 15,
"name": "maybe_title",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 16,
"name": "maybe_prompt_token: PromptToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 17,
"name": "maybe_origin_filename",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 18,
"name": "maybe_duration_millis",
"type_info": {
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 19,
"name": "maybe_frame_width",
"type_info": {
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 20,
"name": "maybe_frame_height",
"type_info": {
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 21,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 22,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
false,
false,
false,
true,
true,
true,
true,
true,
true,
false,
false
]
},
"hash": "8aca9bc976b980ea1a3b3052bc8a45dd4d8db55c20fd1aede2a4415cc1395cf3"
}
@@ -160,7 +160,7 @@
"type": "LongLong",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 20
}
},
{
@@ -50,7 +50,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -60,7 +60,7 @@
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -140,7 +140,7 @@
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -150,7 +150,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 3
"max_size": 11
}
},
{
@@ -0,0 +1,168 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n f.id as `id: u64`,\n f.token as `token: FolderToken`,\n f.name,\n f.owner_user_token as `owner_user_token: UserToken`,\n f.maybe_parent_folder_token as `maybe_parent_folder_token: FolderToken`,\n f.maybe_last_media_file_token_1 as `maybe_last_media_file_token_1: MediaFileToken`,\n f.maybe_last_media_file_token_2 as `maybe_last_media_file_token_2: MediaFileToken`,\n f.maybe_last_media_file_token_3 as `maybe_last_media_file_token_3: MediaFileToken`,\n f.maybe_last_media_file_token_4 as `maybe_last_media_file_token_4: MediaFileToken`,\n f.maybe_cover_image_custom_media_token as `maybe_cover_image_custom_media_token: MediaFileToken`,\n f.maybe_color_code,\n f.has_star as `has_star: bool`,\n f.created_at,\n f.updated_at\nFROM folders f\nWHERE f.maybe_parent_folder_token = ?\n AND f.owner_user_token = ?\n AND f.maybe_deleted_at IS NULL\nORDER BY f.id DESC\nLIMIT ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 2,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 3,
"name": "owner_user_token: UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_parent_folder_token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "maybe_last_media_file_token_1: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "maybe_last_media_file_token_2: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_last_media_file_token_3: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_last_media_file_token_4: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 9,
"name": "maybe_cover_image_custom_media_token: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_color_code",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 11,
"name": "has_star: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 12,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 13,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 3
},
"nullable": [
false,
false,
false,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false
]
},
"hash": "a13680fb2b54809b6d9d9356f8eec87cd0f1f37405b84bbf734ed06cc244efb1"
}
@@ -30,7 +30,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 3
"max_size": 11
}
},
{
@@ -160,7 +160,7 @@
"type": "LongLong",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 20
}
},
{
@@ -270,7 +270,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -1,12 +1,12 @@
{
"db_name": "MySQL",
"query": "\n INSERT INTO media_files\n SET\n token = ?,\n\n media_class = ?,\n media_type = ?,\n\n is_user_upload = ?,\n is_intermediate_system_file = ?,\n\n origin_category = ?, \n origin_product_category = ?, \n maybe_origin_model_type = ?, \n maybe_origin_model_token = ?, \n maybe_origin_filename = ?,\n\n is_batch_generated = ?,\n maybe_batch_token = ?,\n\n maybe_mime_type = ?,\n file_size_bytes = ?,\n maybe_duration_millis = ?,\n maybe_audio_encoding = ?, \n maybe_video_encoding = ?, \n maybe_frame_width = ?, \n maybe_frame_height = ?,\n maybe_prompt_token = ?,\n checksum_sha2 = ?,\n \n maybe_engine_category = ?,\n\n maybe_title = ?,\n maybe_text_transcript = ?,\n\n maybe_scene_source_media_file_token = ?,\n\n public_bucket_directory_hash = ?, \n maybe_public_bucket_prefix = ?, \n maybe_public_bucket_extension = ?, \n\n maybe_creator_user_token = ?, \n maybe_creator_anonymous_visitor_token = ?, \n\n creator_ip_address = ?, \n creator_set_visibility = ?, \n\n maybe_creator_file_synthetic_id = ?, \n maybe_creator_category_synthetic_id = ?,\n\n extra_file_modification_info = ?,\n\n maybe_generation_provider = ?,\n\n maybe_cover_image_media_file_token = ?,\n\n maybe_mod_user_token = ?,\n is_generated_on_prem = ?,\n generated_by_worker = ?,\n generated_by_cluster = ?\n ",
"query": "\n INSERT INTO media_files\n SET\n token = ?,\n\n media_class = ?,\n media_type = ?,\n\n is_user_upload = ?,\n is_intermediate_system_file = ?,\n\n origin_category = ?, \n origin_product_category = ?, \n maybe_origin_model_type = ?, \n maybe_origin_model_token = ?, \n maybe_origin_filename = ?,\n\n is_batch_generated = ?,\n maybe_batch_token = ?,\n\n maybe_mime_type = ?,\n file_size_bytes = ?,\n maybe_duration_millis = ?,\n maybe_audio_encoding = ?, \n maybe_video_encoding = ?, \n maybe_frame_width = ?, \n maybe_frame_height = ?,\n maybe_prompt_token = ?,\n checksum_sha2 = ?,\n \n maybe_engine_category = ?,\n\n maybe_title = ?,\n maybe_text_transcript = ?,\n\n maybe_scene_source_media_file_token = ?,\n\n public_bucket_directory_hash = ?, \n maybe_public_bucket_prefix = ?, \n maybe_public_bucket_extension = ?, \n\n maybe_creator_user_token = ?, \n maybe_creator_anonymous_visitor_token = ?, \n\n creator_ip_address = ?, \n creator_set_visibility = ?, \n\n maybe_creator_file_synthetic_id = ?, \n maybe_creator_category_synthetic_id = ?,\n\n extra_file_modification_info = ?,\n\n maybe_generation_provider = ?,\n\n platform_type = ?,\n\n maybe_cover_image_media_file_token = ?,\n\n maybe_mod_user_token = ?,\n is_generated_on_prem = ?,\n generated_by_worker = ?,\n generated_by_cluster = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 41
"Right": 42
},
"nullable": []
},
"hash": "a4901f904aa1c00d9afc23faa7008816c6e1b653bd6ad9f0b6772e32000be544"
"hash": "ad2ffbd9f48e52678a5c61817bec043bf1df4033463e5c5a18468c04af391e6a"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE folders\nSET\n maybe_last_media_file_token_1 = (\n SELECT mf.token\n FROM folder_media_files fmf\n JOIN media_files mf\n ON mf.token = fmf.media_file_token\n WHERE fmf.folder_token = ?\n AND mf.user_deleted_at IS NULL\n AND mf.mod_deleted_at IS NULL\n ORDER BY fmf.id DESC\n LIMIT 1 OFFSET 0\n ),\n maybe_last_media_file_token_2 = (\n SELECT mf.token\n FROM folder_media_files fmf\n JOIN media_files mf\n ON mf.token = fmf.media_file_token\n WHERE fmf.folder_token = ?\n AND mf.user_deleted_at IS NULL\n AND mf.mod_deleted_at IS NULL\n ORDER BY fmf.id DESC\n LIMIT 1 OFFSET 1\n ),\n maybe_last_media_file_token_3 = (\n SELECT mf.token\n FROM folder_media_files fmf\n JOIN media_files mf\n ON mf.token = fmf.media_file_token\n WHERE fmf.folder_token = ?\n AND mf.user_deleted_at IS NULL\n AND mf.mod_deleted_at IS NULL\n ORDER BY fmf.id DESC\n LIMIT 1 OFFSET 2\n ),\n maybe_last_media_file_token_4 = (\n SELECT mf.token\n FROM folder_media_files fmf\n JOIN media_files mf\n ON mf.token = fmf.media_file_token\n WHERE fmf.folder_token = ?\n AND mf.user_deleted_at IS NULL\n AND mf.mod_deleted_at IS NULL\n ORDER BY fmf.id DESC\n LIMIT 1 OFFSET 3\n )\nWHERE token = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 5
},
"nullable": []
},
"hash": "ae417955113b385031181772b29f234ab9297cf583583f74fe287bf9c24b1e6a"
}
@@ -160,7 +160,7 @@
"type": "LongLong",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 20
}
},
{
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nINSERT INTO folders\nSET\n token = ?,\n name = ?,\n owner_user_token = ?,\n maybe_parent_folder_token = ?,\n maybe_color_code = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 5
},
"nullable": []
},
"hash": "c099b274026619760f0982f0e5082da1e8de16c26122f2750667b9cdc2c4abf3"
}
@@ -0,0 +1,267 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n mf.id as `media_file_id: u64`,\n fmf.created_at as `added_to_folder_at: DateTime<Utc>`,\n\n mf.token as `media_file_token: MediaFileToken`,\n mf.media_class as `media_class: MediaFileClass`,\n mf.media_type as `media_type: MediaFileType`,\n\n mf.maybe_batch_token as `maybe_batch_token: BatchGenerationToken`,\n\n mf.public_bucket_directory_hash,\n mf.maybe_public_bucket_prefix,\n mf.maybe_public_bucket_extension,\n\n cover.public_bucket_directory_hash as `maybe_cover_public_bucket_directory_hash?`,\n cover.maybe_public_bucket_prefix as `maybe_cover_public_bucket_prefix?`,\n cover.maybe_public_bucket_extension as `maybe_cover_public_bucket_extension?`,\n\n mf.creator_set_visibility as `creator_set_visibility: Visibility`,\n mf.is_user_upload as `is_user_upload: bool`,\n mf.is_intermediate_system_file as `is_intermediate_system_file: bool`,\n\n mf.maybe_title,\n mf.maybe_prompt_token as `maybe_prompt_token: PromptToken`,\n mf.maybe_origin_filename,\n\n mf.maybe_duration_millis,\n mf.maybe_frame_width,\n mf.maybe_frame_height,\n\n mf.created_at,\n mf.updated_at\nFROM folder_media_files fmf\nJOIN media_files mf\n ON mf.token = fmf.media_file_token\nLEFT JOIN media_files cover\n ON cover.token = mf.maybe_cover_image_media_file_token\nWHERE fmf.folder_token = ?\n AND mf.user_deleted_at IS NULL\n AND mf.mod_deleted_at IS NULL\n AND mf.id < ?\nORDER BY mf.id DESC\nLIMIT ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "media_file_id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "added_to_folder_at: DateTime<Utc>",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 2,
"name": "media_file_token: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 3,
"name": "media_class: MediaFileClass",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 4,
"name": "media_type: MediaFileType",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 5,
"name": "maybe_batch_token: BatchGenerationToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "public_bucket_directory_hash",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_public_bucket_prefix",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 8,
"name": "maybe_public_bucket_extension",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 9,
"name": "maybe_cover_public_bucket_directory_hash?",
"type_info": {
"type": "VarString",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_cover_public_bucket_prefix?",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 11,
"name": "maybe_cover_public_bucket_extension?",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 12,
"name": "creator_set_visibility: Visibility",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 28
}
},
{
"ordinal": 13,
"name": "is_user_upload: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL | MULTIPLE_KEY",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 14,
"name": "is_intermediate_system_file: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL | MULTIPLE_KEY",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 15,
"name": "maybe_title",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 16,
"name": "maybe_prompt_token: PromptToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 17,
"name": "maybe_origin_filename",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 18,
"name": "maybe_duration_millis",
"type_info": {
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 19,
"name": "maybe_frame_width",
"type_info": {
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 20,
"name": "maybe_frame_height",
"type_info": {
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 11
}
},
{
"ordinal": 21,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 22,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 3
},
"nullable": [
false,
false,
false,
false,
false,
true,
false,
true,
true,
true,
true,
true,
false,
false,
false,
true,
true,
true,
true,
true,
true,
false,
false
]
},
"hash": "c0ba9f9aa3184b1cb3d714173b31e530e201a6c24afd29ad534cf7f3954c7316"
}
@@ -150,7 +150,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 3
"max_size": 11
}
},
{
@@ -0,0 +1,157 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n uec.id as `id: u64`,\n uec.old_email,\n uec.new_email,\n uec.ip_address,\n uec.created_at,\n\n u_subject.token as `user_token: tokens::tokens::users::UserToken`,\n u_subject.username as user_username,\n u_subject.display_name as user_display_name,\n u_subject.email_gravatar_hash as user_gravatar_hash,\n\n u_changer.token as `maybe_changed_by_user_token?: tokens::tokens::users::UserToken`,\n u_changer.username as `maybe_changed_by_user_username?`,\n u_changer.display_name as `maybe_changed_by_user_display_name?`,\n u_changer.email_gravatar_hash as `maybe_changed_by_user_gravatar_hash?`\n\nFROM user_email_changes AS uec\nJOIN users AS u_subject\n ON uec.user_token = u_subject.token\nLEFT JOIN users AS u_changer\n ON uec.maybe_changed_by_user_token = u_changer.token\nWHERE uec.user_token = ?\nORDER BY uec.id DESC\nLIMIT ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "old_email",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 2,
"name": "new_email",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 3,
"name": "ip_address",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 160
}
},
{
"ordinal": 4,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 5,
"name": "user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "user_username",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 7,
"name": "user_display_name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 8,
"name": "user_gravatar_hash",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 9,
"name": "maybe_changed_by_user_token?: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_changed_by_user_username?",
"type_info": {
"type": "VarString",
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 11,
"name": "maybe_changed_by_user_display_name?",
"type_info": {
"type": "VarString",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 80
}
},
{
"ordinal": 12,
"name": "maybe_changed_by_user_gravatar_hash?",
"type_info": {
"type": "String",
"flags": "BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true
]
},
"hash": "c17e1d6b567dd378bb4cb0478fb9558e907a0f36498bd049c7c526e496e89259"
}
@@ -180,7 +180,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -190,7 +190,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -140,7 +140,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -0,0 +1,179 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n f.id as `id: u64`,\n f.token as `token: FolderToken`,\n f.name,\n f.owner_user_token as `owner_user_token: UserToken`,\n f.maybe_parent_folder_token as `maybe_parent_folder_token: FolderToken`,\n f.maybe_last_media_file_token_1 as `maybe_last_media_file_token_1: MediaFileToken`,\n f.maybe_last_media_file_token_2 as `maybe_last_media_file_token_2: MediaFileToken`,\n f.maybe_last_media_file_token_3 as `maybe_last_media_file_token_3: MediaFileToken`,\n f.maybe_last_media_file_token_4 as `maybe_last_media_file_token_4: MediaFileToken`,\n f.maybe_cover_image_custom_media_token as `maybe_cover_image_custom_media_token: MediaFileToken`,\n f.maybe_color_code,\n f.has_star as `has_star: bool`,\n f.created_at,\n f.updated_at,\n (\n f.maybe_parent_folder_token IS NOT NULL\n AND (p.token IS NULL OR p.maybe_deleted_at IS NOT NULL)\n ) as `is_orphaned: bool`\nFROM folders f\nLEFT JOIN folders p\n ON p.token = f.maybe_parent_folder_token\nWHERE f.owner_user_token = ?\n AND f.maybe_deleted_at IS NULL\n AND f.id < ?\nORDER BY f.id DESC\nLIMIT ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 2,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 3,
"name": "owner_user_token: UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_parent_folder_token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "maybe_last_media_file_token_1: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "maybe_last_media_file_token_2: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_last_media_file_token_3: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_last_media_file_token_4: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 9,
"name": "maybe_cover_image_custom_media_token: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_color_code",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 11,
"name": "has_star: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 12,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 13,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 14,
"name": "is_orphaned: bool",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | BINARY",
"char_set": 63,
"max_size": 1
}
}
],
"parameters": {
"Right": 3
},
"nullable": [
false,
false,
false,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false,
false
]
},
"hash": "d6f0c65abce2da20fe86805ff053b8c2569bf0095f6245a5529f0c71854a604b"
}
@@ -0,0 +1,168 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n f.id as `id: u64`,\n f.token as `token: FolderToken`,\n f.name,\n f.owner_user_token as `owner_user_token: UserToken`,\n f.maybe_parent_folder_token as `maybe_parent_folder_token: FolderToken`,\n f.maybe_last_media_file_token_1 as `maybe_last_media_file_token_1: MediaFileToken`,\n f.maybe_last_media_file_token_2 as `maybe_last_media_file_token_2: MediaFileToken`,\n f.maybe_last_media_file_token_3 as `maybe_last_media_file_token_3: MediaFileToken`,\n f.maybe_last_media_file_token_4 as `maybe_last_media_file_token_4: MediaFileToken`,\n f.maybe_cover_image_custom_media_token as `maybe_cover_image_custom_media_token: MediaFileToken`,\n f.maybe_color_code,\n f.has_star as `has_star: bool`,\n f.created_at,\n f.updated_at\nFROM folders f\nWHERE f.maybe_parent_folder_token = ?\n AND f.owner_user_token = ?\n AND f.maybe_deleted_at IS NULL\n AND f.id < ?\nORDER BY f.id DESC\nLIMIT ?\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id: u64",
"type_info": {
"type": "LongLong",
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
"char_set": 63,
"max_size": 20
}
},
{
"ordinal": 1,
"name": "token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 2,
"name": "name",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
},
{
"ordinal": 3,
"name": "owner_user_token: UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "maybe_parent_folder_token: FolderToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 5,
"name": "maybe_last_media_file_token_1: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 6,
"name": "maybe_last_media_file_token_2: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_last_media_file_token_3: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_last_media_file_token_4: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 9,
"name": "maybe_cover_image_custom_media_token: MediaFileToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 10,
"name": "maybe_color_code",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
},
{
"ordinal": 11,
"name": "has_star: bool",
"type_info": {
"type": "Tiny",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 1
}
},
{
"ordinal": 12,
"name": "created_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
"char_set": 63,
"max_size": 19
}
},
{
"ordinal": 13,
"name": "updated_at",
"type_info": {
"type": "Timestamp",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP | ON_UPDATE_NOW",
"char_set": 63,
"max_size": 19
}
}
],
"parameters": {
"Right": 4
},
"nullable": [
false,
false,
false,
false,
true,
true,
true,
true,
true,
true,
true,
false,
false,
false
]
},
"hash": "d85c1a844f14b9416c6260d7a906fec709b50eb4583b98dffb52ebbe6abcb7d5"
}
@@ -180,7 +180,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -190,7 +190,7 @@
"type": "Long",
"flags": "NOT_NULL",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -1,6 +1,6 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n jobs.maybe_external_third_party_id as `order_id`,\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n jobs.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_wallet_ledger_entry_token as `maybe_wallet_ledger_entry_token: tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken`\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\n AND jobs.job_type = ?\n AND jobs.status NOT IN ('complete_success', 'complete_failure')\n AND jobs.maybe_external_third_party_id IS NOT NULL\n\nLIMIT 25000\n ",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n jobs.maybe_external_third_party_id as `order_id`,\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n jobs.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_wallet_ledger_entry_token as `maybe_wallet_ledger_entry_token: tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken`,\n jobs.platform_type as `maybe_platform_type: enums::common::platform_type::PlatformType`\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\n AND jobs.job_type = ?\n AND jobs.status NOT IN ('complete_success', 'complete_failure')\n AND jobs.maybe_external_third_party_id IS NOT NULL\n\nLIMIT 25000\n ",
"describe": {
"columns": [
{
@@ -82,6 +82,16 @@
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 8,
"name": "maybe_platform_type: enums::common::platform_type::PlatformType",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 64
}
}
],
"parameters": {
@@ -95,8 +105,9 @@
false,
false,
true,
true,
true
]
},
"hash": "a0002183d4d077b07bb0cd062ca95bf113d1564ce3195f0e62e531ce4297dd76"
"hash": "ddbbd3886c00268edd3993508f635549fc8ddc877bb059fd58f14b8c07586fc9"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE folders\nSET name = ?\nWHERE token = ?\n AND owner_user_token = ?\n AND maybe_deleted_at IS NULL\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "e32e195ef41bc833e5b7fc53cfde8669f88aeb66d279e5213d047f4860ec86ab"
}
@@ -190,7 +190,7 @@
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -140,7 +140,7 @@
"type": "Long",
"flags": "",
"char_set": 63,
"max_size": 10
"max_size": 11
}
},
{
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\nUPDATE folders\nSET maybe_deleted_at = NOW()\nWHERE token = ?\n AND owner_user_token = ?\n AND maybe_deleted_at IS NULL\nLIMIT 1\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "f9e3ff8ca682948076b799d6b2d934be4a87a4e04665d6f12cc32095494129ad"
}
@@ -0,0 +1,47 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n user_token as `user_token: tokens::tokens::users::UserToken`,\n payments_namespace as `payments_namespace: enums::common::payments_namespace::PaymentsNamespace`,\n stripe_customer_id\n\nFROM user_stripe_customer_links\n\nWHERE user_token = ?\nORDER BY id ASC\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "payments_namespace: enums::common::payments_namespace::PaymentsNamespace",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 2,
"name": "stripe_customer_id",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 1020
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false
]
},
"hash": "ffb5717340f21f21693bfcade201bc055fb3fb8a26da8d0574e3de44b033586c"
}
Generated
+635 -721
View File
File diff suppressed because it is too large Load Diff
+12 -13
View File
@@ -10,6 +10,7 @@ members = [
"crates/api_clients/artcraft/artcraft_client",
"crates/api_clients/artcraft/artcraft_router",
"crates/api_clients/cloud_storage",
"crates/api_clients/comet_api_client",
"crates/api_clients/datadog_client",
"crates/api_clients/fal_client",
"crates/api_clients/google_drive_downloader",
@@ -294,16 +295,14 @@ worldlabs_consumer_client = { path = "crates/api_clients/worldlabs_consumer_clie
# External libs
# Centrally pinned versions so that we can uniformly upgrade/downgrade versions across the workspace
# If a crate needs to use an older/newer version, the dependency should be managed in that crate's own Cargo.toml
actix = "0.13.5"
actix-cors = "0.6.4" # TODO(bt): Carefully upgrade this. CORS broke last time.
actix-http = "3.7.0"
actix-multipart = "0.6.2"
actix-rt = "2.10.0"
actix-cors = "0.7.1"
actix-http = "3.12.1"
actix-multipart = "0.7.2"
actix-rt = "2.11.0"
actix-service = "2.0.3"
actix-utils = "3.0.1"
actix-web = "4.7.0" # TODO(bt): We're behind and need to bump versions.
actix-web-actors = "4.3.1+deprecated"
actix-web-lab = "0.20.2"
actix-web = "4.13.0"
actix-web-lab = "0.26.0"
anyhow = "1.0.102"
assertor = "0.0.3"
base64 = "0.22.1"
@@ -343,11 +342,11 @@ sha2 = "0.11.0-rc.5"
sha3 = "0.10.8"
speculoos = "0.11.0"
strum = { version = "0.28.0", features = ["derive"] }
tauri = { version = "2.8.3", features = ["unstable", "devtools", "protocol-asset"] } # NB: "devtools" prevents App Store distribution; "ubstable" is needed for window access
tauri-plugin-dialog = "2.3.3"
tauri-plugin-fs = "2.4.2"
tauri-plugin-log = "2.6.0"
tauri-plugin-upload = "2.3.1"
tauri = { version = "2.11.2", features = ["unstable", "devtools", "protocol-asset"] } # NB: "devtools" prevents App Store distribution; "ubstable" is needed for window access
tauri-plugin-dialog = "2.7.1"
tauri-plugin-fs = "2.5.1"
tauri-plugin-log = "2.8.0"
tauri-plugin-upload = "2.4.0"
tempdir = "0.3.7"
tempfile = "3.27.0"
thiserror = "2.0.18"
@@ -0,0 +1,5 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
DROP TABLE IF EXISTS user_email_changes;
@@ -0,0 +1,35 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
CREATE TABLE user_email_changes (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-- The user whose email was changed.
user_token VARCHAR(32) NOT NULL,
-- The email address before the change.
old_email VARCHAR(255) NOT NULL,
-- The email address after the change.
new_email VARCHAR(255) NOT NULL,
-- The IP address the change was made from.
-- Wide enough for IPv4/6.
ip_address VARCHAR(40) NOT NULL,
-- The user that performed the change, if known. NULL when the change was
-- performed by the user themselves, by an automated process, or in any
-- other context where there is no acting user.
maybe_changed_by_user_token VARCHAR(32) DEFAULT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- INDICES --
PRIMARY KEY (id),
KEY index_user_token (user_token),
KEY index_old_email (old_email),
KEY index_new_email (new_email),
KEY index_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
@@ -0,0 +1,5 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
DROP TABLE IF EXISTS folders;
@@ -0,0 +1,56 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
CREATE TABLE folders (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-- Effective "primary key" (PUBLIC, used by the API).
token VARCHAR(32) NOT NULL,
-- User-supplied folder name.
name VARCHAR(255) NOT NULL,
-- The user that owns this folder.
owner_user_token VARCHAR(32) NOT NULL,
-- Parent folder for nesting, NULL for top-level folders.
maybe_parent_folder_token VARCHAR(32) DEFAULT NULL,
-- The last four media files added to the folder, in order. These are
-- denormalized for cheap thumbnail-grid rendering on folder cards
-- without a separate fan-out query.
maybe_last_media_file_token_1 VARCHAR(32) DEFAULT NULL,
maybe_last_media_file_token_2 VARCHAR(32) DEFAULT NULL,
maybe_last_media_file_token_3 VARCHAR(32) DEFAULT NULL,
maybe_last_media_file_token_4 VARCHAR(32) DEFAULT NULL,
-- Optional user-chosen cover image (a media file). Overrides the
-- auto-grid thumbnail derived from the last-N media files above.
maybe_cover_image_custom_media_token VARCHAR(32) DEFAULT NULL,
-- Optional user-chosen color tag. Wide enough for "#RRGGBBAA" plus a
-- short named-color fallback.
maybe_color_code VARCHAR(16) DEFAULT NULL,
-- Whether the user has starred / favorited this folder.
has_star BOOLEAN NOT NULL DEFAULT FALSE,
-- ========== TIMESTAMPS ==========
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- Soft-delete timestamp. NULL means the folder is live.
maybe_deleted_at TIMESTAMP NULL,
-- INDICES --
PRIMARY KEY (id),
UNIQUE KEY (token),
KEY fk_owner_user_token (owner_user_token),
KEY fk_maybe_parent_folder_token (maybe_parent_folder_token),
KEY index_folders_created_at (created_at),
KEY index_folders_updated_at (updated_at),
KEY index_maybe_deleted_at (maybe_deleted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
@@ -0,0 +1,5 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
DROP TABLE IF EXISTS folder_media_files;
@@ -0,0 +1,27 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
CREATE TABLE folder_media_files (
-- Auto-increment for posterity / row-creation ordering. Not the primary
-- key — the composite (folder_token, media_file_token) is. AUTO_INCREMENT
-- requires its own key, hence the UNIQUE KEY below.
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-- The folder this membership belongs to.
folder_token VARCHAR(32) NOT NULL,
-- The media file in the folder.
media_file_token VARCHAR(32) NOT NULL,
-- When the media file was added to the folder. Rows are hard-deleted
-- when a media file is removed, so there is no `maybe_deleted_at`.
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- INDICES --
PRIMARY KEY (folder_token, media_file_token),
UNIQUE KEY (id),
KEY index_folder_token (folder_token),
KEY index_media_file_token (media_file_token)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
DROP COLUMN platform_type;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
ADD COLUMN platform_type VARCHAR(16) DEFAULT NULL;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE media_files
DROP COLUMN platform_type;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE media_files
ADD COLUMN platform_type VARCHAR(16) DEFAULT NULL;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
DROP COLUMN maybe_external_third_party_cost_credits;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
ADD COLUMN maybe_external_third_party_cost_credits INT(10) UNSIGNED DEFAULT NULL;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
DROP COLUMN maybe_external_third_party_cost_usd_cents;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
ADD COLUMN maybe_external_third_party_cost_usd_cents INT(10) UNSIGNED DEFAULT NULL;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
DROP COLUMN maybe_system_cost_credits;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
ADD COLUMN maybe_system_cost_credits INT(10) UNSIGNED DEFAULT NULL;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
DROP COLUMN maybe_system_cost_usd_cents;
@@ -0,0 +1,6 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE generic_inference_jobs
ADD COLUMN maybe_system_cost_usd_cents INT(10) UNSIGNED DEFAULT NULL;
@@ -0,0 +1,32 @@
-- NB: This is a manually squashed view of all the CREATE and ALTER statements,
-- with comments attached to the fields for centralized documentation.
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
-- N:M mapping between `folders` and `media_files`. Rows are hard-deleted
-- when a media file is removed from a folder — no soft-delete column.
CREATE TABLE folder_media_files (
-- Auto-increment for posterity / row-creation ordering. Not the primary
-- key — the composite (folder_token, media_file_token) is. AUTO_INCREMENT
-- requires its own key, hence the UNIQUE KEY below.
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-- The folder this membership belongs to.
folder_token VARCHAR(32) NOT NULL,
-- The media file in the folder.
media_file_token VARCHAR(32) NOT NULL,
-- When the media file was added to the folder. Rows are hard-deleted
-- when a media file is removed, so there is no `maybe_deleted_at`.
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- INDICES --
PRIMARY KEY (folder_token, media_file_token),
UNIQUE KEY (id),
KEY index_folder_token (folder_token),
KEY index_media_file_token (media_file_token)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
@@ -0,0 +1,59 @@
-- NB: This is a manually squashed view of all the CREATE and ALTER statements,
-- with comments attached to the fields for centralized documentation.
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
CREATE TABLE folders (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-- Effective "primary key" (PUBLIC, used by the API).
token VARCHAR(32) NOT NULL,
-- User-supplied folder name.
name VARCHAR(255) NOT NULL,
-- The user that owns this folder.
owner_user_token VARCHAR(32) NOT NULL,
-- Parent folder for nesting, NULL for top-level folders.
maybe_parent_folder_token VARCHAR(32) DEFAULT NULL,
-- The last four media files added to the folder, in order. These are
-- denormalized for cheap thumbnail-grid rendering on folder cards
-- without a separate fan-out query.
maybe_last_media_file_token_1 VARCHAR(32) DEFAULT NULL,
maybe_last_media_file_token_2 VARCHAR(32) DEFAULT NULL,
maybe_last_media_file_token_3 VARCHAR(32) DEFAULT NULL,
maybe_last_media_file_token_4 VARCHAR(32) DEFAULT NULL,
-- Optional user-chosen cover image (a media file). Overrides the
-- auto-grid thumbnail derived from the last-N media files above.
maybe_cover_image_custom_media_token VARCHAR(32) DEFAULT NULL,
-- Optional user-chosen color tag. Wide enough for "#RRGGBBAA" plus a
-- short named-color fallback.
maybe_color_code VARCHAR(16) DEFAULT NULL,
-- Whether the user has starred / favorited this folder.
has_star BOOLEAN NOT NULL DEFAULT FALSE,
-- ========== TIMESTAMPS ==========
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- Soft-delete timestamp. NULL means the folder is live.
maybe_deleted_at TIMESTAMP NULL,
-- INDICES --
PRIMARY KEY (id),
UNIQUE KEY (token),
KEY fk_owner_user_token (owner_user_token),
KEY fk_maybe_parent_folder_token (maybe_parent_folder_token),
KEY index_folders_created_at (created_at),
KEY index_folders_updated_at (updated_at),
KEY index_maybe_deleted_at (maybe_deleted_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
@@ -56,6 +56,19 @@ CREATE TABLE generic_inference_jobs (
-- service uses.
maybe_external_third_party_id VARCHAR(64) DEFAULT NULL,
-- What the third-party service charges us for the job, in the service's
-- own credit denomination (if it bills in credits).
maybe_external_third_party_cost_credits INT(10) UNSIGNED DEFAULT NULL,
-- What the third-party service charges us for the job, in USD cents.
maybe_external_third_party_cost_usd_cents INT(10) UNSIGNED DEFAULT NULL,
-- What we charge the user for the job, in our own credits.
maybe_system_cost_credits INT(10) UNSIGNED DEFAULT NULL,
-- What we charge the user for the job, in USD cents.
maybe_system_cost_usd_cents INT(10) UNSIGNED DEFAULT NULL,
-- There is an index on this column.
-- NB: See notes on inference_category. This is becoming a problematic field. We're using
-- this to load the container spin-up arguments and dependencies, but the former is being
@@ -208,6 +221,11 @@ CREATE TABLE generic_inference_jobs (
-- Multiple debug_logs rows can share the same event token.
maybe_debug_log_event_token VARCHAR(32) DEFAULT NULL,
-- The platform the enqueuing request came from ('web', 'desktop_app',
-- 'curl', 'python_requests', 'postman'),
-- inferred from the request's User-Agent header.
platform_type VARCHAR(16) DEFAULT NULL,
-- ========== JOB SYSTEM DETAILS ==========
-- Jobs begin as "pending", then transition to other states.
@@ -65,6 +65,12 @@ CREATE TABLE media_files (
-- What service provided the generation (if any).
maybe_generation_provider VARCHAR(16) DEFAULT NULL,
-- The platform the creating request came from ('web', 'desktop_app',
-- 'curl', 'python_requests', 'postman'),
-- inferred from the request's User-Agent header. Copied from the originating
-- generic_inference_jobs row for inference results.
platform_type VARCHAR(16) DEFAULT NULL,
-- For inference that can be tied back to a model, the type of model.
-- There are multiple indices on this column!
-- DO NOT EXPOSE THIS TO USERS VIA THE API, as we may leak secrets in doing so.
@@ -0,0 +1,38 @@
-- NB: This is a manually squashed view of all the CREATE and ALTER statements,
-- with comments attached to the fields for centralized documentation.
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
CREATE TABLE user_email_changes (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-- The user whose email was changed.
user_token VARCHAR(32) NOT NULL,
-- The email address before the change.
old_email VARCHAR(255) NOT NULL,
-- The email address after the change.
new_email VARCHAR(255) NOT NULL,
-- The IP address the change was made from.
-- Wide enough for IPv4/6.
ip_address VARCHAR(40) NOT NULL,
-- The user that performed the change, if known. NULL when the change was
-- performed by the user themselves, by an automated process, or in any
-- other context where there is no acting user.
maybe_changed_by_user_token VARCHAR(32) DEFAULT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- INDICES --
PRIMARY KEY (id),
KEY index_user_token (user_token),
KEY index_old_email (old_email),
KEY index_new_email (new_email),
KEY index_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
@@ -0,0 +1,94 @@
use chrono::{DateTime, Utc};
use serde_derive::{Deserialize, Serialize};
use url::Url;
use utoipa::ToSchema;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_type::MediaFileType;
use tokens::tokens::folders::FolderToken;
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::users::UserToken;
// NB: The "folder media file" list-item shape lives in storyteller_web
// (see `endpoints/folders/media_files/list_folder_media_files_handler.rs`)
// because it embeds `MediaFileCoverImageDetails` and other domain types
// that depend on the request's `MediaDomain` + `ServerEnvironment`.
/// Canonical wire shape for a folder. Used by single-folder GETs, create
/// responses, list rows, and subfolder list rows.
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct FolderInfo {
pub token: FolderToken,
pub name: String,
pub owner_user_token: UserToken,
pub maybe_parent_folder_token: Option<FolderToken>,
/// The four most-recent media files added to the folder, in slot order
/// (the schema stores them as `maybe_last_media_file_token_1..4`).
/// Slots whose media file has been deleted are skipped, so the vec
/// may contain 0-4 entries.
pub last_media_thumbnails: Vec<FolderThumbnail>,
/// User-chosen cover image. When present, the frontend should use this
/// as the folder's primary thumbnail instead of the
/// `last_media_thumbnails` grid.
pub maybe_custom_cover_thumbnail: Option<FolderThumbnail>,
pub maybe_color_code: Option<String>,
pub has_star: bool,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
/// True when `maybe_parent_folder_token` is set but the referenced
/// parent row is missing or soft-deleted.
pub is_orphaned: bool,
}
/// A compact thumbnail descriptor for a media file referenced by a
/// folder (either one of the `last_media_*` slots or the custom cover).
///
/// Intentionally narrower than `MediaLinks` / `CoverImageLinks` — folders
/// only need the bare minimum to render a thumbnail card. The CDN URL is
/// the direct asset link; `maybe_thumbnail_template` carries the resizing
/// template URL (with `{{width}}` / `{{height}}` placeholders) when the
/// media class supports it.
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct FolderThumbnail {
pub token: MediaFileToken,
pub media_class: MediaFileClass,
pub media_type: MediaFileType,
/// Direct CDN URL to the underlying media asset.
pub cdn_url: Url,
/// Resizing template URL (with `{{width}}` / `{{height}}` placeholders)
/// when the media class supports it. `None` for media classes without
/// a thumbnail variant. (Video media files instead have video previews,
/// which, in turn, have their own thumbnail templates.)
pub maybe_thumbnail_template: Option<String>,
/// Video preview images (still and animated gif) for mp4 video files.
/// These are only set for video media files.
pub maybe_video_previews: Option<FolderThumbnailVideoPreviews>,
}
/// Video preview images for a video media file referenced by a folder.
/// Mirrors the shape of `MediaLinks`' video previews, but is its own type
/// so the folder wire shape can evolve independently.
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct FolderThumbnailVideoPreviews {
/// A static single frame preview image of the video.
pub still: Url,
/// An animated gif preview of the video.
pub animated: Url,
/// A template used to construct the still thumbnail URL.
/// Replace the string `{WIDTH}` with the desired width.
pub still_thumbnail_template: String,
/// A template used to construct the animated thumbnail URL.
/// Replace the string `{WIDTH}` with the desired width.
pub animated_thumbnail_template: String,
}
@@ -0,0 +1,116 @@
use serde_derive::{Deserialize, Serialize};
use utoipa::{IntoParams, ToSchema};
use tokens::tokens::folders::FolderToken;
use tokens::tokens::media_files::MediaFileToken;
use crate::folders::common::FolderInfo;
// ── POST /v1/folders/create ──
#[derive(Deserialize, ToSchema)]
pub struct CreateFolderRequest {
pub name: String,
pub maybe_parent_folder_token: Option<FolderToken>,
pub maybe_color_code: Option<String>,
}
#[derive(Serialize, ToSchema)]
pub struct CreateFolderSuccessResponse {
pub success: bool,
pub folder: FolderInfo,
}
// ── GET /v1/folders/list_all ──
#[derive(Deserialize, ToSchema, IntoParams)]
pub struct ListFoldersQueryParams {
pub cursor: Option<String>,
pub limit: Option<u32>,
}
#[derive(Serialize, ToSchema)]
pub struct ListFoldersSuccessResponse {
pub success: bool,
pub folders: Vec<FolderInfo>,
pub maybe_cursor: Option<String>,
}
// ── GET /v1/folders/folder/{folder_token} ──
#[derive(Deserialize, ToSchema)]
pub struct FolderPathInfo {
pub folder_token: FolderToken,
}
#[derive(Serialize, ToSchema)]
pub struct GetFolderSuccessResponse {
pub success: bool,
pub folder: FolderInfo,
}
// ── PUT /v1/folders/folder/{folder_token}/rename ──
#[derive(Deserialize, ToSchema)]
pub struct RenameFolderRequest {
pub new_name: String,
}
#[derive(Serialize, ToSchema)]
pub struct RenameFolderSuccessResponse {
pub success: bool,
}
// ── PUT /v1/folders/folder/{folder_token}/star ──
#[derive(Deserialize, ToSchema)]
pub struct SetFolderStarRequest {
pub has_star: bool,
}
#[derive(Serialize, ToSchema)]
pub struct SetFolderStarSuccessResponse {
pub success: bool,
}
// ── PUT /v1/folders/folder/{folder_token}/color_code ──
#[derive(Deserialize, ToSchema)]
pub struct SetFolderColorCodeRequest {
/// `None` clears the color tag.
pub maybe_color_code: Option<String>,
}
#[derive(Serialize, ToSchema)]
pub struct SetFolderColorCodeSuccessResponse {
pub success: bool,
}
// ── PUT /v1/folders/folder/{folder_token}/cover_image ──
#[derive(Deserialize, ToSchema)]
pub struct SetFolderCoverImageRequest {
/// `None` clears the cover image. If set, the server resolves it to a
/// usable cover-image media file token: image/video media files are
/// used directly; other types fall back to the file's own
/// `maybe_cover_image_media_file_token` (and fail if neither path
/// applies).
pub maybe_media_file_token: Option<MediaFileToken>,
}
#[derive(Serialize, ToSchema)]
pub struct SetFolderCoverImageSuccessResponse {
pub success: bool,
/// The media file token that ended up being stored as the cover image
/// (may differ from the requested token if the server resolved through
/// the file's own cover image). `None` when the cover was cleared.
pub maybe_resolved_cover_media_file_token: Option<MediaFileToken>,
}
// ── DELETE /v1/folders/folder/{folder_token} ──
#[derive(Serialize, ToSchema)]
pub struct DeleteFolderSuccessResponse {
pub success: bool,
}
@@ -0,0 +1,88 @@
use serde_derive::{Deserialize, Serialize};
use utoipa::{IntoParams, ToSchema};
use tokens::tokens::folders::FolderToken;
use tokens::tokens::media_files::MediaFileToken;
// ── GET /v1/folders/media_files/{folder_token} ──
//
// NB: `ListFolderMediaFilesSuccessResponse` and `FolderMediaFileListItem`
// live in `storyteller_web`'s handler because the wire shape embeds
// `MediaFileCoverImageDetails` and `MediaLinks` constructors that depend
// on the request's `MediaDomain` + `ServerEnvironment`.
#[derive(Deserialize, ToSchema)]
pub struct FolderMediaFilesPathInfo {
pub folder_token: FolderToken,
}
#[derive(Deserialize, ToSchema, IntoParams)]
pub struct ListFolderMediaFilesQueryParams {
pub cursor: Option<String>,
pub limit: Option<u32>,
}
// ── PUT /v1/folders/media_files/{folder_token}/bulk_add ──
#[derive(Deserialize, ToSchema)]
pub struct BulkAddFolderMediaFilesRequest {
/// Media files to add to the folder. Tokens that don't exist or are
/// soft-deleted are silently skipped. Already-added rows are no-ops
/// (idempotent via INSERT IGNORE on the composite primary key).
pub media_file_tokens: Vec<MediaFileToken>,
}
#[derive(Serialize, ToSchema)]
pub struct BulkAddFolderMediaFilesSuccessResponse {
pub success: bool,
/// Tokens that pre-existed (existed + not deleted). Already-added rows
/// are included since the operation is idempotent.
pub accepted_media_file_tokens: Vec<MediaFileToken>,
}
// ── PUT /v1/folders/media_files/{folder_token}/bulk_remove ──
#[derive(Deserialize, ToSchema)]
pub struct BulkRemoveFolderMediaFilesRequest {
pub media_file_tokens: Vec<MediaFileToken>,
}
#[derive(Serialize, ToSchema)]
pub struct BulkRemoveFolderMediaFilesSuccessResponse {
pub success: bool,
/// How many membership rows were actually hard-deleted.
pub removed_count: u64,
}
// ── POST /v1/folders/media_files/{folder_token}/bulk_move ──
/// Atomically move the listed media files from `source_folder` to the
/// URL `folder_token` (destination). Idempotent on both sides: tokens
/// that aren't currently in the source are silently skipped, and tokens
/// that are already in the destination stay there.
#[derive(Deserialize, ToSchema)]
pub struct BulkMoveFolderMediaFilesRequest {
pub source_folder: FolderToken,
pub media_file_tokens: Vec<MediaFileToken>,
}
#[derive(Serialize, ToSchema)]
pub struct BulkMoveFolderMediaFilesSuccessResponse {
pub success: bool,
/// Number of membership rows actually deleted from the source folder.
pub removed_from_source_count: u64,
/// Number of membership rows actually inserted into the destination
/// folder. May be lower than the input length because (a) tokens that
/// were already present in the destination don't insert, and (b)
/// tokens whose media file doesn't exist / is soft-deleted are filtered
/// out before the insert.
pub added_to_destination_count: u64,
/// The media file tokens that ended up resident in the destination
/// folder after the move — i.e. the subset of the input that actually
/// referred to live media files. Includes both newly-inserted rows and
/// rows that were already there.
pub accepted_media_file_tokens: Vec<MediaFileToken>,
}
@@ -0,0 +1,4 @@
pub mod common;
pub mod folder;
pub mod media_files;
pub mod subfolder;
@@ -0,0 +1,61 @@
use serde_derive::{Deserialize, Serialize};
use utoipa::{IntoParams, ToSchema};
use tokens::tokens::folders::FolderToken;
use crate::folders::common::FolderInfo;
// ── GET /v1/folders/subfolders/{folder_token} ──
#[derive(Deserialize, ToSchema)]
pub struct SubfolderPathInfo {
pub folder_token: FolderToken,
}
#[derive(Deserialize, ToSchema, IntoParams)]
pub struct ListSubfoldersQueryParams {
pub cursor: Option<String>,
pub limit: Option<u32>,
}
#[derive(Serialize, ToSchema)]
pub struct ListSubfoldersSuccessResponse {
pub success: bool,
pub subfolders: Vec<FolderInfo>,
pub maybe_cursor: Option<String>,
}
// ── PUT /v1/folders/subfolders/{folder_token}/bulk_add ──
#[derive(Deserialize, ToSchema)]
pub struct BulkAddSubfoldersRequest {
/// The folders to reparent under the URL `folder_token`. Tokens that
/// don't exist, aren't owned by the caller, are soft-deleted, or are
/// the parent itself are silently skipped (idempotent).
pub subfolder_tokens: Vec<FolderToken>,
}
#[derive(Serialize, ToSchema)]
pub struct BulkAddSubfoldersSuccessResponse {
pub success: bool,
/// Tokens that were actually accepted (existed + owned + not deleted +
/// not the parent itself). Already-parented tokens are included here
/// since the operation is idempotent.
pub accepted_subfolder_tokens: Vec<FolderToken>,
}
// ── PUT /v1/folders/subfolders/{folder_token}/bulk_remove ──
#[derive(Deserialize, ToSchema)]
pub struct BulkRemoveSubfoldersRequest {
/// Folders to unparent. Only rows currently parented to the URL
/// `folder_token` are affected; others are silently skipped.
pub subfolder_tokens: Vec<FolderToken>,
}
#[derive(Serialize, ToSchema)]
pub struct BulkRemoveSubfoldersSuccessResponse {
pub success: bool,
/// How many rows were actually unparented.
pub removed_count: u64,
}
@@ -2,6 +2,7 @@ pub mod analytics;
pub mod characters;
pub mod common;
pub mod credits;
pub mod folders;
pub mod generate;
pub mod jobs;
pub mod media_file;
@@ -2,5 +2,6 @@ pub mod alerts;
pub mod jobs;
pub mod user;
pub mod user_referrals;
pub mod user_stripe_data;
pub mod wallet_ledger_entries;
pub mod wallets;
@@ -0,0 +1 @@
pub mod moderator_get_user_stripe_customer_ids;
@@ -0,0 +1,43 @@
use enums::common::payments_namespace::PaymentsNamespace;
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::users::UserToken;
use utoipa::ToSchema;
pub const MODERATOR_GET_USER_STRIPE_CUSTOMER_IDS_PATH: &str =
"/v1/moderation/user_stripe_data/{user_token}/customer_ids";
#[derive(Deserialize, ToSchema)]
pub struct ModeratorGetUserStripeCustomerIdsPathInfo {
pub user_token: UserToken,
}
#[derive(Serialize, ToSchema)]
pub struct ModeratorGetUserStripeCustomerIdsResponse {
pub success: bool,
/// All stripe customer ids we have on file for the user, across payments
/// namespaces. A user may have zero or several: a customer link and/or
/// subscriptions per namespace (eg. artcraft), plus legacy fakeyou
/// subscriptions. The same customer id can appear once per source.
pub customer_ids: Vec<ModeratorUserStripeCustomerIdEntry>,
}
#[derive(Serialize, ToSchema)]
pub struct ModeratorUserStripeCustomerIdEntry {
pub stripe_customer_id: String,
pub payments_namespace: PaymentsNamespace,
pub source: ModeratorStripeCustomerIdSource,
/// Link to the customer in the Stripe dashboard for the namespace's account.
pub stripe_dashboard_url: String,
}
/// Which table the customer id was found in.
#[derive(Serialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum ModeratorStripeCustomerIdSource {
/// From the `user_stripe_customer_links` table (1:1 per namespace).
CustomerLink,
/// From the user's rows in the `user_subscriptions` table.
Subscription,
}
@@ -11,9 +11,11 @@ use crate::generate::generate_image::providers::artcraft::midjourney_7::request:
/// | 3 | 19 | 19¢ | (interpolated; Kinovi doesn't expose 3)
/// | 4 | 25 | 25¢ |
///
/// Kinovi-side math: 12 Kinovi credits per Midjourney task; 193 Kinovi
/// credits per USD. Kinovi rounds to nearest cent, so batches 1/2/4 land
/// on 6/12/25. Batch 3 is `ceil((12 × 3 / 193) × 100) = 19`.
/// Kinovi-side math (historical, 22,000-credit package at 193 credits/$1):
/// 12 Kinovi credits per Midjourney task → batches 1/2/4 land on 6/12/25¢;
/// batch 3 is `ceil((12 × 3 / 193) × 100) = 19`. Under the current
/// 525,000-credit package (243 credits/$1) Kinovi costs only 5/10/20¢ —
/// user pricing is intentionally kept at the 193-derived values.
#[derive(Clone, Debug)]
pub struct ArtcraftMidjourney7CostState {
pub num_images: u16,
@@ -127,38 +129,6 @@ mod tests {
}
}
// ── 1:1 cost parity with Kinovi for batches 1/2/4 ──
//
// Kinovi midjourney_7 returns 6/12/25¢ for batches 1/2/4. The artcraft
// provider must match those values byte-for-byte so users pay the same.
mod kinovi_parity {
use super::*;
use crate::generate::generate_image::providers::kinovi::midjourney_7::cost::KinoviMidjourney7CostState;
use seedance2pro_client::generate::image::generate_midjourney_v7::KinoviMidjourneyBatchCount;
#[test]
fn batch_1_matches_kinovi() {
let kinovi = KinoviMidjourney7CostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
assert_eq!(cost_cents(1), kinovi.cost_in_usd_cents.unwrap());
}
#[test]
fn batch_2_matches_kinovi() {
let kinovi = KinoviMidjourney7CostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
assert_eq!(cost_cents(2), kinovi.cost_in_usd_cents.unwrap());
}
#[test]
fn batch_4_matches_kinovi() {
let kinovi = KinoviMidjourney7CostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
assert_eq!(cost_cents(4), kinovi.cost_in_usd_cents.unwrap());
}
}
// ── Monotonicity ──
#[test]
@@ -82,32 +82,4 @@ mod tests {
}
}
// ── 1:1 cost parity with Kinovi 7-niji ──
mod kinovi_parity {
use super::*;
use crate::generate::generate_image::providers::kinovi::midjourney_7_niji::cost::KinoviMidjourney7NijiCostState;
use seedance2pro_client::generate::image::generate_midjourney_v7_niji::KinoviMidjourneyBatchCount;
#[test]
fn batch_1_matches_kinovi() {
let kinovi = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
assert_eq!(cost_cents(1), kinovi.cost_in_usd_cents.unwrap());
}
#[test]
fn batch_2_matches_kinovi() {
let kinovi = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
assert_eq!(cost_cents(2), kinovi.cost_in_usd_cents.unwrap());
}
#[test]
fn batch_4_matches_kinovi() {
let kinovi = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
assert_eq!(cost_cents(4), kinovi.cost_in_usd_cents.unwrap());
}
}
}
@@ -82,32 +82,4 @@ mod tests {
}
}
// ── 1:1 cost parity with Kinovi v8 ──
mod kinovi_parity {
use super::*;
use crate::generate::generate_image::providers::kinovi::midjourney_8::cost::KinoviMidjourney8CostState;
use seedance2pro_client::generate::image::generate_midjourney_v8::KinoviMidjourneyBatchCount;
#[test]
fn batch_1_matches_kinovi() {
let kinovi = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
assert_eq!(cost_cents(1), kinovi.cost_in_usd_cents.unwrap());
}
#[test]
fn batch_2_matches_kinovi() {
let kinovi = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
assert_eq!(cost_cents(2), kinovi.cost_in_usd_cents.unwrap());
}
#[test]
fn batch_4_matches_kinovi() {
let kinovi = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
assert_eq!(cost_cents(4), kinovi.cost_in_usd_cents.unwrap());
}
}
}
@@ -37,8 +37,9 @@ impl KinoviMidjourney7CostState {
reference_image_urls: None,
};
let cost_in_credits = pricing_request.estimate_credits() as u64;
let cost_in_usd_cents = pricing_request.estimate_cost_in_usd_cents();
let costs = pricing_request.calculate_costs();
let cost_in_credits = costs.kinovi_credits;
let cost_in_usd_cents = costs.usd_cents_rounded_up;
ImageGenerationCostEstimate {
cost_in_credits: Some(cost_in_credits),
@@ -85,27 +86,27 @@ mod tests {
}
}
// ── USD pricing (193 credits per dollar; rounded) ──
// ── USD pricing (243 credits per dollar; rounded up) ──
mod usd {
use super::*;
#[test]
fn batch_one_is_six_cents() {
// 12 / 193 × 100 = 6.21 → 6¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::One), 6);
fn batch_one_is_five_cents() {
// 12/243 × 100 = 4.94 → 5¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::One), 5); // rounds UP
}
#[test]
fn batch_two_is_twelve_cents() {
// 24 / 193 × 100 = 12.44 → 12¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::Two), 12);
fn batch_two_is_ten_cents() {
// 24/243 × 100 = 9.88 → 10¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::Two), 10); // rounds UP
}
#[test]
fn batch_four_is_twentyfive_cents() {
// 48 / 193 × 100 = 24.87 → 25¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::Four), 25);
fn batch_four_is_twenty_cents() {
// 48/243 × 100 = 19.75 → 20¢
assert_eq!(usd_cents_for(KinoviMidjourneyBatchCount::Four), 20);
}
}
@@ -35,8 +35,9 @@ impl KinoviMidjourney7NijiCostState {
reference_image_urls: None,
};
let cost_in_credits = pricing_request.estimate_credits() as u64;
let cost_in_usd_cents = pricing_request.estimate_cost_in_usd_cents();
let costs = pricing_request.calculate_costs();
let cost_in_credits = costs.kinovi_credits;
let cost_in_usd_cents = costs.usd_cents_rounded_up;
ImageGenerationCostEstimate {
cost_in_credits: Some(cost_in_credits),
@@ -55,11 +56,11 @@ mod tests {
use super::*;
#[test]
fn batch_one_is_twelve_credits_and_six_cents() {
fn batch_one_is_twelve_credits_and_five_cents() {
let cost = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(12));
assert_eq!(cost.cost_in_usd_cents, Some(6));
assert_eq!(cost.cost_in_usd_cents, Some(5)); // 1200/243 = 4.94 -> rounds UP
}
#[test]
@@ -67,7 +68,7 @@ mod tests {
let cost = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(24));
assert_eq!(cost.cost_in_usd_cents, Some(12));
assert_eq!(cost.cost_in_usd_cents, Some(10)); // 2400/243 = 9.88 -> rounds UP
}
#[test]
@@ -75,7 +76,7 @@ mod tests {
let cost = KinoviMidjourney7NijiCostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(48));
assert_eq!(cost.cost_in_usd_cents, Some(25));
assert_eq!(cost.cost_in_usd_cents, Some(20));
}
#[test]
@@ -35,8 +35,9 @@ impl KinoviMidjourney8CostState {
reference_image_urls: None,
};
let cost_in_credits = pricing_request.estimate_credits() as u64;
let cost_in_usd_cents = pricing_request.estimate_cost_in_usd_cents();
let costs = pricing_request.calculate_costs();
let cost_in_credits = costs.kinovi_credits;
let cost_in_usd_cents = costs.usd_cents_rounded_up;
ImageGenerationCostEstimate {
cost_in_credits: Some(cost_in_credits),
@@ -55,11 +56,11 @@ mod tests {
use super::*;
#[test]
fn batch_one_is_twelve_credits_and_six_cents() {
fn batch_one_is_twelve_credits_and_five_cents() {
let cost = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::One }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(12));
assert_eq!(cost.cost_in_usd_cents, Some(6));
assert_eq!(cost.cost_in_usd_cents, Some(5)); // 1200/243 = 4.94 -> rounds UP
}
#[test]
@@ -67,7 +68,7 @@ mod tests {
let cost = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::Two }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(24));
assert_eq!(cost.cost_in_usd_cents, Some(12));
assert_eq!(cost.cost_in_usd_cents, Some(10)); // 2400/243 = 9.88 -> rounds UP
}
#[test]
@@ -75,6 +76,6 @@ mod tests {
let cost = KinoviMidjourney8CostState { batch_count: KinoviMidjourneyBatchCount::Four }
.estimate_cost();
assert_eq!(cost.cost_in_credits, Some(48));
assert_eq!(cost.cost_in_usd_cents, Some(25));
assert_eq!(cost.cost_in_usd_cents, Some(20));
}
}

Some files were not shown because too many files have changed in this diff Show More